diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json new file mode 100644 index 0000000..0a7f24c --- /dev/null +++ b/dev/.documenter-siteinfo.json @@ -0,0 +1 @@ +{"documenter":{"julia_version":"1.9.3","generation_timestamp":"2023-09-26T01:25:09","documenter_version":"1.0.1"}} \ No newline at end of file diff --git a/dev/api/momentclosure_api/index.html b/dev/api/momentclosure_api/index.html index 573a4dd..bd37bfe 100644 --- a/dev/api/momentclosure_api/index.html +++ b/dev/api/momentclosure_api/index.html @@ -1,6 +1,6 @@ -MomentClosure.jl API · MomentClosure.jl

MomentClosure.jl API

Model definition

MomentClosure is fully compatible with reaction network models defined using Catalyst and stored as a ModelingToolkit.ReactionSystem. Note that previously we had implemented our own ReactionSystemMod, that allowed us to consider systems containing reactions which products are independent geometrically distributed random variables. However, this is now deprecated as Catalyst has added support for such parameteric stoichiometries offering a much more complete and efficient feature set.

Basic model properties

Moreover, we include a couple of tiny extensions to the Catalyst API:

MomentClosure.propensitiesFunction
propensities(rn::Union{ReactionSystem, ReactionSystemMod}; combinatoric_ratelaws=true)

Return a vector of propensity functions of all reactions in the given ReactionSystem.

Notes:

  • combinatoric_ratelaws=true uses binomials in calculating the propensity functions of a ReactionSystem, see the notes for ModelingToolkit.jumpratelaw.
source
MomentClosure.get_stoichiometryFunction
get_stoichiometry(rn::ReactionSystem, smap::AbstractDict)

Return the net stoichiometry matrix using the specified mapping of species to their indices.

Notes:

source

Moment Equations

MomentClosure.generate_raw_moment_eqsFunction
generate_raw_moment_eqs(rn::ReactionSystem, m_order::Int;
-                        langevin::Bool=false, combinatoric_ratelaws::Bool=true, smap=speciesmap(rn))

Given a ReactionSystem return the RawMomentEquations of the system generated up to m_order.

Notes:

  • The expansion order $q$, denoted by q_order throughout the docs, is automatically determined from the given polynomial form of the propensity functions, see the tutorial and the theory section for more details on how q_order is obtained.
  • if langevin=true, instead of the Chemical Master Equation the Chemical Langevin Equation (diffusion approximation) is considered, and the moment equations are constructed from the corresponding SDE formulation.
  • combinatoric_ratelaws=true uses binomials in calculating the propensity functions of a ReactionSystem, see the notes for ModelingToolkit.jumpratelaw. Note that this field is irrelevant using ReactionSystemMod as then the propensities are defined directly by the user.
  • smap sets the variable ordering in the moment equations (which index corresponds to which species in the reaction network). By default, this is consistent with the internal system ordering accessible with Catalyst.speciesmap.
source
generate_raw_moment_eqs(sys::SDESystem, m_order::Int)

Given an SDESystem, return the RawMomentEquations of the system generated up to m_order.

source
MomentClosure.RawMomentEquationsType
struct RawMomentEquations <: MomentClosure.MomentEquations

Raw moment equations generated for the given system plus a number of helper parameters (used internally).

Fields

  • odes: ModelingToolkit.ODESystem consisting of the time-evolution equations of raw moments.

  • μ: Symbolic variables defining the raw moments.

  • N: Number of species within the system.

  • m_order: Order of moment equations.

  • q_order: Expansion order.

  • iter_all: Vector of all index combinations up to q_order.

  • iter_m: Vector of all index combinations up to m_order.

  • iter_q: Vector of all index combinations of order greater than m_order up to q_order.

  • iter_1: Vector of index combinations of order 1.

source
MomentClosure.generate_central_moment_eqsFunction
generate_central_moment_eqs(rn::ReactionSystem, m_order::Int, q_order::Int=0;
-                            langevin::Bool=false, combinatoric_ratelaws::Bool=true, smap=speciesmap(rn))

Given a ReactionSystem return the CentralMomentEquations of the system generated up to m_order.

Notes:

  • if q_order is not specified by the user, it is assumed that the reaction network contains only polynomial propensity functions and hence q_order is determined automatically as in generate_raw_moment_eqs. However, q_order must be specified if non-polynomial propensities are included. Note that the expansion order $q$ denotes the highest order of central moments which will be included in the ODEs (due to the Taylor expansion of propensity functions).
  • if langevin=true, instead of the Chemical Master Equation the Chemical Langevin Equation (diffusion approximation) is considered, and the moment equations are constructed from the corresponding SDE formulation.
  • combinatoric_ratelaws=true uses binomials in calculating the propensity functions of a ReactionSystem, see the notes for ModelingToolkit.jumpratelaw. Note that this field is irrelevant using ReactionSystemMod as then the propensities are defined directly by the user.
  • smap sets the variable ordering in the moment equations (which index corresponds to which species in the reaction network). By default, this is consistent with the internal system ordering accessible with Catalyst.speciesmap.
source
generate_central_moment_eqs(sys::SDESystem, m_order::Int, q_order::Int=0)

Given an SDESystem, return the CentralMomentEquations of the system generated up to m_order.

source
MomentClosure.CentralMomentEquationsType
struct CentralMomentEquations <: MomentClosure.MomentEquations

Central moment equations generated for the given system plus a number of helper parameters (used internally).

Fields

  • odes: ModelingToolkit.ODESystem consisting of the time-evolution equations of central moments.

  • μ: Symbolic variables defining the means.

  • M: Symbolic variables defining the central moments.

  • N: Number of species within the system.

  • m_order: Order of moment equations.

  • q_order: Expansion order.

  • iter_all: Vector of all index combinations up to q_order.

  • iter_m: Vector of all index combinations up to m_order.

  • iter_q: Vector of all index combinations of order greater than m_order up to q_order.

  • iter_1: Vector of index combinations of order 1.

source
MomentClosure.bernoulli_moment_eqsFunction
bernoulli_moment_eqs(sys::MomentEquations, binary_vars::Array{Int,1})

Given MomentEquations and an array of indices specifying the species which molecule numbers are binary variables (either 0 or 1), apply identities of Bernoulli variables to remove the redundant ODEs and return the cleaned up MomentEquations. See here for example usage.

source

Moment Closure

MomentClosure.moment_closureFunction
moment_closure(sys::MomentEquations, closure::String, binary_vars::Array{Int,1}=Int[])

Given MomentEquations, apply the specified moment closure approximation and return the ClosedMomentEquations.

The supported closure options are:

Notes

  • binary_vars must be specified for conditional closures as an array of indices of all species (as in Catalyst.speciesmap) which molecule number is a Bernoulli variable. Although not necessary for other closures, specifying binary_vars is recommended as the properties of Bernoulli variables will be used to remove the redundant moment equations and simplify the expressions, which can significantly improve numerical stability.
source
MomentClosure.ClosedMomentEquationsType
struct ClosedMomentEquations <: MomentClosure.MomentEquations

Closed moment equations and the corresponding closure functions.

Fields

  • odes: ModelingToolkit.ODESystem consisting of the time-evolution equations of closed moments.

  • closure: Dictionary of moment closure functions for each higher order moment.

  • open_eqs: Original raw or central moment equations (before closure was applied).

source
MomentClosure.deterministic_ICFunction
deterministic_IC(u₀::Array{T, 1}, eqs::MomentEquations) where T<:Real

Given an array of initial molecule numbers and the corresponding moment equations, return a mapping of each moment to its initial value under deterministic initial conditions.

Notes

  • The means are set to initial molecule numbers (as they take the values specified in u₀ with probability one). The higher order raw moments are products of the corresponding powers of the means whereas the higher order central moments are simply zero.
  • The ordering of u₀ elements must be consistent with the ordering of species in the corresponding reaction system (can be checked with the Catalyst.speciesmap function).
  • As higher-order moment functions under log-normal, gamma, derivative matching and the conditional closures involve moments raised to negative powers, setting initial molecule numbers of certain species to zeros will result in NaN errors when solving the ODEs (the specifics depend on the system at hand).
source

Displaying Equations and Closures

The generated moment equations can be converted into LaTeX expressions using Latexify as:

using Latexify
-latexify(moment_eqs)

A ModelingToolkit.ODESystem (saved as moment_eqs.odes) can also be passed to latexify function directly but the output will be different as we apply additional formatting to the symbolic expressions.

Given ClosedMomentEquations, the closure functions can be visualised in the same way by adding a :closure argument:

latexify(moment_eqs, :closure)

Note that this will print out only those higher order moments which are found in the given moment equations. It is possible to print the closure functions of all higher order moments using print_all=true argument:

latexify(moment_eqs, :closure, print_all=true)

Linear Mapping Approximation

MomentClosure.linear_mapping_approximationFunction
  linear_mapping_approximation(rn_nonlinear::T, rn_linear::T, binary_vars::Array{Int,1}=Int[], m_order::Int=0;
-                               combinatoric_ratelaws = true) where T <: ReactionSystem

Given a nonlinear ReactionSystem and an equivalent linear ReactionSystem, perform the Linear Mapping Approximation (LMA) and return the corresponding linear RawMomentEquations of the system as well as a Dictionary of reaction parameter substitutions obtained using LMA that are used to generate the moment equations. See the LMA theory section for more details.

Notes:

  • rn_nonlinear and rn_linear must be identical in layout in order to be interpreted correctly, and the nonlinear reactions contained in rn_nonlinear must all be linearised in rn_linear with rate coefficients updated accordingly. Although this requires a lot of manual input, automating the linearisation further is difficult due to arbitrary choices that may be mane in constructing the reaction networks.
  • binary_vars must be specified for conditional closures as an array of indices of all species (as in Catalyst.speciesmap) which molecule number is a Bernoulli variable. Note that rn_nonlinear and rn_linear may internally order the species differently: binary_vars must be consistent with the ordering in the nonlinear network.
  • By default the moment equations will be generated up to the order determined by the degree of nonlinearity of the nonlinear system's reactions. However, if higher order moment information is required, the optional m_order argument may be provided to increase the expansion order manually.
  • combinatoric_ratelaws=true uses binomials in calculating the propensity functions of a ReactionSystem, see the notes for ModelingToolkit.jumpratelaw.
source

Stochastic Simulation Utilities

We provide provides functions for higher-order moment extraction from SSA and FSP data:

MomentClosure.get_raw_momentsFunction
get_raw_moments(sol::EnsembleSolution, order::Int; naive::Bool=true, b::Int=2)

Given an EnsembleSolution of DifferentialEquations ensemble simulation, return a Dictionary of raw moments computed up to the specified order at each time step.

Notes

  • For example, the dictionary key (2,0,1) maps to an array containing the values of the raw moment $μ_{201}$ at each time step.
  • It is assumed that the time steps are all at the same time point for all trajectories (i.e., fixed dt used by the integrator or values were saved using saveat, as discussed here).
  • Moments are computed using Cumulants.jl internally. The naive algorithm of moment tensor calculations (naive=true) is usually faster for small systems but the proposed novel algorithm (naive=false) should be more efficient in case of many marginal variables. The block size b can also be specified for the novel algorithm and may have a significant effect on its performance.
  • Only useful if higher order moments are needed: DifferentialEquations has a number of far more efficient and flexible ensemble statistics functions for means, variances and correlations, see this tutorial for more details.
source
MomentClosure.get_moments_FSPFunction
get_moments_FSP(sol::ODESolution, order::Int, moment_type::String)

Given an ODESolution obtained using FiniteStateProjection.jl, return a Dictionary of moments computed up to the specified order at each time step. Here, moment_type specifies the type of moments to be computed: available options are raw, central or cumulant.

Notes

  • The ODESolution represents the time-evolution of the probability density function that is the solution of the Chemical Master Equation approximated using Finite State Projection algorithms. See the documentation of FiniteStateProjection.jl for more information.
source
+MomentClosure.jl API · MomentClosure.jl

MomentClosure.jl API

Model definition

MomentClosure is fully compatible with reaction network models defined using Catalyst and stored as a ModelingToolkit.ReactionSystem. Note that previously we had implemented our own ReactionSystemMod, that allowed us to consider systems containing reactions which products are independent geometrically distributed random variables. However, this is now deprecated as Catalyst has added support for such parameteric stoichiometries offering a much more complete and efficient feature set.

Basic model properties

Moreover, we include a couple of tiny extensions to the Catalyst API:

MomentClosure.propensitiesFunction
propensities(rn::Union{ReactionSystem, ReactionSystemMod}; combinatoric_ratelaws=true)

Return a vector of propensity functions of all reactions in the given ReactionSystem.

Notes:

  • combinatoric_ratelaws=true uses binomials in calculating the propensity functions of a ReactionSystem, see the notes for ModelingToolkit.jumpratelaw.
source
MomentClosure.get_stoichiometryFunction
get_stoichiometry(rn::ReactionSystem, smap::AbstractDict)

Return the net stoichiometry matrix using the specified mapping of species to their indices.

Notes:

source

Moment Equations

MomentClosure.generate_raw_moment_eqsFunction
generate_raw_moment_eqs(rn::ReactionSystem, m_order::Int;
+                        langevin::Bool=false, combinatoric_ratelaws::Bool=true, smap=speciesmap(rn))

Given a ReactionSystem return the RawMomentEquations of the system generated up to m_order.

Notes:

  • The expansion order $q$, denoted by q_order throughout the docs, is automatically determined from the given polynomial form of the propensity functions, see the tutorial and the theory section for more details on how q_order is obtained.
  • if langevin=true, instead of the Chemical Master Equation the Chemical Langevin Equation (diffusion approximation) is considered, and the moment equations are constructed from the corresponding SDE formulation.
  • combinatoric_ratelaws=true uses binomials in calculating the propensity functions of a ReactionSystem, see the notes for ModelingToolkit.jumpratelaw. Note that this field is irrelevant using ReactionSystemMod as then the propensities are defined directly by the user.
  • smap sets the variable ordering in the moment equations (which index corresponds to which species in the reaction network). By default, this is consistent with the internal system ordering accessible with Catalyst.speciesmap.
source
generate_raw_moment_eqs(sys::SDESystem, m_order::Int)

Given an SDESystem, return the RawMomentEquations of the system generated up to m_order.

source
MomentClosure.RawMomentEquationsType
struct RawMomentEquations <: MomentClosure.MomentEquations

Raw moment equations generated for the given system plus a number of helper parameters (used internally).

Fields

  • odes: ModelingToolkit.ODESystem consisting of the time-evolution equations of raw moments.

  • μ: Symbolic variables defining the raw moments.

  • N: Number of species within the system.

  • m_order: Order of moment equations.

  • q_order: Expansion order.

  • iter_all: Vector of all index combinations up to q_order.

  • iter_m: Vector of all index combinations up to m_order.

  • iter_q: Vector of all index combinations of order greater than m_order up to q_order.

  • iter_1: Vector of index combinations of order 1.

source
MomentClosure.generate_central_moment_eqsFunction
generate_central_moment_eqs(rn::ReactionSystem, m_order::Int, q_order::Int=0;
+                            langevin::Bool=false, combinatoric_ratelaws::Bool=true, smap=speciesmap(rn))

Given a ReactionSystem return the CentralMomentEquations of the system generated up to m_order.

Notes:

  • if q_order is not specified by the user, it is assumed that the reaction network contains only polynomial propensity functions and hence q_order is determined automatically as in generate_raw_moment_eqs. However, q_order must be specified if non-polynomial propensities are included. Note that the expansion order $q$ denotes the highest order of central moments which will be included in the ODEs (due to the Taylor expansion of propensity functions).
  • if langevin=true, instead of the Chemical Master Equation the Chemical Langevin Equation (diffusion approximation) is considered, and the moment equations are constructed from the corresponding SDE formulation.
  • combinatoric_ratelaws=true uses binomials in calculating the propensity functions of a ReactionSystem, see the notes for ModelingToolkit.jumpratelaw. Note that this field is irrelevant using ReactionSystemMod as then the propensities are defined directly by the user.
  • smap sets the variable ordering in the moment equations (which index corresponds to which species in the reaction network). By default, this is consistent with the internal system ordering accessible with Catalyst.speciesmap.
source
generate_central_moment_eqs(sys::SDESystem, m_order::Int, q_order::Int=0)

Given an SDESystem, return the CentralMomentEquations of the system generated up to m_order.

source
MomentClosure.CentralMomentEquationsType
struct CentralMomentEquations <: MomentClosure.MomentEquations

Central moment equations generated for the given system plus a number of helper parameters (used internally).

Fields

  • odes: ModelingToolkit.ODESystem consisting of the time-evolution equations of central moments.

  • μ: Symbolic variables defining the means.

  • M: Symbolic variables defining the central moments.

  • N: Number of species within the system.

  • m_order: Order of moment equations.

  • q_order: Expansion order.

  • iter_all: Vector of all index combinations up to q_order.

  • iter_m: Vector of all index combinations up to m_order.

  • iter_q: Vector of all index combinations of order greater than m_order up to q_order.

  • iter_1: Vector of index combinations of order 1.

source
MomentClosure.bernoulli_moment_eqsFunction
bernoulli_moment_eqs(sys::MomentEquations, binary_vars::Array{Int,1})

Given MomentEquations and an array of indices specifying the species which molecule numbers are binary variables (either 0 or 1), apply identities of Bernoulli variables to remove the redundant ODEs and return the cleaned up MomentEquations. See here for example usage.

source

Moment Closure

MomentClosure.moment_closureFunction
moment_closure(sys::MomentEquations, closure::String, binary_vars::Array{Int,1}=Int[])

Given MomentEquations, apply the specified moment closure approximation and return the ClosedMomentEquations.

The supported closure options are:

Notes

  • binary_vars must be specified for conditional closures as an array of indices of all species (as in Catalyst.speciesmap) which molecule number is a Bernoulli variable. Although not necessary for other closures, specifying binary_vars is recommended as the properties of Bernoulli variables will be used to remove the redundant moment equations and simplify the expressions, which can significantly improve numerical stability.
source
MomentClosure.ClosedMomentEquationsType
struct ClosedMomentEquations <: MomentClosure.MomentEquations

Closed moment equations and the corresponding closure functions.

Fields

  • odes: ModelingToolkit.ODESystem consisting of the time-evolution equations of closed moments.

  • closure: Dictionary of moment closure functions for each higher order moment.

  • open_eqs: Original raw or central moment equations (before closure was applied).

source
MomentClosure.deterministic_ICFunction
deterministic_IC(u₀::Array{T, 1}, eqs::MomentEquations) where T<:Real

Given an array of initial molecule numbers and the corresponding moment equations, return a mapping of each moment to its initial value under deterministic initial conditions.

Notes

  • The means are set to initial molecule numbers (as they take the values specified in u₀ with probability one). The higher order raw moments are products of the corresponding powers of the means whereas the higher order central moments are simply zero.
  • The ordering of u₀ elements must be consistent with the ordering of species in the corresponding reaction system (can be checked with the Catalyst.speciesmap function).
  • As higher-order moment functions under log-normal, gamma, derivative matching and the conditional closures involve moments raised to negative powers, setting initial molecule numbers of certain species to zeros will result in NaN errors when solving the ODEs (the specifics depend on the system at hand).
source

Displaying Equations and Closures

The generated moment equations can be converted into LaTeX expressions using Latexify as:

using Latexify
+latexify(moment_eqs)

A ModelingToolkit.ODESystem (saved as moment_eqs.odes) can also be passed to latexify function directly but the output will be different as we apply additional formatting to the symbolic expressions.

Given ClosedMomentEquations, the closure functions can be visualised in the same way by adding a :closure argument:

latexify(moment_eqs, :closure)

Note that this will print out only those higher order moments which are found in the given moment equations. It is possible to print the closure functions of all higher order moments using print_all=true argument:

latexify(moment_eqs, :closure, print_all=true)

Linear Mapping Approximation

MomentClosure.linear_mapping_approximationFunction
  linear_mapping_approximation(rn_nonlinear::T, rn_linear::T, binary_vars::Array{Int,1}=Int[], m_order::Int=0;
+                               combinatoric_ratelaws = true) where T <: ReactionSystem

Given a nonlinear ReactionSystem and an equivalent linear ReactionSystem, perform the Linear Mapping Approximation (LMA) and return the corresponding linear RawMomentEquations of the system as well as a Dictionary of reaction parameter substitutions obtained using LMA that are used to generate the moment equations. See the LMA theory section for more details.

Notes:

  • rn_nonlinear and rn_linear must be identical in layout in order to be interpreted correctly, and the nonlinear reactions contained in rn_nonlinear must all be linearised in rn_linear with rate coefficients updated accordingly. Although this requires a lot of manual input, automating the linearisation further is difficult due to arbitrary choices that may be mane in constructing the reaction networks.
  • binary_vars must be specified for conditional closures as an array of indices of all species (as in Catalyst.speciesmap) which molecule number is a Bernoulli variable. Note that rn_nonlinear and rn_linear may internally order the species differently: binary_vars must be consistent with the ordering in the nonlinear network.
  • By default the moment equations will be generated up to the order determined by the degree of nonlinearity of the nonlinear system's reactions. However, if higher order moment information is required, the optional m_order argument may be provided to increase the expansion order manually.
  • combinatoric_ratelaws=true uses binomials in calculating the propensity functions of a ReactionSystem, see the notes for ModelingToolkit.jumpratelaw.
source

Stochastic Simulation Utilities

We provide provides functions for higher-order moment extraction from SSA and FSP data:

MomentClosure.get_raw_momentsFunction
get_raw_moments(sol::EnsembleSolution, order::Int; naive::Bool=true, b::Int=2)

Given an EnsembleSolution of DifferentialEquations ensemble simulation, return a Dictionary of raw moments computed up to the specified order at each time step.

Notes

  • For example, the dictionary key (2,0,1) maps to an array containing the values of the raw moment $μ_{201}$ at each time step.
  • It is assumed that the time steps are all at the same time point for all trajectories (i.e., fixed dt used by the integrator or values were saved using saveat, as discussed here).
  • Moments are computed using Cumulants.jl internally. The naive algorithm of moment tensor calculations (naive=true) is usually faster for small systems but the proposed novel algorithm (naive=false) should be more efficient in case of many marginal variables. The block size b can also be specified for the novel algorithm and may have a significant effect on its performance.
  • Only useful if higher order moments are needed: DifferentialEquations has a number of far more efficient and flexible ensemble statistics functions for means, variances and correlations, see this tutorial for more details.
source
MomentClosure.get_moments_FSPFunction
get_moments_FSP(sol::ODESolution, order::Int, moment_type::String)

Given an ODESolution obtained using FiniteStateProjection.jl, return a Dictionary of moments computed up to the specified order at each time step. Here, moment_type specifies the type of moments to be computed: available options are raw, central or cumulant.

Notes

  • The ODESolution represents the time-evolution of the probability density function that is the solution of the Chemical Master Equation approximated using Finite State Projection algorithms. See the documentation of FiniteStateProjection.jl for more information.
source
diff --git a/dev/assets/documenter.js b/dev/assets/documenter.js index 32e27c5..6d44ceb 100644 --- a/dev/assets/documenter.js +++ b/dev/assets/documenter.js @@ -1,14 +1,14 @@ // Generated by Documenter.jl requirejs.config({ paths: { - 'highlight-julia': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/languages/julia.min', + 'highlight-julia': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/languages/julia.min', 'headroom': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.12.0/headroom.min', - 'jqueryui': 'https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min', - 'jquery': 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min', - 'mathjax': 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-AMS_HTML', + 'jqueryui': 'https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min', + 'minisearch': 'https://cdn.jsdelivr.net/npm/minisearch@6.1.0/dist/umd/index.min', + 'jquery': 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min', 'headroom-jquery': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.12.0/jQuery.headroom.min', - 'highlight': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min', - 'highlight-julia-repl': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/languages/julia-repl.min', + 'highlight': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min', + 'highlight-julia-repl': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/languages/julia-repl.min', }, shim: { "highlight-julia": { @@ -16,9 +16,6 @@ requirejs.config({ "highlight" ] }, - "mathjax": { - "exports": "MathJax" - }, "headroom-jquery": { "deps": [ "jquery", @@ -33,19 +30,14 @@ requirejs.config({ } }); //////////////////////////////////////////////////////////////////////////////// -require(['mathjax'], function(MathJax) { -MathJax.Hub.Config({ - "jax": [ - "input/TeX", - "output/HTML-CSS", - "output/NativeMML" - ], - "TeX": { - "equationNumbers": { - "autoNumber": "AMS" - } - }, - "tex2jax": { +require([], function() { +window.MathJax = { + "tex": { + "packages": [ + "base", + "ams", + "autoload" + ], "inlineMath": [ [ "$", @@ -56,21 +48,21 @@ MathJax.Hub.Config({ "\\)" ] ], - "processEscapes": true + "tags": "ams" }, - "config": [ - "MMLorHTML.js" - ], - "extensions": [ - "MathMenu.js", - "MathZoom.js", - "TeX/AMSmath.js", - "TeX/AMSsymbols.js", - "TeX/autobold.js", - "TeX/autoload-all.js" - ] + "options": { + "ignoreHtmlClass": "tex2jax_ignore", + "processHtmlClass": "tex2jax_process" + } } -); +; + +(function () { + var script = document.createElement('script'); + script.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-svg.js'; + script.async = true; + document.head.appendChild(script); +})(); }) //////////////////////////////////////////////////////////////////////////////// @@ -79,13 +71,75 @@ $(document).ready(function() { hljs.highlightAll(); }) +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + +var isExpanded = true; + +$(document).on("click", ".docstring header", function () { + let articleToggleTitle = "Expand docstring"; + + if ($(this).siblings("section").is(":visible")) { + $(this) + .find(".docstring-article-toggle-button") + .removeClass("fa-chevron-down") + .addClass("fa-chevron-right"); + } else { + $(this) + .find(".docstring-article-toggle-button") + .removeClass("fa-chevron-right") + .addClass("fa-chevron-down"); + + articleToggleTitle = "Collapse docstring"; + } + + $(this) + .find(".docstring-article-toggle-button") + .prop("title", articleToggleTitle); + $(this).siblings("section").slideToggle(); +}); + +$(document).on("click", ".docs-article-toggle-button", function () { + let articleToggleTitle = "Expand docstring"; + let navArticleToggleTitle = "Expand all docstrings"; + + if (isExpanded) { + $(this).removeClass("fa-chevron-up").addClass("fa-chevron-down"); + $(".docstring-article-toggle-button") + .removeClass("fa-chevron-down") + .addClass("fa-chevron-right"); + + isExpanded = false; + + $(".docstring section").slideUp(); + } else { + $(this).removeClass("fa-chevron-down").addClass("fa-chevron-up"); + $(".docstring-article-toggle-button") + .removeClass("fa-chevron-right") + .addClass("fa-chevron-down"); + + isExpanded = true; + articleToggleTitle = "Collapse docstring"; + navArticleToggleTitle = "Collapse all docstrings"; + + $(".docstring section").slideDown(); + } + + $(this).prop("title", navArticleToggleTitle); + $(".docstring-article-toggle-button").prop("title", articleToggleTitle); +}); + }) //////////////////////////////////////////////////////////////////////////////// require([], function() { function addCopyButtonCallbacks() { for (const el of document.getElementsByTagName("pre")) { const button = document.createElement("button"); - button.classList.add("copy-button", "fas", "fa-copy"); + button.classList.add("copy-button", "fa-solid", "fa-copy"); + button.setAttribute("aria-label", "Copy this code block"); + button.setAttribute("title", "Copy"); + el.appendChild(button); const success = function () { @@ -94,7 +148,7 @@ function addCopyButtonCallbacks() { }; const failure = function () { - button.classList.add("error", "fa-times"); + button.classList.add("error", "fa-xmark"); button.classList.remove("fa-copy"); }; @@ -103,7 +157,7 @@ function addCopyButtonCallbacks() { setTimeout(function () { button.classList.add("fa-copy"); - button.classList.remove("success", "fa-check", "fa-times"); + button.classList.remove("success", "fa-check", "fa-xmark"); }, 5000); }); } @@ -147,29 +201,418 @@ require(['jquery', 'headroom', 'headroom-jquery'], function($, Headroom) { // Manages the top navigation bar (hides it when the user starts scrolling down on the // mobile). window.Headroom = Headroom; // work around buggy module loading? -$(document).ready(function() { - $('#documenter .docs-navbar').headroom({ - "tolerance": {"up": 10, "down": 10}, +$(document).ready(function () { + $("#documenter .docs-navbar").headroom({ + tolerance: { up: 10, down: 10 }, }); +}); + }) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery', 'minisearch'], function($, minisearch) { + +// In general, most search related things will have "search" as a prefix. +// To get an in-depth about the thought process you can refer: https://hetarth02.hashnode.dev/series/gsoc + +let results = []; +let timer = undefined; + +let data = documenterSearchIndex["docs"].map((x, key) => { + x["id"] = key; // minisearch requires a unique for each object + return x; +}); + +// list below is the lunr 2.1.3 list minus the intersect with names(Base) +// (all, any, get, in, is, only, which) and (do, else, for, let, where, while, with) +// ideally we'd just filter the original list but it's not available as a variable +const stopWords = new Set([ + "a", + "able", + "about", + "across", + "after", + "almost", + "also", + "am", + "among", + "an", + "and", + "are", + "as", + "at", + "be", + "because", + "been", + "but", + "by", + "can", + "cannot", + "could", + "dear", + "did", + "does", + "either", + "ever", + "every", + "from", + "got", + "had", + "has", + "have", + "he", + "her", + "hers", + "him", + "his", + "how", + "however", + "i", + "if", + "into", + "it", + "its", + "just", + "least", + "like", + "likely", + "may", + "me", + "might", + "most", + "must", + "my", + "neither", + "no", + "nor", + "not", + "of", + "off", + "often", + "on", + "or", + "other", + "our", + "own", + "rather", + "said", + "say", + "says", + "she", + "should", + "since", + "so", + "some", + "than", + "that", + "the", + "their", + "them", + "then", + "there", + "these", + "they", + "this", + "tis", + "to", + "too", + "twas", + "us", + "wants", + "was", + "we", + "were", + "what", + "when", + "who", + "whom", + "why", + "will", + "would", + "yet", + "you", + "your", +]); + +let index = new minisearch({ + fields: ["title", "text"], // fields to index for full-text search + storeFields: ["location", "title", "text", "category", "page"], // fields to return with search results + processTerm: (term) => { + let word = stopWords.has(term) ? null : term; + if (word) { + // custom trimmer that doesn't strip @ and !, which are used in julia macro and function names + word = word + .replace(/^[^a-zA-Z0-9@!]+/, "") + .replace(/[^a-zA-Z0-9@!]+$/, ""); + } + + return word ?? null; + }, + // add . as a separator, because otherwise "title": "Documenter.Anchors.add!", would not find anything if searching for "add!", only for the entire qualification + tokenize: (string) => string.split(/[\s\-\.]+/), + // options which will be applied during the search + searchOptions: { + boost: { title: 100 }, + fuzzy: 2, + processTerm: (term) => { + let word = stopWords.has(term) ? null : term; + if (word) { + word = word + .replace(/^[^a-zA-Z0-9@!]+/, "") + .replace(/[^a-zA-Z0-9@!]+$/, ""); + } + + return word ?? null; + }, + tokenize: (string) => string.split(/[\s\-\.]+/), + }, +}); + +index.addAll(data); + +let filters = [...new Set(data.map((x) => x.category))]; +var modal_filters = make_modal_body_filters(filters); +var filter_results = []; + +$(document).on("keyup", ".documenter-search-input", function (event) { + // Adding a debounce to prevent disruptions from super-speed typing! + debounce(() => update_search(filter_results), 300); +}); + +$(document).on("click", ".search-filter", function () { + if ($(this).hasClass("search-filter-selected")) { + $(this).removeClass("search-filter-selected"); + } else { + $(this).addClass("search-filter-selected"); + } + + // Adding a debounce to prevent disruptions from crazy clicking! + debounce(() => get_filters(), 300); +}); + +/** + * A debounce function, takes a function and an optional timeout in milliseconds + * + * @function callback + * @param {number} timeout + */ +function debounce(callback, timeout = 300) { + clearTimeout(timer); + timer = setTimeout(callback, timeout); +} + +/** + * Make/Update the search component + * + * @param {string[]} selected_filters + */ +function update_search(selected_filters = []) { + let initial_search_body = ` +
Type something to get started!
+ `; + + let querystring = $(".documenter-search-input").val(); + + if (querystring.trim()) { + results = index.search(querystring, { + filter: (result) => { + // Filtering results + if (selected_filters.length === 0) { + return result.score >= 1; + } else { + return ( + result.score >= 1 && selected_filters.includes(result.category) + ); + } + }, + }); + + let search_result_container = ``; + let search_divider = `
`; + + if (results.length) { + let links = []; + let count = 0; + let search_results = ""; + + results.forEach(function (result) { + if (result.location) { + // Checking for duplication of results for the same page + if (!links.includes(result.location)) { + search_results += make_search_result(result, querystring); + count++; + } + + links.push(result.location); + } + }); + + let result_count = `
${count} result(s)
`; + + search_result_container = ` +
+ ${modal_filters} + ${search_divider} + ${result_count} +
+ ${search_results} +
+
+ `; + } else { + search_result_container = ` +
+ ${modal_filters} + ${search_divider} +
0 result(s)
+
+
No result found!
+ `; + } + + if ($(".search-modal-card-body").hasClass("is-justify-content-center")) { + $(".search-modal-card-body").removeClass("is-justify-content-center"); + } + + $(".search-modal-card-body").html(search_result_container); + } else { + filter_results = []; + modal_filters = make_modal_body_filters(filters, filter_results); + + if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) { + $(".search-modal-card-body").addClass("is-justify-content-center"); + } + + $(".search-modal-card-body").html(initial_search_body); + } +} + +/** + * Make the modal filter html + * + * @param {string[]} filters + * @param {string[]} selected_filters + * @returns string + */ +function make_modal_body_filters(filters, selected_filters = []) { + let str = ``; + + filters.forEach((val) => { + if (selected_filters.includes(val)) { + str += `${val}`; + } else { + str += `${val}`; + } + }); + + let filter_html = ` +
+ Filters: + ${str} +
+ `; + + return filter_html; +} + +/** + * Make the result component given a minisearch result data object and the value of the search input as queryString. + * To view the result object structure, refer: https://lucaong.github.io/minisearch/modules/_minisearch_.html#searchresult + * + * @param {object} result + * @param {string} querystring + * @returns string + */ +function make_search_result(result, querystring) { + let search_divider = `
`; + let display_link = + result.location.slice(Math.max(0), Math.min(50, result.location.length)) + + (result.location.length > 30 ? "..." : ""); // To cut-off the link because it messes with the overflow of the whole div + + if (result.page !== "") { + display_link += ` (${result.page})`; + } + + let textindex = new RegExp(`\\b${querystring}\\b`, "i").exec(result.text); + let text = + textindex !== null + ? result.text.slice( + Math.max(textindex.index - 100, 0), + Math.min( + textindex.index + querystring.length + 100, + result.text.length + ) + ) + : ""; // cut-off text before and after from the match + + let display_result = text.length + ? "..." + + text.replace( + new RegExp(`\\b${querystring}\\b`, "i"), // For first occurrence + '$&' + ) + + "..." + : ""; // highlights the match + + let in_code = false; + if (!["page", "section"].includes(result.category.toLowerCase())) { + in_code = true; + } + + // We encode the full url to escape some special characters which can lead to broken links + let result_div = ` + +
+
${result.title}
+
${result.category}
+
+

+ ${display_result} +

+
+ ${display_link} +
+
+ ${search_divider} + `; + + return result_div; +} + +/** + * Get selected filters, remake the filter html and lastly update the search modal + */ +function get_filters() { + let ele = $(".search-filters .search-filter-selected").get(); + filter_results = ele.map((x) => $(x).text().toLowerCase()); + modal_filters = make_modal_body_filters(filters, filter_results); + update_search(filter_results); +} }) //////////////////////////////////////////////////////////////////////////////// require(['jquery'], function($) { // Modal settings dialog -$(document).ready(function() { - var settings = $('#documenter-settings'); - $('#documenter-settings-button').click(function(){ - settings.toggleClass('is-active'); +$(document).ready(function () { + var settings = $("#documenter-settings"); + $("#documenter-settings-button").click(function () { + settings.toggleClass("is-active"); }); // Close the dialog if X is clicked - $('#documenter-settings button.delete').click(function(){ - settings.removeClass('is-active'); + $("#documenter-settings button.delete").click(function () { + settings.removeClass("is-active"); }); // Close dialog if ESC is pressed - $(document).keyup(function(e) { - if (e.keyCode == 27) settings.removeClass('is-active'); + $(document).keyup(function (e) { + if (e.keyCode == 27) settings.removeClass("is-active"); }); }); @@ -177,151 +620,242 @@ $(document).ready(function() { //////////////////////////////////////////////////////////////////////////////// require(['jquery'], function($) { +let search_modal_header = ` + +`; + +let initial_search_body = ` +
Type something to get started!
+`; + +let search_modal_footer = ` + +`; + +$(document.body).append( + ` + + ` +); + +document.querySelector(".docs-search-query").addEventListener("click", () => { + openModal(); +}); + +document.querySelector(".close-search-modal").addEventListener("click", () => { + closeModal(); +}); + +$(document).on("click", ".search-result-link", function () { + closeModal(); +}); + +document.addEventListener("keydown", (event) => { + if ((event.ctrlKey || event.metaKey) && event.key === "/") { + openModal(); + } else if (event.key === "Escape") { + closeModal(); + } + + return false; +}); + +// Functions to open and close a modal +function openModal() { + let searchModal = document.querySelector("#search-modal"); + + searchModal.classList.add("is-active"); + document.querySelector(".documenter-search-input").focus(); +} + +function closeModal() { + let searchModal = document.querySelector("#search-modal"); + let initial_search_body = ` +
Type something to get started!
+ `; + + searchModal.classList.remove("is-active"); + document.querySelector(".documenter-search-input").blur(); + + if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) { + $(".search-modal-card-body").addClass("is-justify-content-center"); + } + + $(".documenter-search-input").val(""); + $(".search-modal-card-body").html(initial_search_body); +} + +document + .querySelector("#search-modal .modal-background") + .addEventListener("click", () => { + closeModal(); + }); + +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { + // Manages the showing and hiding of the sidebar. -$(document).ready(function() { +$(document).ready(function () { var sidebar = $("#documenter > .docs-sidebar"); - var sidebar_button = $("#documenter-sidebar-button") - sidebar_button.click(function(ev) { + var sidebar_button = $("#documenter-sidebar-button"); + sidebar_button.click(function (ev) { ev.preventDefault(); - sidebar.toggleClass('visible'); - if (sidebar.hasClass('visible')) { + sidebar.toggleClass("visible"); + if (sidebar.hasClass("visible")) { // Makes sure that the current menu item is visible in the sidebar. $("#documenter .docs-menu a.is-active").focus(); } }); - $("#documenter > .docs-main").bind('click', function(ev) { + $("#documenter > .docs-main").bind("click", function (ev) { if ($(ev.target).is(sidebar_button)) { return; } - if (sidebar.hasClass('visible')) { - sidebar.removeClass('visible'); + if (sidebar.hasClass("visible")) { + sidebar.removeClass("visible"); } }); -}) +}); // Resizes the package name / sitename in the sidebar if it is too wide. // Inspired by: https://github.com/davatron5000/FitText.js -$(document).ready(function() { +$(document).ready(function () { e = $("#documenter .docs-autofit"); function resize() { - var L = parseInt(e.css('max-width'), 10); + var L = parseInt(e.css("max-width"), 10); var L0 = e.width(); - if(L0 > L) { - var h0 = parseInt(e.css('font-size'), 10); - e.css('font-size', L * h0 / L0); + if (L0 > L) { + var h0 = parseInt(e.css("font-size"), 10); + e.css("font-size", (L * h0) / L0); // TODO: make sure it survives resizes? } } // call once and then register events resize(); $(window).resize(resize); - $(window).on('orientationchange', resize); + $(window).on("orientationchange", resize); }); // Scroll the navigation bar to the currently selected menu item -$(document).ready(function() { +$(document).ready(function () { var sidebar = $("#documenter .docs-menu").get(0); var active = $("#documenter .docs-menu .is-active").get(0); - if(typeof active !== 'undefined') { + if (typeof active !== "undefined") { sidebar.scrollTop = active.offsetTop - sidebar.offsetTop - 15; } -}) +}); }) //////////////////////////////////////////////////////////////////////////////// require(['jquery'], function($) { -function set_theme(theme) { - var active = null; - var disabled = []; - for (var i = 0; i < document.styleSheets.length; i++) { - var ss = document.styleSheets[i]; - var themename = ss.ownerNode.getAttribute("data-theme-name"); - if(themename === null) continue; // ignore non-theme stylesheets - // Find the active theme - if(themename === theme) active = ss; - else disabled.push(ss); - } - if(active !== null) { - active.disabled = false; - if(active.ownerNode.getAttribute("data-theme-primary") === null) { - document.getElementsByTagName('html')[0].className = "theme--" + theme; - } else { - document.getElementsByTagName('html')[0].className = ""; - } - disabled.forEach(function(ss){ - ss.disabled = true; - }); - } - - // Store the theme in localStorage - if(typeof(window.localStorage) !== "undefined") { - window.localStorage.setItem("documenter-theme", theme); - } else { - console.error("Browser does not support window.localStorage"); - } -} - // Theme picker setup -$(document).ready(function() { +$(document).ready(function () { // onchange callback - $('#documenter-themepicker').change(function themepick_callback(ev){ - var themename = $('#documenter-themepicker option:selected').attr('value'); - set_theme(themename); + $("#documenter-themepicker").change(function themepick_callback(ev) { + var themename = $("#documenter-themepicker option:selected").attr("value"); + if (themename === "auto") { + // set_theme(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'); + window.localStorage.removeItem("documenter-theme"); + } else { + // set_theme(themename); + window.localStorage.setItem("documenter-theme", themename); + } + // We re-use the global function from themeswap.js to actually do the swapping. + set_theme_from_local_storage(); }); // Make sure that the themepicker displays the correct theme when the theme is retrieved // from localStorage - if(typeof(window.localStorage) !== "undefined") { - var theme = window.localStorage.getItem("documenter-theme"); - if(theme !== null) { - $('#documenter-themepicker option').each(function(i,e) { - e.selected = (e.value === theme); - }) - } else { - $('#documenter-themepicker option').each(function(i,e) { - e.selected = $("html").hasClass(`theme--${e.value}`); - }) + if (typeof window.localStorage !== "undefined") { + var theme = window.localStorage.getItem("documenter-theme"); + if (theme !== null) { + $("#documenter-themepicker option").each(function (i, e) { + e.selected = e.value === theme; + }); } } -}) +}); }) //////////////////////////////////////////////////////////////////////////////// require(['jquery'], function($) { // update the version selector with info from the siteinfo.js and ../versions.js files -$(document).ready(function() { +$(document).ready(function () { // If the version selector is disabled with DOCUMENTER_VERSION_SELECTOR_DISABLED in the // siteinfo.js file, we just return immediately and not display the version selector. - if (typeof DOCUMENTER_VERSION_SELECTOR_DISABLED === 'boolean' && DOCUMENTER_VERSION_SELECTOR_DISABLED) { + if ( + typeof DOCUMENTER_VERSION_SELECTOR_DISABLED === "boolean" && + DOCUMENTER_VERSION_SELECTOR_DISABLED + ) { return; } var version_selector = $("#documenter .docs-version-selector"); var version_selector_select = $("#documenter .docs-version-selector select"); - version_selector_select.change(function(x) { - target_href = version_selector_select.children("option:selected").get(0).value; + version_selector_select.change(function (x) { + target_href = version_selector_select + .children("option:selected") + .get(0).value; window.location.href = target_href; }); // add the current version to the selector based on siteinfo.js, but only if the selector is empty - if (typeof DOCUMENTER_CURRENT_VERSION !== 'undefined' && $('#version-selector > option').length == 0) { - var option = $(""); + if ( + typeof DOCUMENTER_CURRENT_VERSION !== "undefined" && + $("#version-selector > option").length == 0 + ) { + var option = $( + "" + ); version_selector_select.append(option); } - if (typeof DOC_VERSIONS !== 'undefined') { + if (typeof DOC_VERSIONS !== "undefined") { var existing_versions = version_selector_select.children("option"); - var existing_versions_texts = existing_versions.map(function(i,x){return x.text}); - DOC_VERSIONS.forEach(function(each) { - var version_url = documenterBaseURL + "/../" + each; + var existing_versions_texts = existing_versions.map(function (i, x) { + return x.text; + }); + DOC_VERSIONS.forEach(function (each) { + var version_url = documenterBaseURL + "/../" + each + "/"; var existing_id = $.inArray(each, existing_versions_texts); // if not already in the version selector, add it as a new option, // otherwise update the old option with the URL and enable it if (existing_id == -1) { - var option = $(""); + var option = $( + "" + ); version_selector_select.append(option); } else { var option = existing_versions[existing_id]; @@ -335,6 +869,6 @@ $(document).ready(function() { if (version_selector_select.children("option").length > 0) { version_selector.toggleClass("visible"); } -}) +}); }) diff --git a/dev/assets/search.js b/dev/assets/search.js deleted file mode 100644 index c133f74..0000000 --- a/dev/assets/search.js +++ /dev/null @@ -1,267 +0,0 @@ -// Generated by Documenter.jl -requirejs.config({ - paths: { - 'lunr': 'https://cdnjs.cloudflare.com/ajax/libs/lunr.js/2.3.9/lunr.min', - 'lodash': 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min', - 'jquery': 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min', - } -}); -//////////////////////////////////////////////////////////////////////////////// -require(['jquery', 'lunr', 'lodash'], function($, lunr, _) { - -$(document).ready(function() { - // parseUri 1.2.2 - // (c) Steven Levithan - // MIT License - function parseUri (str) { - var o = parseUri.options, - m = o.parser[o.strictMode ? "strict" : "loose"].exec(str), - uri = {}, - i = 14; - - while (i--) uri[o.key[i]] = m[i] || ""; - - uri[o.q.name] = {}; - uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { - if ($1) uri[o.q.name][$1] = $2; - }); - - return uri; - }; - parseUri.options = { - strictMode: false, - key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], - q: { - name: "queryKey", - parser: /(?:^|&)([^&=]*)=?([^&]*)/g - }, - parser: { - strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, - loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ - } - }; - - $("#search-form").submit(function(e) { - e.preventDefault() - }) - - // list below is the lunr 2.1.3 list minus the intersect with names(Base) - // (all, any, get, in, is, only, which) and (do, else, for, let, where, while, with) - // ideally we'd just filter the original list but it's not available as a variable - lunr.stopWordFilter = lunr.generateStopWordFilter([ - 'a', - 'able', - 'about', - 'across', - 'after', - 'almost', - 'also', - 'am', - 'among', - 'an', - 'and', - 'are', - 'as', - 'at', - 'be', - 'because', - 'been', - 'but', - 'by', - 'can', - 'cannot', - 'could', - 'dear', - 'did', - 'does', - 'either', - 'ever', - 'every', - 'from', - 'got', - 'had', - 'has', - 'have', - 'he', - 'her', - 'hers', - 'him', - 'his', - 'how', - 'however', - 'i', - 'if', - 'into', - 'it', - 'its', - 'just', - 'least', - 'like', - 'likely', - 'may', - 'me', - 'might', - 'most', - 'must', - 'my', - 'neither', - 'no', - 'nor', - 'not', - 'of', - 'off', - 'often', - 'on', - 'or', - 'other', - 'our', - 'own', - 'rather', - 'said', - 'say', - 'says', - 'she', - 'should', - 'since', - 'so', - 'some', - 'than', - 'that', - 'the', - 'their', - 'them', - 'then', - 'there', - 'these', - 'they', - 'this', - 'tis', - 'to', - 'too', - 'twas', - 'us', - 'wants', - 'was', - 'we', - 'were', - 'what', - 'when', - 'who', - 'whom', - 'why', - 'will', - 'would', - 'yet', - 'you', - 'your' - ]) - - // add . as a separator, because otherwise "title": "Documenter.Anchors.add!" - // would not find anything if searching for "add!", only for the entire qualification - lunr.tokenizer.separator = /[\s\-\.]+/ - - // custom trimmer that doesn't strip @ and !, which are used in julia macro and function names - lunr.trimmer = function (token) { - return token.update(function (s) { - return s.replace(/^[^a-zA-Z0-9@!]+/, '').replace(/[^a-zA-Z0-9@!]+$/, '') - }) - } - - lunr.Pipeline.registerFunction(lunr.stopWordFilter, 'juliaStopWordFilter') - lunr.Pipeline.registerFunction(lunr.trimmer, 'juliaTrimmer') - - var index = lunr(function () { - this.ref('location') - this.field('title',{boost: 100}) - this.field('text') - documenterSearchIndex['docs'].forEach(function(e) { - this.add(e) - }, this) - }) - var store = {} - - documenterSearchIndex['docs'].forEach(function(e) { - store[e.location] = {title: e.title, category: e.category, page: e.page} - }) - - $(function(){ - searchresults = $('#documenter-search-results'); - searchinfo = $('#documenter-search-info'); - searchbox = $('#documenter-search-query'); - searchform = $('.docs-search'); - sidebar = $('.docs-sidebar'); - function update_search(querystring) { - tokens = lunr.tokenizer(querystring) - results = index.query(function (q) { - tokens.forEach(function (t) { - q.term(t.toString(), { - fields: ["title"], - boost: 100, - usePipeline: true, - editDistance: 0, - wildcard: lunr.Query.wildcard.NONE - }) - q.term(t.toString(), { - fields: ["title"], - boost: 10, - usePipeline: true, - editDistance: 2, - wildcard: lunr.Query.wildcard.NONE - }) - q.term(t.toString(), { - fields: ["text"], - boost: 1, - usePipeline: true, - editDistance: 0, - wildcard: lunr.Query.wildcard.NONE - }) - }) - }) - searchinfo.text("Number of results: " + results.length) - searchresults.empty() - results.forEach(function(result) { - data = store[result.ref] - link = $(''+data.title+'') - link.attr('href', documenterBaseURL+'/'+result.ref) - if (data.category != "page"){ - cat = $('('+data.category+', '+data.page+')') - } else { - cat = $('('+data.category+')') - } - li = $('
  • ').append(link).append(" ").append(cat) - searchresults.append(li) - }) - } - - function update_search_box() { - querystring = searchbox.val() - update_search(querystring) - } - - searchbox.keyup(_.debounce(update_search_box, 250)) - searchbox.change(update_search_box) - - // Disable enter-key form submission for the searchbox on the search page - // and just re-run search rather than refresh the whole page. - searchform.keypress( - function(event){ - if (event.which == '13') { - if (sidebar.hasClass('visible')) { - sidebar.removeClass('visible'); - } - update_search_box(); - event.preventDefault(); - } - } - ); - - search_query_uri = parseUri(window.location).queryKey["q"] - if(search_query_uri !== undefined) { - search_query = decodeURIComponent(search_query_uri.replace(/\+/g, '%20')) - searchbox.val(search_query) - } - update_search_box(); - }) -}) - -}) diff --git a/dev/assets/themes/documenter-dark.css b/dev/assets/themes/documenter-dark.css index c94a294..691b83a 100644 --- a/dev/assets/themes/documenter-dark.css +++ b/dev/assets/themes/documenter-dark.css @@ -1,7 +1,7 @@ -@keyframes spinAround{from{transform:rotate(0deg)}to{transform:rotate(359deg)}}html.theme--documenter-dark .tabs,html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark .breadcrumb,html.theme--documenter-dark .file,html.theme--documenter-dark .button,.is-unselectable,html.theme--documenter-dark .modal-close,html.theme--documenter-dark .delete{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}html.theme--documenter-dark .navbar-link:not(.is-arrowless)::after,html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading)::after{border:3px solid rgba(0,0,0,0);border-radius:2px;border-right:0;border-top:0;content:" ";display:block;height:0.625em;margin-top:-0.4375em;pointer-events:none;position:absolute;top:50%;transform:rotate(-45deg);transform-origin:center;width:0.625em}html.theme--documenter-dark .admonition:not(:last-child),html.theme--documenter-dark .tabs:not(:last-child),html.theme--documenter-dark .message:not(:last-child),html.theme--documenter-dark .list:not(:last-child),html.theme--documenter-dark .level:not(:last-child),html.theme--documenter-dark .breadcrumb:not(:last-child),html.theme--documenter-dark .highlight:not(:last-child),html.theme--documenter-dark .block:not(:last-child),html.theme--documenter-dark .title:not(:last-child),html.theme--documenter-dark .subtitle:not(:last-child),html.theme--documenter-dark .table-container:not(:last-child),html.theme--documenter-dark .table:not(:last-child),html.theme--documenter-dark .progress:not(:last-child),html.theme--documenter-dark .notification:not(:last-child),html.theme--documenter-dark .content:not(:last-child),html.theme--documenter-dark .box:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .modal-close,html.theme--documenter-dark .delete{-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,0.2);border:none;border-radius:290486px;cursor:pointer;pointer-events:auto;display:inline-block;flex-grow:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:none;position:relative;vertical-align:top;width:20px}html.theme--documenter-dark .modal-close::before,html.theme--documenter-dark .delete::before,html.theme--documenter-dark .modal-close::after,html.theme--documenter-dark .delete::after{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--documenter-dark .modal-close::before,html.theme--documenter-dark .delete::before{height:2px;width:50%}html.theme--documenter-dark .modal-close::after,html.theme--documenter-dark .delete::after{height:50%;width:2px}html.theme--documenter-dark .modal-close:hover,html.theme--documenter-dark .delete:hover,html.theme--documenter-dark .modal-close:focus,html.theme--documenter-dark .delete:focus{background-color:rgba(10,10,10,0.3)}html.theme--documenter-dark .modal-close:active,html.theme--documenter-dark .delete:active{background-color:rgba(10,10,10,0.4)}html.theme--documenter-dark .is-small.modal-close,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.modal-close,html.theme--documenter-dark .is-small.delete,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.delete{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}html.theme--documenter-dark .is-medium.modal-close,html.theme--documenter-dark .is-medium.delete{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}html.theme--documenter-dark .is-large.modal-close,html.theme--documenter-dark .is-large.delete{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}html.theme--documenter-dark .control.is-loading::after,html.theme--documenter-dark .select.is-loading::after,html.theme--documenter-dark .loader,html.theme--documenter-dark .button.is-loading::after{animation:spinAround 500ms infinite linear;border:2px solid #dbdee0;border-radius:290486px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em}html.theme--documenter-dark .hero-video,html.theme--documenter-dark .modal-background,html.theme--documenter-dark .modal,html.theme--documenter-dark .image.is-square img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--documenter-dark .image.is-square .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--documenter-dark .image.is-1by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--documenter-dark .image.is-1by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--documenter-dark .image.is-5by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--documenter-dark .image.is-5by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--documenter-dark .image.is-4by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--documenter-dark .image.is-4by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--documenter-dark .image.is-3by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--documenter-dark .image.is-3by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--documenter-dark .image.is-5by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--documenter-dark .image.is-5by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--documenter-dark .image.is-16by9 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--documenter-dark .image.is-16by9 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--documenter-dark .image.is-2by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--documenter-dark .image.is-2by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--documenter-dark .image.is-3by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--documenter-dark .image.is-3by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--documenter-dark .image.is-4by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--documenter-dark .image.is-4by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--documenter-dark .image.is-3by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--documenter-dark .image.is-3by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--documenter-dark .image.is-2by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--documenter-dark .image.is-2by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--documenter-dark .image.is-3by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--documenter-dark .image.is-3by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--documenter-dark .image.is-9by16 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--documenter-dark .image.is-9by16 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--documenter-dark .image.is-1by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--documenter-dark .image.is-1by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--documenter-dark .image.is-1by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--documenter-dark .image.is-1by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio,.is-overlay{bottom:0;left:0;position:absolute;right:0;top:0}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark .file-cta,html.theme--documenter-dark .file-name,html.theme--documenter-dark .select select,html.theme--documenter-dark .textarea,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark .button{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;border-radius:.4em;box-shadow:none;display:inline-flex;font-size:15px;height:2.25em;justify-content:flex-start;line-height:1.5;padding-bottom:calc(0.375em - 1px);padding-left:calc(0.625em - 1px);padding-right:calc(0.625em - 1px);padding-top:calc(0.375em - 1px);position:relative;vertical-align:top}html.theme--documenter-dark .pagination-previous:focus,html.theme--documenter-dark .pagination-next:focus,html.theme--documenter-dark .pagination-link:focus,html.theme--documenter-dark .pagination-ellipsis:focus,html.theme--documenter-dark .file-cta:focus,html.theme--documenter-dark .file-name:focus,html.theme--documenter-dark .select select:focus,html.theme--documenter-dark .textarea:focus,html.theme--documenter-dark .input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:focus,html.theme--documenter-dark .button:focus,html.theme--documenter-dark .is-focused.pagination-previous,html.theme--documenter-dark .is-focused.pagination-next,html.theme--documenter-dark .is-focused.pagination-link,html.theme--documenter-dark .is-focused.pagination-ellipsis,html.theme--documenter-dark .is-focused.file-cta,html.theme--documenter-dark .is-focused.file-name,html.theme--documenter-dark .select select.is-focused,html.theme--documenter-dark .is-focused.textarea,html.theme--documenter-dark .is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-focused.button,html.theme--documenter-dark .pagination-previous:active,html.theme--documenter-dark .pagination-next:active,html.theme--documenter-dark .pagination-link:active,html.theme--documenter-dark .pagination-ellipsis:active,html.theme--documenter-dark .file-cta:active,html.theme--documenter-dark .file-name:active,html.theme--documenter-dark .select select:active,html.theme--documenter-dark .textarea:active,html.theme--documenter-dark .input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:active,html.theme--documenter-dark .button:active,html.theme--documenter-dark .is-active.pagination-previous,html.theme--documenter-dark .is-active.pagination-next,html.theme--documenter-dark .is-active.pagination-link,html.theme--documenter-dark .is-active.pagination-ellipsis,html.theme--documenter-dark .is-active.file-cta,html.theme--documenter-dark .is-active.file-name,html.theme--documenter-dark .select select.is-active,html.theme--documenter-dark .is-active.textarea,html.theme--documenter-dark .is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--documenter-dark .is-active.button{outline:none}html.theme--documenter-dark .pagination-previous[disabled],html.theme--documenter-dark .pagination-next[disabled],html.theme--documenter-dark .pagination-link[disabled],html.theme--documenter-dark .pagination-ellipsis[disabled],html.theme--documenter-dark .file-cta[disabled],html.theme--documenter-dark .file-name[disabled],html.theme--documenter-dark .select select[disabled],html.theme--documenter-dark .textarea[disabled],html.theme--documenter-dark .input[disabled],html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled],html.theme--documenter-dark .button[disabled],fieldset[disabled] html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark fieldset[disabled] .pagination-previous,fieldset[disabled] html.theme--documenter-dark .pagination-next,html.theme--documenter-dark fieldset[disabled] .pagination-next,fieldset[disabled] html.theme--documenter-dark .pagination-link,html.theme--documenter-dark fieldset[disabled] .pagination-link,fieldset[disabled] html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark fieldset[disabled] .pagination-ellipsis,fieldset[disabled] html.theme--documenter-dark .file-cta,html.theme--documenter-dark fieldset[disabled] .file-cta,fieldset[disabled] html.theme--documenter-dark .file-name,html.theme--documenter-dark fieldset[disabled] .file-name,fieldset[disabled] html.theme--documenter-dark .select select,fieldset[disabled] html.theme--documenter-dark .textarea,fieldset[disabled] html.theme--documenter-dark .input,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark fieldset[disabled] .select select,html.theme--documenter-dark .select fieldset[disabled] select,html.theme--documenter-dark fieldset[disabled] .textarea,html.theme--documenter-dark fieldset[disabled] .input,html.theme--documenter-dark fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar fieldset[disabled] form.docs-search>input,fieldset[disabled] html.theme--documenter-dark .button,html.theme--documenter-dark fieldset[disabled] .button{cursor:not-allowed}/*! minireset.css v0.0.4 | MIT License | github.com/jgthms/minireset.css */html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,embed,iframe,object,video{height:auto;max-width:100%}audio{max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:left}.is-clearfix::after{clear:both;content:" ";display:table}.is-pulled-left{float:left !important}.is-pulled-right{float:right !important}.is-clipped{overflow:hidden !important}.is-size-1{font-size:3rem !important}.is-size-2{font-size:2.5rem !important}.is-size-3{font-size:2rem !important}.is-size-4{font-size:1.5rem !important}.is-size-5{font-size:1.25rem !important}.is-size-6{font-size:15px !important}.is-size-7,html.theme--documenter-dark .docstring>section>a.docs-sourcelink{font-size:.85em !important}@media screen and (max-width: 768px){.is-size-1-mobile{font-size:3rem !important}.is-size-2-mobile{font-size:2.5rem !important}.is-size-3-mobile{font-size:2rem !important}.is-size-4-mobile{font-size:1.5rem !important}.is-size-5-mobile{font-size:1.25rem !important}.is-size-6-mobile{font-size:15px !important}.is-size-7-mobile{font-size:.85em !important}}@media screen and (min-width: 769px),print{.is-size-1-tablet{font-size:3rem !important}.is-size-2-tablet{font-size:2.5rem !important}.is-size-3-tablet{font-size:2rem !important}.is-size-4-tablet{font-size:1.5rem !important}.is-size-5-tablet{font-size:1.25rem !important}.is-size-6-tablet{font-size:15px !important}.is-size-7-tablet{font-size:.85em !important}}@media screen and (max-width: 1055px){.is-size-1-touch{font-size:3rem !important}.is-size-2-touch{font-size:2.5rem !important}.is-size-3-touch{font-size:2rem !important}.is-size-4-touch{font-size:1.5rem !important}.is-size-5-touch{font-size:1.25rem !important}.is-size-6-touch{font-size:15px !important}.is-size-7-touch{font-size:.85em !important}}@media screen and (min-width: 1056px){.is-size-1-desktop{font-size:3rem !important}.is-size-2-desktop{font-size:2.5rem !important}.is-size-3-desktop{font-size:2rem !important}.is-size-4-desktop{font-size:1.5rem !important}.is-size-5-desktop{font-size:1.25rem !important}.is-size-6-desktop{font-size:15px !important}.is-size-7-desktop{font-size:.85em !important}}@media screen and (min-width: 1216px){.is-size-1-widescreen{font-size:3rem !important}.is-size-2-widescreen{font-size:2.5rem !important}.is-size-3-widescreen{font-size:2rem !important}.is-size-4-widescreen{font-size:1.5rem !important}.is-size-5-widescreen{font-size:1.25rem !important}.is-size-6-widescreen{font-size:15px !important}.is-size-7-widescreen{font-size:.85em !important}}@media screen and (min-width: 1408px){.is-size-1-fullhd{font-size:3rem !important}.is-size-2-fullhd{font-size:2.5rem !important}.is-size-3-fullhd{font-size:2rem !important}.is-size-4-fullhd{font-size:1.5rem !important}.is-size-5-fullhd{font-size:1.25rem !important}.is-size-6-fullhd{font-size:15px !important}.is-size-7-fullhd{font-size:.85em !important}}.has-text-centered{text-align:center !important}.has-text-justified{text-align:justify !important}.has-text-left{text-align:left !important}.has-text-right{text-align:right !important}@media screen and (max-width: 768px){.has-text-centered-mobile{text-align:center !important}}@media screen and (min-width: 769px),print{.has-text-centered-tablet{text-align:center !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-centered-tablet-only{text-align:center !important}}@media screen and (max-width: 1055px){.has-text-centered-touch{text-align:center !important}}@media screen and (min-width: 1056px){.has-text-centered-desktop{text-align:center !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-centered-desktop-only{text-align:center !important}}@media screen and (min-width: 1216px){.has-text-centered-widescreen{text-align:center !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-centered-widescreen-only{text-align:center !important}}@media screen and (min-width: 1408px){.has-text-centered-fullhd{text-align:center !important}}@media screen and (max-width: 768px){.has-text-justified-mobile{text-align:justify !important}}@media screen and (min-width: 769px),print{.has-text-justified-tablet{text-align:justify !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-justified-tablet-only{text-align:justify !important}}@media screen and (max-width: 1055px){.has-text-justified-touch{text-align:justify !important}}@media screen and (min-width: 1056px){.has-text-justified-desktop{text-align:justify !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-justified-desktop-only{text-align:justify !important}}@media screen and (min-width: 1216px){.has-text-justified-widescreen{text-align:justify !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-justified-widescreen-only{text-align:justify !important}}@media screen and (min-width: 1408px){.has-text-justified-fullhd{text-align:justify !important}}@media screen and (max-width: 768px){.has-text-left-mobile{text-align:left !important}}@media screen and (min-width: 769px),print{.has-text-left-tablet{text-align:left !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-left-tablet-only{text-align:left !important}}@media screen and (max-width: 1055px){.has-text-left-touch{text-align:left !important}}@media screen and (min-width: 1056px){.has-text-left-desktop{text-align:left !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-left-desktop-only{text-align:left !important}}@media screen and (min-width: 1216px){.has-text-left-widescreen{text-align:left !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-left-widescreen-only{text-align:left !important}}@media screen and (min-width: 1408px){.has-text-left-fullhd{text-align:left !important}}@media screen and (max-width: 768px){.has-text-right-mobile{text-align:right !important}}@media screen and (min-width: 769px),print{.has-text-right-tablet{text-align:right !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-right-tablet-only{text-align:right !important}}@media screen and (max-width: 1055px){.has-text-right-touch{text-align:right !important}}@media screen and (min-width: 1056px){.has-text-right-desktop{text-align:right !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-right-desktop-only{text-align:right !important}}@media screen and (min-width: 1216px){.has-text-right-widescreen{text-align:right !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-right-widescreen-only{text-align:right !important}}@media screen and (min-width: 1408px){.has-text-right-fullhd{text-align:right !important}}.is-capitalized{text-transform:capitalize !important}.is-lowercase{text-transform:lowercase !important}.is-uppercase{text-transform:uppercase !important}.is-italic{font-style:italic !important}.has-text-white{color:#fff !important}a.has-text-white:hover,a.has-text-white:focus{color:#e6e6e6 !important}.has-background-white{background-color:#fff !important}.has-text-black{color:#0a0a0a !important}a.has-text-black:hover,a.has-text-black:focus{color:#000 !important}.has-background-black{background-color:#0a0a0a !important}.has-text-light{color:#ecf0f1 !important}a.has-text-light:hover,a.has-text-light:focus{color:#cfd9db !important}.has-background-light{background-color:#ecf0f1 !important}.has-text-dark{color:#282f2f !important}a.has-text-dark:hover,a.has-text-dark:focus{color:#111414 !important}.has-background-dark{background-color:#282f2f !important}.has-text-primary{color:#375a7f !important}a.has-text-primary:hover,a.has-text-primary:focus{color:#28415b !important}.has-background-primary{background-color:#375a7f !important}.has-text-link{color:#1abc9c !important}a.has-text-link:hover,a.has-text-link:focus{color:#148f77 !important}.has-background-link{background-color:#1abc9c !important}.has-text-info{color:#024c7d !important}a.has-text-info:hover,a.has-text-info:focus{color:#012d4b !important}.has-background-info{background-color:#024c7d !important}.has-text-success{color:#008438 !important}a.has-text-success:hover,a.has-text-success:focus{color:#005122 !important}.has-background-success{background-color:#008438 !important}.has-text-warning{color:#ad8100 !important}a.has-text-warning:hover,a.has-text-warning:focus{color:#7a5b00 !important}.has-background-warning{background-color:#ad8100 !important}.has-text-danger{color:#9e1b0d !important}a.has-text-danger:hover,a.has-text-danger:focus{color:#6f1309 !important}.has-background-danger{background-color:#9e1b0d !important}.has-text-black-bis{color:#121212 !important}.has-background-black-bis{background-color:#121212 !important}.has-text-black-ter{color:#242424 !important}.has-background-black-ter{background-color:#242424 !important}.has-text-grey-darker{color:#282f2f !important}.has-background-grey-darker{background-color:#282f2f !important}.has-text-grey-dark{color:#343c3d !important}.has-background-grey-dark{background-color:#343c3d !important}.has-text-grey{color:#5e6d6f !important}.has-background-grey{background-color:#5e6d6f !important}.has-text-grey-light{color:#8c9b9d !important}.has-background-grey-light{background-color:#8c9b9d !important}.has-text-grey-lighter{color:#dbdee0 !important}.has-background-grey-lighter{background-color:#dbdee0 !important}.has-text-white-ter{color:#ecf0f1 !important}.has-background-white-ter{background-color:#ecf0f1 !important}.has-text-white-bis{color:#fafafa !important}.has-background-white-bis{background-color:#fafafa !important}.has-text-weight-light{font-weight:300 !important}.has-text-weight-normal{font-weight:400 !important}.has-text-weight-medium{font-weight:500 !important}.has-text-weight-semibold{font-weight:600 !important}.has-text-weight-bold{font-weight:700 !important}.is-family-primary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-secondary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-sans-serif{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-monospace{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-family-code{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-block{display:block !important}@media screen and (max-width: 768px){.is-block-mobile{display:block !important}}@media screen and (min-width: 769px),print{.is-block-tablet{display:block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-block-tablet-only{display:block !important}}@media screen and (max-width: 1055px){.is-block-touch{display:block !important}}@media screen and (min-width: 1056px){.is-block-desktop{display:block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-block-desktop-only{display:block !important}}@media screen and (min-width: 1216px){.is-block-widescreen{display:block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-block-widescreen-only{display:block !important}}@media screen and (min-width: 1408px){.is-block-fullhd{display:block !important}}.is-flex{display:flex !important}@media screen and (max-width: 768px){.is-flex-mobile{display:flex !important}}@media screen and (min-width: 769px),print{.is-flex-tablet{display:flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-flex-tablet-only{display:flex !important}}@media screen and (max-width: 1055px){.is-flex-touch{display:flex !important}}@media screen and (min-width: 1056px){.is-flex-desktop{display:flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-flex-desktop-only{display:flex !important}}@media screen and (min-width: 1216px){.is-flex-widescreen{display:flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-flex-widescreen-only{display:flex !important}}@media screen and (min-width: 1408px){.is-flex-fullhd{display:flex !important}}.is-inline{display:inline !important}@media screen and (max-width: 768px){.is-inline-mobile{display:inline !important}}@media screen and (min-width: 769px),print{.is-inline-tablet{display:inline !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-tablet-only{display:inline !important}}@media screen and (max-width: 1055px){.is-inline-touch{display:inline !important}}@media screen and (min-width: 1056px){.is-inline-desktop{display:inline !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-desktop-only{display:inline !important}}@media screen and (min-width: 1216px){.is-inline-widescreen{display:inline !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-widescreen-only{display:inline !important}}@media screen and (min-width: 1408px){.is-inline-fullhd{display:inline !important}}.is-inline-block{display:inline-block !important}@media screen and (max-width: 768px){.is-inline-block-mobile{display:inline-block !important}}@media screen and (min-width: 769px),print{.is-inline-block-tablet{display:inline-block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-block-tablet-only{display:inline-block !important}}@media screen and (max-width: 1055px){.is-inline-block-touch{display:inline-block !important}}@media screen and (min-width: 1056px){.is-inline-block-desktop{display:inline-block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-block-desktop-only{display:inline-block !important}}@media screen and (min-width: 1216px){.is-inline-block-widescreen{display:inline-block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-block-widescreen-only{display:inline-block !important}}@media screen and (min-width: 1408px){.is-inline-block-fullhd{display:inline-block !important}}.is-inline-flex{display:inline-flex !important}@media screen and (max-width: 768px){.is-inline-flex-mobile{display:inline-flex !important}}@media screen and (min-width: 769px),print{.is-inline-flex-tablet{display:inline-flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-flex-tablet-only{display:inline-flex !important}}@media screen and (max-width: 1055px){.is-inline-flex-touch{display:inline-flex !important}}@media screen and (min-width: 1056px){.is-inline-flex-desktop{display:inline-flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-flex-desktop-only{display:inline-flex !important}}@media screen and (min-width: 1216px){.is-inline-flex-widescreen{display:inline-flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-flex-widescreen-only{display:inline-flex !important}}@media screen and (min-width: 1408px){.is-inline-flex-fullhd{display:inline-flex !important}}.is-hidden{display:none !important}.is-sr-only{border:none !important;clip:rect(0, 0, 0, 0) !important;height:0.01em !important;overflow:hidden !important;padding:0 !important;position:absolute !important;white-space:nowrap !important;width:0.01em !important}@media screen and (max-width: 768px){.is-hidden-mobile{display:none !important}}@media screen and (min-width: 769px),print{.is-hidden-tablet{display:none !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-hidden-tablet-only{display:none !important}}@media screen and (max-width: 1055px){.is-hidden-touch{display:none !important}}@media screen and (min-width: 1056px){.is-hidden-desktop{display:none !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-hidden-desktop-only{display:none !important}}@media screen and (min-width: 1216px){.is-hidden-widescreen{display:none !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-hidden-widescreen-only{display:none !important}}@media screen and (min-width: 1408px){.is-hidden-fullhd{display:none !important}}.is-invisible{visibility:hidden !important}@media screen and (max-width: 768px){.is-invisible-mobile{visibility:hidden !important}}@media screen and (min-width: 769px),print{.is-invisible-tablet{visibility:hidden !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-invisible-tablet-only{visibility:hidden !important}}@media screen and (max-width: 1055px){.is-invisible-touch{visibility:hidden !important}}@media screen and (min-width: 1056px){.is-invisible-desktop{visibility:hidden !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-invisible-desktop-only{visibility:hidden !important}}@media screen and (min-width: 1216px){.is-invisible-widescreen{visibility:hidden !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-invisible-widescreen-only{visibility:hidden !important}}@media screen and (min-width: 1408px){.is-invisible-fullhd{visibility:hidden !important}}.is-marginless{margin:0 !important}.is-paddingless{padding:0 !important}.is-radiusless{border-radius:0 !important}.is-shadowless{box-shadow:none !important}.is-relative{position:relative !important}html.theme--documenter-dark{/*! +html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark .file-cta,html.theme--documenter-dark .file-name,html.theme--documenter-dark .select select,html.theme--documenter-dark .textarea,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark .button{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;border-radius:.4em;box-shadow:none;display:inline-flex;font-size:1rem;height:2.5em;justify-content:flex-start;line-height:1.5;padding-bottom:calc(0.5em - 1px);padding-left:calc(0.75em - 1px);padding-right:calc(0.75em - 1px);padding-top:calc(0.5em - 1px);position:relative;vertical-align:top}html.theme--documenter-dark .pagination-previous:focus,html.theme--documenter-dark .pagination-next:focus,html.theme--documenter-dark .pagination-link:focus,html.theme--documenter-dark .pagination-ellipsis:focus,html.theme--documenter-dark .file-cta:focus,html.theme--documenter-dark .file-name:focus,html.theme--documenter-dark .select select:focus,html.theme--documenter-dark .textarea:focus,html.theme--documenter-dark .input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:focus,html.theme--documenter-dark .button:focus,html.theme--documenter-dark .is-focused.pagination-previous,html.theme--documenter-dark .is-focused.pagination-next,html.theme--documenter-dark .is-focused.pagination-link,html.theme--documenter-dark .is-focused.pagination-ellipsis,html.theme--documenter-dark .is-focused.file-cta,html.theme--documenter-dark .is-focused.file-name,html.theme--documenter-dark .select select.is-focused,html.theme--documenter-dark .is-focused.textarea,html.theme--documenter-dark .is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-focused.button,html.theme--documenter-dark .pagination-previous:active,html.theme--documenter-dark .pagination-next:active,html.theme--documenter-dark .pagination-link:active,html.theme--documenter-dark .pagination-ellipsis:active,html.theme--documenter-dark .file-cta:active,html.theme--documenter-dark .file-name:active,html.theme--documenter-dark .select select:active,html.theme--documenter-dark .textarea:active,html.theme--documenter-dark .input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:active,html.theme--documenter-dark .button:active,html.theme--documenter-dark .is-active.pagination-previous,html.theme--documenter-dark .is-active.pagination-next,html.theme--documenter-dark .is-active.pagination-link,html.theme--documenter-dark .is-active.pagination-ellipsis,html.theme--documenter-dark .is-active.file-cta,html.theme--documenter-dark .is-active.file-name,html.theme--documenter-dark .select select.is-active,html.theme--documenter-dark .is-active.textarea,html.theme--documenter-dark .is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--documenter-dark .is-active.button{outline:none}html.theme--documenter-dark .pagination-previous[disabled],html.theme--documenter-dark .pagination-next[disabled],html.theme--documenter-dark .pagination-link[disabled],html.theme--documenter-dark .pagination-ellipsis[disabled],html.theme--documenter-dark .file-cta[disabled],html.theme--documenter-dark .file-name[disabled],html.theme--documenter-dark .select select[disabled],html.theme--documenter-dark .textarea[disabled],html.theme--documenter-dark .input[disabled],html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled],html.theme--documenter-dark .button[disabled],fieldset[disabled] html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark fieldset[disabled] .pagination-previous,fieldset[disabled] html.theme--documenter-dark .pagination-next,html.theme--documenter-dark fieldset[disabled] .pagination-next,fieldset[disabled] html.theme--documenter-dark .pagination-link,html.theme--documenter-dark fieldset[disabled] .pagination-link,fieldset[disabled] html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark fieldset[disabled] .pagination-ellipsis,fieldset[disabled] html.theme--documenter-dark .file-cta,html.theme--documenter-dark fieldset[disabled] .file-cta,fieldset[disabled] html.theme--documenter-dark .file-name,html.theme--documenter-dark fieldset[disabled] .file-name,fieldset[disabled] html.theme--documenter-dark .select select,fieldset[disabled] html.theme--documenter-dark .textarea,fieldset[disabled] html.theme--documenter-dark .input,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark fieldset[disabled] .select select,html.theme--documenter-dark .select fieldset[disabled] select,html.theme--documenter-dark fieldset[disabled] .textarea,html.theme--documenter-dark fieldset[disabled] .input,html.theme--documenter-dark fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar fieldset[disabled] form.docs-search>input,fieldset[disabled] html.theme--documenter-dark .button,html.theme--documenter-dark fieldset[disabled] .button{cursor:not-allowed}html.theme--documenter-dark .tabs,html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark .breadcrumb,html.theme--documenter-dark .file,html.theme--documenter-dark .button,.is-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}html.theme--documenter-dark .navbar-link:not(.is-arrowless)::after,html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading)::after{border:3px solid rgba(0,0,0,0);border-radius:2px;border-right:0;border-top:0;content:" ";display:block;height:0.625em;margin-top:-0.4375em;pointer-events:none;position:absolute;top:50%;transform:rotate(-45deg);transform-origin:center;width:0.625em}html.theme--documenter-dark .admonition:not(:last-child),html.theme--documenter-dark .tabs:not(:last-child),html.theme--documenter-dark .pagination:not(:last-child),html.theme--documenter-dark .message:not(:last-child),html.theme--documenter-dark .level:not(:last-child),html.theme--documenter-dark .breadcrumb:not(:last-child),html.theme--documenter-dark .block:not(:last-child),html.theme--documenter-dark .title:not(:last-child),html.theme--documenter-dark .subtitle:not(:last-child),html.theme--documenter-dark .table-container:not(:last-child),html.theme--documenter-dark .table:not(:last-child),html.theme--documenter-dark .progress:not(:last-child),html.theme--documenter-dark .notification:not(:last-child),html.theme--documenter-dark .content:not(:last-child),html.theme--documenter-dark .box:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .modal-close,html.theme--documenter-dark .delete{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,0.2);border:none;border-radius:9999px;cursor:pointer;pointer-events:auto;display:inline-block;flex-grow:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:none;position:relative;vertical-align:top;width:20px}html.theme--documenter-dark .modal-close::before,html.theme--documenter-dark .delete::before,html.theme--documenter-dark .modal-close::after,html.theme--documenter-dark .delete::after{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--documenter-dark .modal-close::before,html.theme--documenter-dark .delete::before{height:2px;width:50%}html.theme--documenter-dark .modal-close::after,html.theme--documenter-dark .delete::after{height:50%;width:2px}html.theme--documenter-dark .modal-close:hover,html.theme--documenter-dark .delete:hover,html.theme--documenter-dark .modal-close:focus,html.theme--documenter-dark .delete:focus{background-color:rgba(10,10,10,0.3)}html.theme--documenter-dark .modal-close:active,html.theme--documenter-dark .delete:active{background-color:rgba(10,10,10,0.4)}html.theme--documenter-dark .is-small.modal-close,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.modal-close,html.theme--documenter-dark .is-small.delete,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.delete{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}html.theme--documenter-dark .is-medium.modal-close,html.theme--documenter-dark .is-medium.delete{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}html.theme--documenter-dark .is-large.modal-close,html.theme--documenter-dark .is-large.delete{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}html.theme--documenter-dark .control.is-loading::after,html.theme--documenter-dark .select.is-loading::after,html.theme--documenter-dark .loader,html.theme--documenter-dark .button.is-loading::after{animation:spinAround 500ms infinite linear;border:2px solid #dbdee0;border-radius:9999px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em}html.theme--documenter-dark .hero-video,html.theme--documenter-dark .modal-background,html.theme--documenter-dark .modal,html.theme--documenter-dark .image.is-square img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--documenter-dark .image.is-square .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--documenter-dark .image.is-1by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--documenter-dark .image.is-1by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--documenter-dark .image.is-5by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--documenter-dark .image.is-5by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--documenter-dark .image.is-4by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--documenter-dark .image.is-4by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--documenter-dark .image.is-3by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--documenter-dark .image.is-3by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--documenter-dark .image.is-5by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--documenter-dark .image.is-5by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--documenter-dark .image.is-16by9 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--documenter-dark .image.is-16by9 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--documenter-dark .image.is-2by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--documenter-dark .image.is-2by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--documenter-dark .image.is-3by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--documenter-dark .image.is-3by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--documenter-dark .image.is-4by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--documenter-dark .image.is-4by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--documenter-dark .image.is-3by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--documenter-dark .image.is-3by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--documenter-dark .image.is-2by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--documenter-dark .image.is-2by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--documenter-dark .image.is-3by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--documenter-dark .image.is-3by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--documenter-dark .image.is-9by16 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--documenter-dark .image.is-9by16 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--documenter-dark .image.is-1by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--documenter-dark .image.is-1by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--documenter-dark .image.is-1by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--documenter-dark .image.is-1by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio,.is-overlay{bottom:0;left:0;position:absolute;right:0;top:0}html.theme--documenter-dark .navbar-burger{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0}/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:inherit}.has-text-white{color:#fff !important}a.has-text-white:hover,a.has-text-white:focus{color:#e6e6e6 !important}.has-background-white{background-color:#fff !important}.has-text-black{color:#0a0a0a !important}a.has-text-black:hover,a.has-text-black:focus{color:#000 !important}.has-background-black{background-color:#0a0a0a !important}.has-text-light{color:#ecf0f1 !important}a.has-text-light:hover,a.has-text-light:focus{color:#cfd9db !important}.has-background-light{background-color:#ecf0f1 !important}.has-text-dark{color:#282f2f !important}a.has-text-dark:hover,a.has-text-dark:focus{color:#111414 !important}.has-background-dark{background-color:#282f2f !important}.has-text-primary{color:#375a7f !important}a.has-text-primary:hover,a.has-text-primary:focus{color:#28415b !important}.has-background-primary{background-color:#375a7f !important}.has-text-primary-light{color:#f1f5f9 !important}a.has-text-primary-light:hover,a.has-text-primary-light:focus{color:#cddbe9 !important}.has-background-primary-light{background-color:#f1f5f9 !important}.has-text-primary-dark{color:#4d7eb2 !important}a.has-text-primary-dark:hover,a.has-text-primary-dark:focus{color:#7198c1 !important}.has-background-primary-dark{background-color:#4d7eb2 !important}.has-text-link{color:#1abc9c !important}a.has-text-link:hover,a.has-text-link:focus{color:#148f77 !important}.has-background-link{background-color:#1abc9c !important}.has-text-link-light{color:#edfdf9 !important}a.has-text-link-light:hover,a.has-text-link-light:focus{color:#c0f6ec !important}.has-background-link-light{background-color:#edfdf9 !important}.has-text-link-dark{color:#15987e !important}a.has-text-link-dark:hover,a.has-text-link-dark:focus{color:#1bc5a4 !important}.has-background-link-dark{background-color:#15987e !important}.has-text-info{color:#024c7d !important}a.has-text-info:hover,a.has-text-info:focus{color:#012d4b !important}.has-background-info{background-color:#024c7d !important}.has-text-info-light{color:#ebf7ff !important}a.has-text-info-light:hover,a.has-text-info-light:focus{color:#b9e2fe !important}.has-background-info-light{background-color:#ebf7ff !important}.has-text-info-dark{color:#0e9dfb !important}a.has-text-info-dark:hover,a.has-text-info-dark:focus{color:#40b1fc !important}.has-background-info-dark{background-color:#0e9dfb !important}.has-text-success{color:#008438 !important}a.has-text-success:hover,a.has-text-success:focus{color:#005122 !important}.has-background-success{background-color:#008438 !important}.has-text-success-light{color:#ebfff3 !important}a.has-text-success-light:hover,a.has-text-success-light:focus{color:#b8ffd6 !important}.has-background-success-light{background-color:#ebfff3 !important}.has-text-success-dark{color:#00eb64 !important}a.has-text-success-dark:hover,a.has-text-success-dark:focus{color:#1fff7e !important}.has-background-success-dark{background-color:#00eb64 !important}.has-text-warning{color:#ad8100 !important}a.has-text-warning:hover,a.has-text-warning:focus{color:#7a5b00 !important}.has-background-warning{background-color:#ad8100 !important}.has-text-warning-light{color:#fffaeb !important}a.has-text-warning-light:hover,a.has-text-warning-light:focus{color:#ffedb8 !important}.has-background-warning-light{background-color:#fffaeb !important}.has-text-warning-dark{color:#d19c00 !important}a.has-text-warning-dark:hover,a.has-text-warning-dark:focus{color:#ffbf05 !important}.has-background-warning-dark{background-color:#d19c00 !important}.has-text-danger{color:#9e1b0d !important}a.has-text-danger:hover,a.has-text-danger:focus{color:#6f1309 !important}.has-background-danger{background-color:#9e1b0d !important}.has-text-danger-light{color:#fdeeec !important}a.has-text-danger-light:hover,a.has-text-danger-light:focus{color:#fac3bd !important}.has-background-danger-light{background-color:#fdeeec !important}.has-text-danger-dark{color:#ec311d !important}a.has-text-danger-dark:hover,a.has-text-danger-dark:focus{color:#f05c4c !important}.has-background-danger-dark{background-color:#ec311d !important}.has-text-black-bis{color:#121212 !important}.has-background-black-bis{background-color:#121212 !important}.has-text-black-ter{color:#242424 !important}.has-background-black-ter{background-color:#242424 !important}.has-text-grey-darker{color:#282f2f !important}.has-background-grey-darker{background-color:#282f2f !important}.has-text-grey-dark{color:#343c3d !important}.has-background-grey-dark{background-color:#343c3d !important}.has-text-grey{color:#5e6d6f !important}.has-background-grey{background-color:#5e6d6f !important}.has-text-grey-light{color:#8c9b9d !important}.has-background-grey-light{background-color:#8c9b9d !important}.has-text-grey-lighter{color:#dbdee0 !important}.has-background-grey-lighter{background-color:#dbdee0 !important}.has-text-white-ter{color:#ecf0f1 !important}.has-background-white-ter{background-color:#ecf0f1 !important}.has-text-white-bis{color:#fafafa !important}.has-background-white-bis{background-color:#fafafa !important}.is-flex-direction-row{flex-direction:row !important}.is-flex-direction-row-reverse{flex-direction:row-reverse !important}.is-flex-direction-column{flex-direction:column !important}.is-flex-direction-column-reverse{flex-direction:column-reverse !important}.is-flex-wrap-nowrap{flex-wrap:nowrap !important}.is-flex-wrap-wrap{flex-wrap:wrap !important}.is-flex-wrap-wrap-reverse{flex-wrap:wrap-reverse !important}.is-justify-content-flex-start{justify-content:flex-start !important}.is-justify-content-flex-end{justify-content:flex-end !important}.is-justify-content-center{justify-content:center !important}.is-justify-content-space-between{justify-content:space-between !important}.is-justify-content-space-around{justify-content:space-around !important}.is-justify-content-space-evenly{justify-content:space-evenly !important}.is-justify-content-start{justify-content:start !important}.is-justify-content-end{justify-content:end !important}.is-justify-content-left{justify-content:left !important}.is-justify-content-right{justify-content:right !important}.is-align-content-flex-start{align-content:flex-start !important}.is-align-content-flex-end{align-content:flex-end !important}.is-align-content-center{align-content:center !important}.is-align-content-space-between{align-content:space-between !important}.is-align-content-space-around{align-content:space-around !important}.is-align-content-space-evenly{align-content:space-evenly !important}.is-align-content-stretch{align-content:stretch !important}.is-align-content-start{align-content:start !important}.is-align-content-end{align-content:end !important}.is-align-content-baseline{align-content:baseline !important}.is-align-items-stretch{align-items:stretch !important}.is-align-items-flex-start{align-items:flex-start !important}.is-align-items-flex-end{align-items:flex-end !important}.is-align-items-center{align-items:center !important}.is-align-items-baseline{align-items:baseline !important}.is-align-items-start{align-items:start !important}.is-align-items-end{align-items:end !important}.is-align-items-self-start{align-items:self-start !important}.is-align-items-self-end{align-items:self-end !important}.is-align-self-auto{align-self:auto !important}.is-align-self-flex-start{align-self:flex-start !important}.is-align-self-flex-end{align-self:flex-end !important}.is-align-self-center{align-self:center !important}.is-align-self-baseline{align-self:baseline !important}.is-align-self-stretch{align-self:stretch !important}.is-flex-grow-0{flex-grow:0 !important}.is-flex-grow-1{flex-grow:1 !important}.is-flex-grow-2{flex-grow:2 !important}.is-flex-grow-3{flex-grow:3 !important}.is-flex-grow-4{flex-grow:4 !important}.is-flex-grow-5{flex-grow:5 !important}.is-flex-shrink-0{flex-shrink:0 !important}.is-flex-shrink-1{flex-shrink:1 !important}.is-flex-shrink-2{flex-shrink:2 !important}.is-flex-shrink-3{flex-shrink:3 !important}.is-flex-shrink-4{flex-shrink:4 !important}.is-flex-shrink-5{flex-shrink:5 !important}.is-clearfix::after{clear:both;content:" ";display:table}.is-pulled-left{float:left !important}.is-pulled-right{float:right !important}.is-radiusless{border-radius:0 !important}.is-shadowless{box-shadow:none !important}.is-clickable{cursor:pointer !important;pointer-events:all !important}.is-clipped{overflow:hidden !important}.is-relative{position:relative !important}.is-marginless{margin:0 !important}.is-paddingless{padding:0 !important}.m-0{margin:0 !important}.mt-0{margin-top:0 !important}.mr-0{margin-right:0 !important}.mb-0{margin-bottom:0 !important}.ml-0{margin-left:0 !important}.mx-0{margin-left:0 !important;margin-right:0 !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.m-1{margin:.25rem !important}.mt-1{margin-top:.25rem !important}.mr-1{margin-right:.25rem !important}.mb-1{margin-bottom:.25rem !important}.ml-1{margin-left:.25rem !important}.mx-1{margin-left:.25rem !important;margin-right:.25rem !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.m-2{margin:.5rem !important}.mt-2{margin-top:.5rem !important}.mr-2{margin-right:.5rem !important}.mb-2{margin-bottom:.5rem !important}.ml-2{margin-left:.5rem !important}.mx-2{margin-left:.5rem !important;margin-right:.5rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.m-3{margin:.75rem !important}.mt-3{margin-top:.75rem !important}.mr-3{margin-right:.75rem !important}.mb-3{margin-bottom:.75rem !important}.ml-3{margin-left:.75rem !important}.mx-3{margin-left:.75rem !important;margin-right:.75rem !important}.my-3{margin-top:.75rem !important;margin-bottom:.75rem !important}.m-4{margin:1rem !important}.mt-4{margin-top:1rem !important}.mr-4{margin-right:1rem !important}.mb-4{margin-bottom:1rem !important}.ml-4{margin-left:1rem !important}.mx-4{margin-left:1rem !important;margin-right:1rem !important}.my-4{margin-top:1rem !important;margin-bottom:1rem !important}.m-5{margin:1.5rem !important}.mt-5{margin-top:1.5rem !important}.mr-5{margin-right:1.5rem !important}.mb-5{margin-bottom:1.5rem !important}.ml-5{margin-left:1.5rem !important}.mx-5{margin-left:1.5rem !important;margin-right:1.5rem !important}.my-5{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.m-6{margin:3rem !important}.mt-6{margin-top:3rem !important}.mr-6{margin-right:3rem !important}.mb-6{margin-bottom:3rem !important}.ml-6{margin-left:3rem !important}.mx-6{margin-left:3rem !important;margin-right:3rem !important}.my-6{margin-top:3rem !important;margin-bottom:3rem !important}.m-auto{margin:auto !important}.mt-auto{margin-top:auto !important}.mr-auto{margin-right:auto !important}.mb-auto{margin-bottom:auto !important}.ml-auto{margin-left:auto !important}.mx-auto{margin-left:auto !important;margin-right:auto !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.p-0{padding:0 !important}.pt-0{padding-top:0 !important}.pr-0{padding-right:0 !important}.pb-0{padding-bottom:0 !important}.pl-0{padding-left:0 !important}.px-0{padding-left:0 !important;padding-right:0 !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.p-1{padding:.25rem !important}.pt-1{padding-top:.25rem !important}.pr-1{padding-right:.25rem !important}.pb-1{padding-bottom:.25rem !important}.pl-1{padding-left:.25rem !important}.px-1{padding-left:.25rem !important;padding-right:.25rem !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.p-2{padding:.5rem !important}.pt-2{padding-top:.5rem !important}.pr-2{padding-right:.5rem !important}.pb-2{padding-bottom:.5rem !important}.pl-2{padding-left:.5rem !important}.px-2{padding-left:.5rem !important;padding-right:.5rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.p-3{padding:.75rem !important}.pt-3{padding-top:.75rem !important}.pr-3{padding-right:.75rem !important}.pb-3{padding-bottom:.75rem !important}.pl-3{padding-left:.75rem !important}.px-3{padding-left:.75rem !important;padding-right:.75rem !important}.py-3{padding-top:.75rem !important;padding-bottom:.75rem !important}.p-4{padding:1rem !important}.pt-4{padding-top:1rem !important}.pr-4{padding-right:1rem !important}.pb-4{padding-bottom:1rem !important}.pl-4{padding-left:1rem !important}.px-4{padding-left:1rem !important;padding-right:1rem !important}.py-4{padding-top:1rem !important;padding-bottom:1rem !important}.p-5{padding:1.5rem !important}.pt-5{padding-top:1.5rem !important}.pr-5{padding-right:1.5rem !important}.pb-5{padding-bottom:1.5rem !important}.pl-5{padding-left:1.5rem !important}.px-5{padding-left:1.5rem !important;padding-right:1.5rem !important}.py-5{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.p-6{padding:3rem !important}.pt-6{padding-top:3rem !important}.pr-6{padding-right:3rem !important}.pb-6{padding-bottom:3rem !important}.pl-6{padding-left:3rem !important}.px-6{padding-left:3rem !important;padding-right:3rem !important}.py-6{padding-top:3rem !important;padding-bottom:3rem !important}.p-auto{padding:auto !important}.pt-auto{padding-top:auto !important}.pr-auto{padding-right:auto !important}.pb-auto{padding-bottom:auto !important}.pl-auto{padding-left:auto !important}.px-auto{padding-left:auto !important;padding-right:auto !important}.py-auto{padding-top:auto !important;padding-bottom:auto !important}.is-size-1{font-size:3rem !important}.is-size-2{font-size:2.5rem !important}.is-size-3{font-size:2rem !important}.is-size-4{font-size:1.5rem !important}.is-size-5{font-size:1.25rem !important}.is-size-6{font-size:1rem !important}.is-size-7,html.theme--documenter-dark .docstring>section>a.docs-sourcelink{font-size:.75rem !important}@media screen and (max-width: 768px){.is-size-1-mobile{font-size:3rem !important}.is-size-2-mobile{font-size:2.5rem !important}.is-size-3-mobile{font-size:2rem !important}.is-size-4-mobile{font-size:1.5rem !important}.is-size-5-mobile{font-size:1.25rem !important}.is-size-6-mobile{font-size:1rem !important}.is-size-7-mobile{font-size:.75rem !important}}@media screen and (min-width: 769px),print{.is-size-1-tablet{font-size:3rem !important}.is-size-2-tablet{font-size:2.5rem !important}.is-size-3-tablet{font-size:2rem !important}.is-size-4-tablet{font-size:1.5rem !important}.is-size-5-tablet{font-size:1.25rem !important}.is-size-6-tablet{font-size:1rem !important}.is-size-7-tablet{font-size:.75rem !important}}@media screen and (max-width: 1055px){.is-size-1-touch{font-size:3rem !important}.is-size-2-touch{font-size:2.5rem !important}.is-size-3-touch{font-size:2rem !important}.is-size-4-touch{font-size:1.5rem !important}.is-size-5-touch{font-size:1.25rem !important}.is-size-6-touch{font-size:1rem !important}.is-size-7-touch{font-size:.75rem !important}}@media screen and (min-width: 1056px){.is-size-1-desktop{font-size:3rem !important}.is-size-2-desktop{font-size:2.5rem !important}.is-size-3-desktop{font-size:2rem !important}.is-size-4-desktop{font-size:1.5rem !important}.is-size-5-desktop{font-size:1.25rem !important}.is-size-6-desktop{font-size:1rem !important}.is-size-7-desktop{font-size:.75rem !important}}@media screen and (min-width: 1216px){.is-size-1-widescreen{font-size:3rem !important}.is-size-2-widescreen{font-size:2.5rem !important}.is-size-3-widescreen{font-size:2rem !important}.is-size-4-widescreen{font-size:1.5rem !important}.is-size-5-widescreen{font-size:1.25rem !important}.is-size-6-widescreen{font-size:1rem !important}.is-size-7-widescreen{font-size:.75rem !important}}@media screen and (min-width: 1408px){.is-size-1-fullhd{font-size:3rem !important}.is-size-2-fullhd{font-size:2.5rem !important}.is-size-3-fullhd{font-size:2rem !important}.is-size-4-fullhd{font-size:1.5rem !important}.is-size-5-fullhd{font-size:1.25rem !important}.is-size-6-fullhd{font-size:1rem !important}.is-size-7-fullhd{font-size:.75rem !important}}.has-text-centered{text-align:center !important}.has-text-justified{text-align:justify !important}.has-text-left{text-align:left !important}.has-text-right{text-align:right !important}@media screen and (max-width: 768px){.has-text-centered-mobile{text-align:center !important}}@media screen and (min-width: 769px),print{.has-text-centered-tablet{text-align:center !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-centered-tablet-only{text-align:center !important}}@media screen and (max-width: 1055px){.has-text-centered-touch{text-align:center !important}}@media screen and (min-width: 1056px){.has-text-centered-desktop{text-align:center !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-centered-desktop-only{text-align:center !important}}@media screen and (min-width: 1216px){.has-text-centered-widescreen{text-align:center !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-centered-widescreen-only{text-align:center !important}}@media screen and (min-width: 1408px){.has-text-centered-fullhd{text-align:center !important}}@media screen and (max-width: 768px){.has-text-justified-mobile{text-align:justify !important}}@media screen and (min-width: 769px),print{.has-text-justified-tablet{text-align:justify !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-justified-tablet-only{text-align:justify !important}}@media screen and (max-width: 1055px){.has-text-justified-touch{text-align:justify !important}}@media screen and (min-width: 1056px){.has-text-justified-desktop{text-align:justify !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-justified-desktop-only{text-align:justify !important}}@media screen and (min-width: 1216px){.has-text-justified-widescreen{text-align:justify !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-justified-widescreen-only{text-align:justify !important}}@media screen and (min-width: 1408px){.has-text-justified-fullhd{text-align:justify !important}}@media screen and (max-width: 768px){.has-text-left-mobile{text-align:left !important}}@media screen and (min-width: 769px),print{.has-text-left-tablet{text-align:left !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-left-tablet-only{text-align:left !important}}@media screen and (max-width: 1055px){.has-text-left-touch{text-align:left !important}}@media screen and (min-width: 1056px){.has-text-left-desktop{text-align:left !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-left-desktop-only{text-align:left !important}}@media screen and (min-width: 1216px){.has-text-left-widescreen{text-align:left !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-left-widescreen-only{text-align:left !important}}@media screen and (min-width: 1408px){.has-text-left-fullhd{text-align:left !important}}@media screen and (max-width: 768px){.has-text-right-mobile{text-align:right !important}}@media screen and (min-width: 769px),print{.has-text-right-tablet{text-align:right !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-right-tablet-only{text-align:right !important}}@media screen and (max-width: 1055px){.has-text-right-touch{text-align:right !important}}@media screen and (min-width: 1056px){.has-text-right-desktop{text-align:right !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-right-desktop-only{text-align:right !important}}@media screen and (min-width: 1216px){.has-text-right-widescreen{text-align:right !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-right-widescreen-only{text-align:right !important}}@media screen and (min-width: 1408px){.has-text-right-fullhd{text-align:right !important}}.is-capitalized{text-transform:capitalize !important}.is-lowercase{text-transform:lowercase !important}.is-uppercase{text-transform:uppercase !important}.is-italic{font-style:italic !important}.is-underlined{text-decoration:underline !important}.has-text-weight-light{font-weight:300 !important}.has-text-weight-normal{font-weight:400 !important}.has-text-weight-medium{font-weight:500 !important}.has-text-weight-semibold{font-weight:600 !important}.has-text-weight-bold{font-weight:700 !important}.is-family-primary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-secondary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-sans-serif{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-monospace{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-family-code{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-block{display:block !important}@media screen and (max-width: 768px){.is-block-mobile{display:block !important}}@media screen and (min-width: 769px),print{.is-block-tablet{display:block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-block-tablet-only{display:block !important}}@media screen and (max-width: 1055px){.is-block-touch{display:block !important}}@media screen and (min-width: 1056px){.is-block-desktop{display:block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-block-desktop-only{display:block !important}}@media screen and (min-width: 1216px){.is-block-widescreen{display:block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-block-widescreen-only{display:block !important}}@media screen and (min-width: 1408px){.is-block-fullhd{display:block !important}}.is-flex{display:flex !important}@media screen and (max-width: 768px){.is-flex-mobile{display:flex !important}}@media screen and (min-width: 769px),print{.is-flex-tablet{display:flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-flex-tablet-only{display:flex !important}}@media screen and (max-width: 1055px){.is-flex-touch{display:flex !important}}@media screen and (min-width: 1056px){.is-flex-desktop{display:flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-flex-desktop-only{display:flex !important}}@media screen and (min-width: 1216px){.is-flex-widescreen{display:flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-flex-widescreen-only{display:flex !important}}@media screen and (min-width: 1408px){.is-flex-fullhd{display:flex !important}}.is-inline{display:inline !important}@media screen and (max-width: 768px){.is-inline-mobile{display:inline !important}}@media screen and (min-width: 769px),print{.is-inline-tablet{display:inline !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-tablet-only{display:inline !important}}@media screen and (max-width: 1055px){.is-inline-touch{display:inline !important}}@media screen and (min-width: 1056px){.is-inline-desktop{display:inline !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-desktop-only{display:inline !important}}@media screen and (min-width: 1216px){.is-inline-widescreen{display:inline !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-widescreen-only{display:inline !important}}@media screen and (min-width: 1408px){.is-inline-fullhd{display:inline !important}}.is-inline-block{display:inline-block !important}@media screen and (max-width: 768px){.is-inline-block-mobile{display:inline-block !important}}@media screen and (min-width: 769px),print{.is-inline-block-tablet{display:inline-block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-block-tablet-only{display:inline-block !important}}@media screen and (max-width: 1055px){.is-inline-block-touch{display:inline-block !important}}@media screen and (min-width: 1056px){.is-inline-block-desktop{display:inline-block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-block-desktop-only{display:inline-block !important}}@media screen and (min-width: 1216px){.is-inline-block-widescreen{display:inline-block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-block-widescreen-only{display:inline-block !important}}@media screen and (min-width: 1408px){.is-inline-block-fullhd{display:inline-block !important}}.is-inline-flex{display:inline-flex !important}@media screen and (max-width: 768px){.is-inline-flex-mobile{display:inline-flex !important}}@media screen and (min-width: 769px),print{.is-inline-flex-tablet{display:inline-flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-flex-tablet-only{display:inline-flex !important}}@media screen and (max-width: 1055px){.is-inline-flex-touch{display:inline-flex !important}}@media screen and (min-width: 1056px){.is-inline-flex-desktop{display:inline-flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-flex-desktop-only{display:inline-flex !important}}@media screen and (min-width: 1216px){.is-inline-flex-widescreen{display:inline-flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-flex-widescreen-only{display:inline-flex !important}}@media screen and (min-width: 1408px){.is-inline-flex-fullhd{display:inline-flex !important}}.is-hidden{display:none !important}.is-sr-only{border:none !important;clip:rect(0, 0, 0, 0) !important;height:0.01em !important;overflow:hidden !important;padding:0 !important;position:absolute !important;white-space:nowrap !important;width:0.01em !important}@media screen and (max-width: 768px){.is-hidden-mobile{display:none !important}}@media screen and (min-width: 769px),print{.is-hidden-tablet{display:none !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-hidden-tablet-only{display:none !important}}@media screen and (max-width: 1055px){.is-hidden-touch{display:none !important}}@media screen and (min-width: 1056px){.is-hidden-desktop{display:none !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-hidden-desktop-only{display:none !important}}@media screen and (min-width: 1216px){.is-hidden-widescreen{display:none !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-hidden-widescreen-only{display:none !important}}@media screen and (min-width: 1408px){.is-hidden-fullhd{display:none !important}}.is-invisible{visibility:hidden !important}@media screen and (max-width: 768px){.is-invisible-mobile{visibility:hidden !important}}@media screen and (min-width: 769px),print{.is-invisible-tablet{visibility:hidden !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-invisible-tablet-only{visibility:hidden !important}}@media screen and (max-width: 1055px){.is-invisible-touch{visibility:hidden !important}}@media screen and (min-width: 1056px){.is-invisible-desktop{visibility:hidden !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-invisible-desktop-only{visibility:hidden !important}}@media screen and (min-width: 1216px){.is-invisible-widescreen{visibility:hidden !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-invisible-widescreen-only{visibility:hidden !important}}@media screen and (min-width: 1408px){.is-invisible-fullhd{visibility:hidden !important}}html.theme--documenter-dark{/*! Theme: a11y-dark Author: @ericwbailey Maintainer: @ericwbailey Based on the Tomorrow Night Eighties theme: https://github.com/isagalaev/highlight.js/blob/master/src/styles/tomorrow-night-eighties.css -*/}html.theme--documenter-dark html{background-color:#1f2424;font-size:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--documenter-dark article,html.theme--documenter-dark aside,html.theme--documenter-dark figure,html.theme--documenter-dark footer,html.theme--documenter-dark header,html.theme--documenter-dark hgroup,html.theme--documenter-dark section{display:block}html.theme--documenter-dark body,html.theme--documenter-dark button,html.theme--documenter-dark input,html.theme--documenter-dark select,html.theme--documenter-dark textarea{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif}html.theme--documenter-dark code,html.theme--documenter-dark pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}html.theme--documenter-dark body{color:#fff;font-size:1em;font-weight:400;line-height:1.5}html.theme--documenter-dark a{color:#1abc9c;cursor:pointer;text-decoration:none}html.theme--documenter-dark a strong{color:currentColor}html.theme--documenter-dark a:hover{color:#1dd2af}html.theme--documenter-dark code{background-color:rgba(255,255,255,0.05);color:#ececec;font-size:.875em;font-weight:normal;padding:.1em}html.theme--documenter-dark hr{background-color:#282f2f;border:none;display:block;height:2px;margin:1.5rem 0}html.theme--documenter-dark img{height:auto;max-width:100%}html.theme--documenter-dark input[type="checkbox"],html.theme--documenter-dark input[type="radio"]{vertical-align:baseline}html.theme--documenter-dark small{font-size:.875em}html.theme--documenter-dark span{font-style:inherit;font-weight:inherit}html.theme--documenter-dark strong{color:#f2f2f2;font-weight:700}html.theme--documenter-dark fieldset{border:none}html.theme--documenter-dark pre{-webkit-overflow-scrolling:touch;background-color:#282f2f;color:#fff;font-size:.875em;overflow-x:auto;padding:1.25rem 1.5rem;white-space:pre;word-wrap:normal}html.theme--documenter-dark pre code{background-color:transparent;color:currentColor;font-size:1em;padding:0}html.theme--documenter-dark table td,html.theme--documenter-dark table th{vertical-align:top}html.theme--documenter-dark table td:not([align]),html.theme--documenter-dark table th:not([align]){text-align:left}html.theme--documenter-dark table th{color:#f2f2f2}html.theme--documenter-dark .box{background-color:#343c3d;border-radius:8px;box-shadow:none;color:#fff;display:block;padding:1.25rem}html.theme--documenter-dark a.box:hover,html.theme--documenter-dark a.box:focus{box-shadow:0 2px 3px rgba(10,10,10,0.1),0 0 0 1px #1abc9c}html.theme--documenter-dark a.box:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2),0 0 0 1px #1abc9c}html.theme--documenter-dark .button{background-color:#282f2f;border-color:#4c5759;border-width:1px;color:#375a7f;cursor:pointer;justify-content:center;padding-bottom:calc(0.375em - 1px);padding-left:.75em;padding-right:.75em;padding-top:calc(0.375em - 1px);text-align:center;white-space:nowrap}html.theme--documenter-dark .button strong{color:inherit}html.theme--documenter-dark .button .icon,html.theme--documenter-dark .button .icon.is-small,html.theme--documenter-dark .button #documenter .docs-sidebar form.docs-search>input.icon,html.theme--documenter-dark #documenter .docs-sidebar .button form.docs-search>input.icon,html.theme--documenter-dark .button .icon.is-medium,html.theme--documenter-dark .button .icon.is-large{height:1.5em;width:1.5em}html.theme--documenter-dark .button .icon:first-child:not(:last-child){margin-left:calc(-0.375em - 1px);margin-right:0.1875em}html.theme--documenter-dark .button .icon:last-child:not(:first-child){margin-left:0.1875em;margin-right:calc(-0.375em - 1px)}html.theme--documenter-dark .button .icon:first-child:last-child{margin-left:calc(-0.375em - 1px);margin-right:calc(-0.375em - 1px)}html.theme--documenter-dark .button:hover,html.theme--documenter-dark .button.is-hovered{border-color:#8c9b9d;color:#f2f2f2}html.theme--documenter-dark .button:focus,html.theme--documenter-dark .button.is-focused{border-color:#8c9b9d;color:#17a689}html.theme--documenter-dark .button:focus:not(:active),html.theme--documenter-dark .button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .button:active,html.theme--documenter-dark .button.is-active{border-color:#343c3d;color:#f2f2f2}html.theme--documenter-dark .button.is-text{background-color:transparent;border-color:transparent;color:#fff;text-decoration:underline}html.theme--documenter-dark .button.is-text:hover,html.theme--documenter-dark .button.is-text.is-hovered,html.theme--documenter-dark .button.is-text:focus,html.theme--documenter-dark .button.is-text.is-focused{background-color:#282f2f;color:#f2f2f2}html.theme--documenter-dark .button.is-text:active,html.theme--documenter-dark .button.is-text.is-active{background-color:#1d2122;color:#f2f2f2}html.theme--documenter-dark .button.is-text[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-text{background-color:transparent;border-color:transparent;box-shadow:none}html.theme--documenter-dark .button.is-white{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white:hover,html.theme--documenter-dark .button.is-white.is-hovered{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white:focus,html.theme--documenter-dark .button.is-white.is-focused{border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white:focus:not(:active),html.theme--documenter-dark .button.is-white.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--documenter-dark .button.is-white:active,html.theme--documenter-dark .button.is-white.is-active{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white{background-color:#fff;border-color:transparent;box-shadow:none}html.theme--documenter-dark .button.is-white.is-inverted{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .button.is-white.is-inverted:hover,html.theme--documenter-dark .button.is-white.is-inverted.is-hovered{background-color:#000}html.theme--documenter-dark .button.is-white.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white.is-inverted{background-color:#0a0a0a;border-color:transparent;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-white.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-white.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-white.is-outlined:hover,html.theme--documenter-dark .button.is-white.is-outlined.is-hovered,html.theme--documenter-dark .button.is-white.is-outlined:focus,html.theme--documenter-dark .button.is-white.is-outlined.is-focused{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--documenter-dark .button.is-white.is-outlined.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-white.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-white.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-white.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-white.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-white.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-focused{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--documenter-dark .button.is-black{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black:hover,html.theme--documenter-dark .button.is-black.is-hovered{background-color:#040404;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black:focus,html.theme--documenter-dark .button.is-black.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black:focus:not(:active),html.theme--documenter-dark .button.is-black.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--documenter-dark .button.is-black:active,html.theme--documenter-dark .button.is-black.is-active{background-color:#000;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black{background-color:#0a0a0a;border-color:transparent;box-shadow:none}html.theme--documenter-dark .button.is-black.is-inverted{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-inverted:hover,html.theme--documenter-dark .button.is-black.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-black.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-outlined:hover,html.theme--documenter-dark .button.is-black.is-outlined.is-hovered,html.theme--documenter-dark .button.is-black.is-outlined:focus,html.theme--documenter-dark .button.is-black.is-outlined.is-focused{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--documenter-dark .button.is-black.is-outlined.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-black.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-black.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-black.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-black.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-black.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-focused{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-light{background-color:#ecf0f1;border-color:transparent;color:#282f2f}html.theme--documenter-dark .button.is-light:hover,html.theme--documenter-dark .button.is-light.is-hovered{background-color:#e5eaec;border-color:transparent;color:#282f2f}html.theme--documenter-dark .button.is-light:focus,html.theme--documenter-dark .button.is-light.is-focused{border-color:transparent;color:#282f2f}html.theme--documenter-dark .button.is-light:focus:not(:active),html.theme--documenter-dark .button.is-light.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(236,240,241,0.25)}html.theme--documenter-dark .button.is-light:active,html.theme--documenter-dark .button.is-light.is-active{background-color:#dde4e6;border-color:transparent;color:#282f2f}html.theme--documenter-dark .button.is-light[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light{background-color:#ecf0f1;border-color:transparent;box-shadow:none}html.theme--documenter-dark .button.is-light.is-inverted{background-color:#282f2f;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-inverted:hover,html.theme--documenter-dark .button.is-light.is-inverted.is-hovered{background-color:#1d2122}html.theme--documenter-dark .button.is-light.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light.is-inverted{background-color:#282f2f;border-color:transparent;box-shadow:none;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-loading::after{border-color:transparent transparent #282f2f #282f2f !important}html.theme--documenter-dark .button.is-light.is-outlined{background-color:transparent;border-color:#ecf0f1;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-outlined:hover,html.theme--documenter-dark .button.is-light.is-outlined.is-hovered,html.theme--documenter-dark .button.is-light.is-outlined:focus,html.theme--documenter-dark .button.is-light.is-outlined.is-focused{background-color:#ecf0f1;border-color:#ecf0f1;color:#282f2f}html.theme--documenter-dark .button.is-light.is-outlined.is-loading::after{border-color:transparent transparent #ecf0f1 #ecf0f1 !important}html.theme--documenter-dark .button.is-light.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-light.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-light.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-light.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #282f2f #282f2f !important}html.theme--documenter-dark .button.is-light.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light.is-outlined{background-color:transparent;border-color:#ecf0f1;box-shadow:none;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:#282f2f;color:#282f2f}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-focused{background-color:#282f2f;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #ecf0f1 #ecf0f1 !important}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:#282f2f;box-shadow:none;color:#282f2f}html.theme--documenter-dark .button.is-dark,html.theme--documenter-dark .content kbd.button{background-color:#282f2f;border-color:transparent;color:#ecf0f1}html.theme--documenter-dark .button.is-dark:hover,html.theme--documenter-dark .content kbd.button:hover,html.theme--documenter-dark .button.is-dark.is-hovered,html.theme--documenter-dark .content kbd.button.is-hovered{background-color:#232829;border-color:transparent;color:#ecf0f1}html.theme--documenter-dark .button.is-dark:focus,html.theme--documenter-dark .content kbd.button:focus,html.theme--documenter-dark .button.is-dark.is-focused,html.theme--documenter-dark .content kbd.button.is-focused{border-color:transparent;color:#ecf0f1}html.theme--documenter-dark .button.is-dark:focus:not(:active),html.theme--documenter-dark .content kbd.button:focus:not(:active),html.theme--documenter-dark .button.is-dark.is-focused:not(:active),html.theme--documenter-dark .content kbd.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(40,47,47,0.25)}html.theme--documenter-dark .button.is-dark:active,html.theme--documenter-dark .content kbd.button:active,html.theme--documenter-dark .button.is-dark.is-active,html.theme--documenter-dark .content kbd.button.is-active{background-color:#1d2122;border-color:transparent;color:#ecf0f1}html.theme--documenter-dark .button.is-dark[disabled],html.theme--documenter-dark .content kbd.button[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark,fieldset[disabled] html.theme--documenter-dark .content kbd.button{background-color:#282f2f;border-color:transparent;box-shadow:none}html.theme--documenter-dark .button.is-dark.is-inverted,html.theme--documenter-dark .content kbd.button.is-inverted{background-color:#ecf0f1;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-inverted:hover,html.theme--documenter-dark .content kbd.button.is-inverted:hover,html.theme--documenter-dark .button.is-dark.is-inverted.is-hovered,html.theme--documenter-dark .content kbd.button.is-inverted.is-hovered{background-color:#dde4e6}html.theme--documenter-dark .button.is-dark.is-inverted[disabled],html.theme--documenter-dark .content kbd.button.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-inverted,fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-inverted{background-color:#ecf0f1;border-color:transparent;box-shadow:none;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-loading::after,html.theme--documenter-dark .content kbd.button.is-loading::after{border-color:transparent transparent #ecf0f1 #ecf0f1 !important}html.theme--documenter-dark .button.is-dark.is-outlined,html.theme--documenter-dark .content kbd.button.is-outlined{background-color:transparent;border-color:#282f2f;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-outlined:hover,html.theme--documenter-dark .content kbd.button.is-outlined:hover,html.theme--documenter-dark .button.is-dark.is-outlined.is-hovered,html.theme--documenter-dark .content kbd.button.is-outlined.is-hovered,html.theme--documenter-dark .button.is-dark.is-outlined:focus,html.theme--documenter-dark .content kbd.button.is-outlined:focus,html.theme--documenter-dark .button.is-dark.is-outlined.is-focused,html.theme--documenter-dark .content kbd.button.is-outlined.is-focused{background-color:#282f2f;border-color:#282f2f;color:#ecf0f1}html.theme--documenter-dark .button.is-dark.is-outlined.is-loading::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading::after{border-color:transparent transparent #282f2f #282f2f !important}html.theme--documenter-dark .button.is-dark.is-outlined.is-loading:hover::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-dark.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-dark.is-outlined.is-loading:focus::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-dark.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #ecf0f1 #ecf0f1 !important}html.theme--documenter-dark .button.is-dark.is-outlined[disabled],html.theme--documenter-dark .content kbd.button.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-outlined,fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-outlined{background-color:transparent;border-color:#282f2f;box-shadow:none;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#ecf0f1;color:#ecf0f1}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined:hover,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined:focus,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-focused,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-focused{background-color:#ecf0f1;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #282f2f #282f2f !important}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined[disabled],html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined,fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#ecf0f1;box-shadow:none;color:#ecf0f1}html.theme--documenter-dark .button.is-primary,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink{background-color:#375a7f;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary:hover,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-hovered.docs-sourcelink{background-color:#335476;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary:focus,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:focus,html.theme--documenter-dark .button.is-primary.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-focused.docs-sourcelink{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary:focus:not(:active),html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:focus:not(:active),html.theme--documenter-dark .button.is-primary.is-focused:not(:active),html.theme--documenter-dark .docstring>section>a.button.is-focused.docs-sourcelink:not(:active){box-shadow:0 0 0 0.125em rgba(55,90,127,0.25)}html.theme--documenter-dark .button.is-primary:active,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:active,html.theme--documenter-dark .button.is-primary.is-active,html.theme--documenter-dark .docstring>section>a.button.is-active.docs-sourcelink{background-color:#2f4d6d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary[disabled],html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink{background-color:#375a7f;border-color:transparent;box-shadow:none}html.theme--documenter-dark .button.is-primary.is-inverted,html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-inverted:hover,html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-inverted.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-hovered.docs-sourcelink{background-color:#f2f2f2}html.theme--documenter-dark .button.is-primary.is-inverted[disabled],html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-inverted,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;border-color:transparent;box-shadow:none;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-loading::after,html.theme--documenter-dark .docstring>section>a.button.is-loading.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-primary.is-outlined,html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#375a7f;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-outlined:hover,html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-outlined.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-hovered.docs-sourcelink,html.theme--documenter-dark .button.is-primary.is-outlined:focus,html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink:focus,html.theme--documenter-dark .button.is-primary.is-outlined.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-focused.docs-sourcelink{background-color:#375a7f;border-color:#375a7f;color:#fff}html.theme--documenter-dark .button.is-primary.is-outlined.is-loading::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink::after{border-color:transparent transparent #375a7f #375a7f !important}html.theme--documenter-dark .button.is-primary.is-outlined.is-loading:hover::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--documenter-dark .button.is-primary.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--documenter-dark .button.is-primary.is-outlined.is-loading:focus::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--documenter-dark .button.is-primary.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-primary.is-outlined[disabled],html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-outlined,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#375a7f;box-shadow:none;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined:hover,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-hovered.docs-sourcelink,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined:focus,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:focus,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-focused.docs-sourcelink{background-color:#fff;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #375a7f #375a7f !important}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined[disabled],html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-link{background-color:#1abc9c;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link:hover,html.theme--documenter-dark .button.is-link.is-hovered{background-color:#18b193;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link:focus,html.theme--documenter-dark .button.is-link.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link:focus:not(:active),html.theme--documenter-dark .button.is-link.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .button.is-link:active,html.theme--documenter-dark .button.is-link.is-active{background-color:#17a689;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link{background-color:#1abc9c;border-color:transparent;box-shadow:none}html.theme--documenter-dark .button.is-link.is-inverted{background-color:#fff;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-inverted:hover,html.theme--documenter-dark .button.is-link.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-link.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-link.is-outlined{background-color:transparent;border-color:#1abc9c;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-outlined:hover,html.theme--documenter-dark .button.is-link.is-outlined.is-hovered,html.theme--documenter-dark .button.is-link.is-outlined:focus,html.theme--documenter-dark .button.is-link.is-outlined.is-focused{background-color:#1abc9c;border-color:#1abc9c;color:#fff}html.theme--documenter-dark .button.is-link.is-outlined.is-loading::after{border-color:transparent transparent #1abc9c #1abc9c !important}html.theme--documenter-dark .button.is-link.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-link.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-link.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-link.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-link.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link.is-outlined{background-color:transparent;border-color:#1abc9c;box-shadow:none;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-focused{background-color:#fff;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #1abc9c #1abc9c !important}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-info{background-color:#024c7d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info:hover,html.theme--documenter-dark .button.is-info.is-hovered{background-color:#024470;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info:focus,html.theme--documenter-dark .button.is-info.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info:focus:not(:active),html.theme--documenter-dark .button.is-info.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(2,76,125,0.25)}html.theme--documenter-dark .button.is-info:active,html.theme--documenter-dark .button.is-info.is-active{background-color:#023d64;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info{background-color:#024c7d;border-color:transparent;box-shadow:none}html.theme--documenter-dark .button.is-info.is-inverted{background-color:#fff;color:#024c7d}html.theme--documenter-dark .button.is-info.is-inverted:hover,html.theme--documenter-dark .button.is-info.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-info.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#024c7d}html.theme--documenter-dark .button.is-info.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-info.is-outlined{background-color:transparent;border-color:#024c7d;color:#024c7d}html.theme--documenter-dark .button.is-info.is-outlined:hover,html.theme--documenter-dark .button.is-info.is-outlined.is-hovered,html.theme--documenter-dark .button.is-info.is-outlined:focus,html.theme--documenter-dark .button.is-info.is-outlined.is-focused{background-color:#024c7d;border-color:#024c7d;color:#fff}html.theme--documenter-dark .button.is-info.is-outlined.is-loading::after{border-color:transparent transparent #024c7d #024c7d !important}html.theme--documenter-dark .button.is-info.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-info.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-info.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-info.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-info.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info.is-outlined{background-color:transparent;border-color:#024c7d;box-shadow:none;color:#024c7d}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-focused{background-color:#fff;color:#024c7d}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #024c7d #024c7d !important}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-success{background-color:#008438;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success:hover,html.theme--documenter-dark .button.is-success.is-hovered{background-color:#073;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success:focus,html.theme--documenter-dark .button.is-success.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success:focus:not(:active),html.theme--documenter-dark .button.is-success.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(0,132,56,0.25)}html.theme--documenter-dark .button.is-success:active,html.theme--documenter-dark .button.is-success.is-active{background-color:#006b2d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success{background-color:#008438;border-color:transparent;box-shadow:none}html.theme--documenter-dark .button.is-success.is-inverted{background-color:#fff;color:#008438}html.theme--documenter-dark .button.is-success.is-inverted:hover,html.theme--documenter-dark .button.is-success.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-success.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#008438}html.theme--documenter-dark .button.is-success.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-success.is-outlined{background-color:transparent;border-color:#008438;color:#008438}html.theme--documenter-dark .button.is-success.is-outlined:hover,html.theme--documenter-dark .button.is-success.is-outlined.is-hovered,html.theme--documenter-dark .button.is-success.is-outlined:focus,html.theme--documenter-dark .button.is-success.is-outlined.is-focused{background-color:#008438;border-color:#008438;color:#fff}html.theme--documenter-dark .button.is-success.is-outlined.is-loading::after{border-color:transparent transparent #008438 #008438 !important}html.theme--documenter-dark .button.is-success.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-success.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-success.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-success.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-success.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success.is-outlined{background-color:transparent;border-color:#008438;box-shadow:none;color:#008438}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-focused{background-color:#fff;color:#008438}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #008438 #008438 !important}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-warning{background-color:#ad8100;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning:hover,html.theme--documenter-dark .button.is-warning.is-hovered{background-color:#a07700;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning:focus,html.theme--documenter-dark .button.is-warning.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning:focus:not(:active),html.theme--documenter-dark .button.is-warning.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(173,129,0,0.25)}html.theme--documenter-dark .button.is-warning:active,html.theme--documenter-dark .button.is-warning.is-active{background-color:#946e00;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning{background-color:#ad8100;border-color:transparent;box-shadow:none}html.theme--documenter-dark .button.is-warning.is-inverted{background-color:#fff;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-inverted:hover,html.theme--documenter-dark .button.is-warning.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-warning.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-warning.is-outlined{background-color:transparent;border-color:#ad8100;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-outlined:hover,html.theme--documenter-dark .button.is-warning.is-outlined.is-hovered,html.theme--documenter-dark .button.is-warning.is-outlined:focus,html.theme--documenter-dark .button.is-warning.is-outlined.is-focused{background-color:#ad8100;border-color:#ad8100;color:#fff}html.theme--documenter-dark .button.is-warning.is-outlined.is-loading::after{border-color:transparent transparent #ad8100 #ad8100 !important}html.theme--documenter-dark .button.is-warning.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-warning.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-warning.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-warning.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-warning.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-outlined{background-color:transparent;border-color:#ad8100;box-shadow:none;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-focused{background-color:#fff;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #ad8100 #ad8100 !important}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-danger{background-color:#9e1b0d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger:hover,html.theme--documenter-dark .button.is-danger.is-hovered{background-color:#92190c;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger:focus,html.theme--documenter-dark .button.is-danger.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger:focus:not(:active),html.theme--documenter-dark .button.is-danger.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(158,27,13,0.25)}html.theme--documenter-dark .button.is-danger:active,html.theme--documenter-dark .button.is-danger.is-active{background-color:#86170b;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger{background-color:#9e1b0d;border-color:transparent;box-shadow:none}html.theme--documenter-dark .button.is-danger.is-inverted{background-color:#fff;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-inverted:hover,html.theme--documenter-dark .button.is-danger.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-danger.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-danger.is-outlined{background-color:transparent;border-color:#9e1b0d;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-outlined:hover,html.theme--documenter-dark .button.is-danger.is-outlined.is-hovered,html.theme--documenter-dark .button.is-danger.is-outlined:focus,html.theme--documenter-dark .button.is-danger.is-outlined.is-focused{background-color:#9e1b0d;border-color:#9e1b0d;color:#fff}html.theme--documenter-dark .button.is-danger.is-outlined.is-loading::after{border-color:transparent transparent #9e1b0d #9e1b0d !important}html.theme--documenter-dark .button.is-danger.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-danger.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-danger.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-danger.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-danger.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-outlined{background-color:transparent;border-color:#9e1b0d;box-shadow:none;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-focused{background-color:#fff;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #9e1b0d #9e1b0d !important}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.button{border-radius:3px;font-size:.85em}html.theme--documenter-dark .button.is-normal{font-size:15px}html.theme--documenter-dark .button.is-medium{font-size:1.25rem}html.theme--documenter-dark .button.is-large{font-size:1.5rem}html.theme--documenter-dark .button[disabled],fieldset[disabled] html.theme--documenter-dark .button{background-color:#8c9b9d;border-color:#dbdee0;box-shadow:none;opacity:.5}html.theme--documenter-dark .button.is-fullwidth{display:flex;width:100%}html.theme--documenter-dark .button.is-loading{color:transparent !important;pointer-events:none}html.theme--documenter-dark .button.is-loading::after{position:absolute;left:calc(50% - (1em / 2));top:calc(50% - (1em / 2));position:absolute !important}html.theme--documenter-dark .button.is-static{background-color:#282f2f;border-color:#5e6d6f;color:#dbdee0;box-shadow:none;pointer-events:none}html.theme--documenter-dark .button.is-rounded,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.button{border-radius:290486px;padding-left:1em;padding-right:1em}html.theme--documenter-dark .buttons{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--documenter-dark .buttons .button{margin-bottom:0.5rem}html.theme--documenter-dark .buttons .button:not(:last-child):not(.is-fullwidth){margin-right:0.5rem}html.theme--documenter-dark .buttons:last-child{margin-bottom:-0.5rem}html.theme--documenter-dark .buttons:not(:last-child){margin-bottom:1rem}html.theme--documenter-dark .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large){border-radius:3px;font-size:.85em}html.theme--documenter-dark .buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large){font-size:1.25rem}html.theme--documenter-dark .buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium){font-size:1.5rem}html.theme--documenter-dark .buttons.has-addons .button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}html.theme--documenter-dark .buttons.has-addons .button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}html.theme--documenter-dark .buttons.has-addons .button:last-child{margin-right:0}html.theme--documenter-dark .buttons.has-addons .button:hover,html.theme--documenter-dark .buttons.has-addons .button.is-hovered{z-index:2}html.theme--documenter-dark .buttons.has-addons .button:focus,html.theme--documenter-dark .buttons.has-addons .button.is-focused,html.theme--documenter-dark .buttons.has-addons .button:active,html.theme--documenter-dark .buttons.has-addons .button.is-active,html.theme--documenter-dark .buttons.has-addons .button.is-selected{z-index:3}html.theme--documenter-dark .buttons.has-addons .button:focus:hover,html.theme--documenter-dark .buttons.has-addons .button.is-focused:hover,html.theme--documenter-dark .buttons.has-addons .button:active:hover,html.theme--documenter-dark .buttons.has-addons .button.is-active:hover,html.theme--documenter-dark .buttons.has-addons .button.is-selected:hover{z-index:4}html.theme--documenter-dark .buttons.has-addons .button.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .buttons.is-centered{justify-content:center}html.theme--documenter-dark .buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}html.theme--documenter-dark .buttons.is-right{justify-content:flex-end}html.theme--documenter-dark .buttons.is-right:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}html.theme--documenter-dark .container{flex-grow:1;margin:0 auto;position:relative;width:auto}@media screen and (min-width: 1056px){html.theme--documenter-dark .container{max-width:992px}html.theme--documenter-dark .container.is-fluid{margin-left:32px;margin-right:32px;max-width:none}}@media screen and (max-width: 1215px){html.theme--documenter-dark .container.is-widescreen{max-width:1152px}}@media screen and (max-width: 1407px){html.theme--documenter-dark .container.is-fullhd{max-width:1344px}}@media screen and (min-width: 1216px){html.theme--documenter-dark .container{max-width:1152px}}@media screen and (min-width: 1408px){html.theme--documenter-dark .container{max-width:1344px}}html.theme--documenter-dark .content li+li{margin-top:0.25em}html.theme--documenter-dark .content p:not(:last-child),html.theme--documenter-dark .content dl:not(:last-child),html.theme--documenter-dark .content ol:not(:last-child),html.theme--documenter-dark .content ul:not(:last-child),html.theme--documenter-dark .content blockquote:not(:last-child),html.theme--documenter-dark .content pre:not(:last-child),html.theme--documenter-dark .content table:not(:last-child){margin-bottom:1em}html.theme--documenter-dark .content h1,html.theme--documenter-dark .content h2,html.theme--documenter-dark .content h3,html.theme--documenter-dark .content h4,html.theme--documenter-dark .content h5,html.theme--documenter-dark .content h6{color:#f2f2f2;font-weight:600;line-height:1.125}html.theme--documenter-dark .content h1{font-size:2em;margin-bottom:0.5em}html.theme--documenter-dark .content h1:not(:first-child){margin-top:1em}html.theme--documenter-dark .content h2{font-size:1.75em;margin-bottom:0.5714em}html.theme--documenter-dark .content h2:not(:first-child){margin-top:1.1428em}html.theme--documenter-dark .content h3{font-size:1.5em;margin-bottom:0.6666em}html.theme--documenter-dark .content h3:not(:first-child){margin-top:1.3333em}html.theme--documenter-dark .content h4{font-size:1.25em;margin-bottom:0.8em}html.theme--documenter-dark .content h5{font-size:1.125em;margin-bottom:0.8888em}html.theme--documenter-dark .content h6{font-size:1em;margin-bottom:1em}html.theme--documenter-dark .content blockquote{background-color:#282f2f;border-left:5px solid #5e6d6f;padding:1.25em 1.5em}html.theme--documenter-dark .content ol{list-style-position:outside;margin-left:2em;margin-top:1em}html.theme--documenter-dark .content ol:not([type]){list-style-type:decimal}html.theme--documenter-dark .content ol.is-lower-alpha:not([type]){list-style-type:lower-alpha}html.theme--documenter-dark .content ol.is-lower-roman:not([type]){list-style-type:lower-roman}html.theme--documenter-dark .content ol.is-upper-alpha:not([type]){list-style-type:upper-alpha}html.theme--documenter-dark .content ol.is-upper-roman:not([type]){list-style-type:upper-roman}html.theme--documenter-dark .content ul{list-style:disc outside;margin-left:2em;margin-top:1em}html.theme--documenter-dark .content ul ul{list-style-type:circle;margin-top:0.5em}html.theme--documenter-dark .content ul ul ul{list-style-type:square}html.theme--documenter-dark .content dd{margin-left:2em}html.theme--documenter-dark .content figure{margin-left:2em;margin-right:2em;text-align:center}html.theme--documenter-dark .content figure:not(:first-child){margin-top:2em}html.theme--documenter-dark .content figure:not(:last-child){margin-bottom:2em}html.theme--documenter-dark .content figure img{display:inline-block}html.theme--documenter-dark .content figure figcaption{font-style:italic}html.theme--documenter-dark .content pre{-webkit-overflow-scrolling:touch;overflow-x:auto;padding:0;white-space:pre;word-wrap:normal}html.theme--documenter-dark .content sup,html.theme--documenter-dark .content sub{font-size:75%}html.theme--documenter-dark .content table{width:100%}html.theme--documenter-dark .content table td,html.theme--documenter-dark .content table th{border:1px solid #5e6d6f;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--documenter-dark .content table th{color:#f2f2f2}html.theme--documenter-dark .content table th:not([align]){text-align:left}html.theme--documenter-dark .content table thead td,html.theme--documenter-dark .content table thead th{border-width:0 0 2px;color:#f2f2f2}html.theme--documenter-dark .content table tfoot td,html.theme--documenter-dark .content table tfoot th{border-width:2px 0 0;color:#f2f2f2}html.theme--documenter-dark .content table tbody tr:last-child td,html.theme--documenter-dark .content table tbody tr:last-child th{border-bottom-width:0}html.theme--documenter-dark .content .tabs li+li{margin-top:0}html.theme--documenter-dark .content.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.content{font-size:.85em}html.theme--documenter-dark .content.is-medium{font-size:1.25rem}html.theme--documenter-dark .content.is-large{font-size:1.5rem}html.theme--documenter-dark .icon{align-items:center;display:inline-flex;justify-content:center;height:1.5rem;width:1.5rem}html.theme--documenter-dark .icon.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.icon{height:1rem;width:1rem}html.theme--documenter-dark .icon.is-medium{height:2rem;width:2rem}html.theme--documenter-dark .icon.is-large{height:3rem;width:3rem}html.theme--documenter-dark .image,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img{display:block;position:relative}html.theme--documenter-dark .image img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img img{display:block;height:auto;width:100%}html.theme--documenter-dark .image img.is-rounded,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img img.is-rounded{border-radius:290486px}html.theme--documenter-dark .image.is-square img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--documenter-dark .image.is-square .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--documenter-dark .image.is-1by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--documenter-dark .image.is-1by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--documenter-dark .image.is-5by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--documenter-dark .image.is-5by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--documenter-dark .image.is-4by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--documenter-dark .image.is-4by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--documenter-dark .image.is-3by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--documenter-dark .image.is-3by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--documenter-dark .image.is-5by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--documenter-dark .image.is-5by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--documenter-dark .image.is-16by9 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--documenter-dark .image.is-16by9 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--documenter-dark .image.is-2by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--documenter-dark .image.is-2by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--documenter-dark .image.is-3by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--documenter-dark .image.is-3by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--documenter-dark .image.is-4by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--documenter-dark .image.is-4by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--documenter-dark .image.is-3by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--documenter-dark .image.is-3by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--documenter-dark .image.is-2by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--documenter-dark .image.is-2by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--documenter-dark .image.is-3by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--documenter-dark .image.is-3by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--documenter-dark .image.is-9by16 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--documenter-dark .image.is-9by16 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--documenter-dark .image.is-1by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--documenter-dark .image.is-1by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--documenter-dark .image.is-1by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--documenter-dark .image.is-1by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio{height:100%;width:100%}html.theme--documenter-dark .image.is-square,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square,html.theme--documenter-dark .image.is-1by1,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1{padding-top:100%}html.theme--documenter-dark .image.is-5by4,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4{padding-top:80%}html.theme--documenter-dark .image.is-4by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3{padding-top:75%}html.theme--documenter-dark .image.is-3by2,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2{padding-top:66.6666%}html.theme--documenter-dark .image.is-5by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3{padding-top:60%}html.theme--documenter-dark .image.is-16by9,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9{padding-top:56.25%}html.theme--documenter-dark .image.is-2by1,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1{padding-top:50%}html.theme--documenter-dark .image.is-3by1,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1{padding-top:33.3333%}html.theme--documenter-dark .image.is-4by5,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5{padding-top:125%}html.theme--documenter-dark .image.is-3by4,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4{padding-top:133.3333%}html.theme--documenter-dark .image.is-2by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3{padding-top:150%}html.theme--documenter-dark .image.is-3by5,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5{padding-top:166.6666%}html.theme--documenter-dark .image.is-9by16,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16{padding-top:177.7777%}html.theme--documenter-dark .image.is-1by2,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2{padding-top:200%}html.theme--documenter-dark .image.is-1by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3{padding-top:300%}html.theme--documenter-dark .image.is-16x16,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16x16{height:16px;width:16px}html.theme--documenter-dark .image.is-24x24,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-24x24{height:24px;width:24px}html.theme--documenter-dark .image.is-32x32,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-32x32{height:32px;width:32px}html.theme--documenter-dark .image.is-48x48,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-48x48{height:48px;width:48px}html.theme--documenter-dark .image.is-64x64,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-64x64{height:64px;width:64px}html.theme--documenter-dark .image.is-96x96,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-96x96{height:96px;width:96px}html.theme--documenter-dark .image.is-128x128,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-128x128{height:128px;width:128px}html.theme--documenter-dark .notification{background-color:#282f2f;border-radius:.4em;padding:1.25rem 2.5rem 1.25rem 1.5rem;position:relative}html.theme--documenter-dark .notification a:not(.button):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--documenter-dark .notification strong{color:currentColor}html.theme--documenter-dark .notification code,html.theme--documenter-dark .notification pre{background:#fff}html.theme--documenter-dark .notification pre code{background:transparent}html.theme--documenter-dark .notification>.delete{position:absolute;right:0.5rem;top:0.5rem}html.theme--documenter-dark .notification .title,html.theme--documenter-dark .notification .subtitle,html.theme--documenter-dark .notification .content{color:currentColor}html.theme--documenter-dark .notification.is-white{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .notification.is-black{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .notification.is-light{background-color:#ecf0f1;color:#282f2f}html.theme--documenter-dark .notification.is-dark,html.theme--documenter-dark .content kbd.notification{background-color:#282f2f;color:#ecf0f1}html.theme--documenter-dark .notification.is-primary,html.theme--documenter-dark .docstring>section>a.notification.docs-sourcelink{background-color:#375a7f;color:#fff}html.theme--documenter-dark .notification.is-link{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .notification.is-info{background-color:#024c7d;color:#fff}html.theme--documenter-dark .notification.is-success{background-color:#008438;color:#fff}html.theme--documenter-dark .notification.is-warning{background-color:#ad8100;color:#fff}html.theme--documenter-dark .notification.is-danger{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:290486px;display:block;height:15px;overflow:hidden;padding:0;width:100%}html.theme--documenter-dark .progress::-webkit-progress-bar{background-color:#5e6d6f}html.theme--documenter-dark .progress::-webkit-progress-value{background-color:#dbdee0}html.theme--documenter-dark .progress::-moz-progress-bar{background-color:#dbdee0}html.theme--documenter-dark .progress::-ms-fill{background-color:#dbdee0;border:none}html.theme--documenter-dark .progress.is-white::-webkit-progress-value{background-color:#fff}html.theme--documenter-dark .progress.is-white::-moz-progress-bar{background-color:#fff}html.theme--documenter-dark .progress.is-white::-ms-fill{background-color:#fff}html.theme--documenter-dark .progress.is-white:indeterminate{background-image:linear-gradient(to right, #fff 30%, #5e6d6f 30%)}html.theme--documenter-dark .progress.is-black::-webkit-progress-value{background-color:#0a0a0a}html.theme--documenter-dark .progress.is-black::-moz-progress-bar{background-color:#0a0a0a}html.theme--documenter-dark .progress.is-black::-ms-fill{background-color:#0a0a0a}html.theme--documenter-dark .progress.is-black:indeterminate{background-image:linear-gradient(to right, #0a0a0a 30%, #5e6d6f 30%)}html.theme--documenter-dark .progress.is-light::-webkit-progress-value{background-color:#ecf0f1}html.theme--documenter-dark .progress.is-light::-moz-progress-bar{background-color:#ecf0f1}html.theme--documenter-dark .progress.is-light::-ms-fill{background-color:#ecf0f1}html.theme--documenter-dark .progress.is-light:indeterminate{background-image:linear-gradient(to right, #ecf0f1 30%, #5e6d6f 30%)}html.theme--documenter-dark .progress.is-dark::-webkit-progress-value,html.theme--documenter-dark .content kbd.progress::-webkit-progress-value{background-color:#282f2f}html.theme--documenter-dark .progress.is-dark::-moz-progress-bar,html.theme--documenter-dark .content kbd.progress::-moz-progress-bar{background-color:#282f2f}html.theme--documenter-dark .progress.is-dark::-ms-fill,html.theme--documenter-dark .content kbd.progress::-ms-fill{background-color:#282f2f}html.theme--documenter-dark .progress.is-dark:indeterminate,html.theme--documenter-dark .content kbd.progress:indeterminate{background-image:linear-gradient(to right, #282f2f 30%, #5e6d6f 30%)}html.theme--documenter-dark .progress.is-primary::-webkit-progress-value,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink::-webkit-progress-value{background-color:#375a7f}html.theme--documenter-dark .progress.is-primary::-moz-progress-bar,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink::-moz-progress-bar{background-color:#375a7f}html.theme--documenter-dark .progress.is-primary::-ms-fill,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink::-ms-fill{background-color:#375a7f}html.theme--documenter-dark .progress.is-primary:indeterminate,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink:indeterminate{background-image:linear-gradient(to right, #375a7f 30%, #5e6d6f 30%)}html.theme--documenter-dark .progress.is-link::-webkit-progress-value{background-color:#1abc9c}html.theme--documenter-dark .progress.is-link::-moz-progress-bar{background-color:#1abc9c}html.theme--documenter-dark .progress.is-link::-ms-fill{background-color:#1abc9c}html.theme--documenter-dark .progress.is-link:indeterminate{background-image:linear-gradient(to right, #1abc9c 30%, #5e6d6f 30%)}html.theme--documenter-dark .progress.is-info::-webkit-progress-value{background-color:#024c7d}html.theme--documenter-dark .progress.is-info::-moz-progress-bar{background-color:#024c7d}html.theme--documenter-dark .progress.is-info::-ms-fill{background-color:#024c7d}html.theme--documenter-dark .progress.is-info:indeterminate{background-image:linear-gradient(to right, #024c7d 30%, #5e6d6f 30%)}html.theme--documenter-dark .progress.is-success::-webkit-progress-value{background-color:#008438}html.theme--documenter-dark .progress.is-success::-moz-progress-bar{background-color:#008438}html.theme--documenter-dark .progress.is-success::-ms-fill{background-color:#008438}html.theme--documenter-dark .progress.is-success:indeterminate{background-image:linear-gradient(to right, #008438 30%, #5e6d6f 30%)}html.theme--documenter-dark .progress.is-warning::-webkit-progress-value{background-color:#ad8100}html.theme--documenter-dark .progress.is-warning::-moz-progress-bar{background-color:#ad8100}html.theme--documenter-dark .progress.is-warning::-ms-fill{background-color:#ad8100}html.theme--documenter-dark .progress.is-warning:indeterminate{background-image:linear-gradient(to right, #ad8100 30%, #5e6d6f 30%)}html.theme--documenter-dark .progress.is-danger::-webkit-progress-value{background-color:#9e1b0d}html.theme--documenter-dark .progress.is-danger::-moz-progress-bar{background-color:#9e1b0d}html.theme--documenter-dark .progress.is-danger::-ms-fill{background-color:#9e1b0d}html.theme--documenter-dark .progress.is-danger:indeterminate{background-image:linear-gradient(to right, #9e1b0d 30%, #5e6d6f 30%)}html.theme--documenter-dark .progress:indeterminate{animation-duration:1.5s;animation-iteration-count:infinite;animation-name:moveIndeterminate;animation-timing-function:linear;background-color:#5e6d6f;background-image:linear-gradient(to right, #fff 30%, #5e6d6f 30%);background-position:top left;background-repeat:no-repeat;background-size:150% 150%}html.theme--documenter-dark .progress:indeterminate::-webkit-progress-bar{background-color:transparent}html.theme--documenter-dark .progress:indeterminate::-moz-progress-bar{background-color:transparent}html.theme--documenter-dark .progress.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.progress{height:.85em}html.theme--documenter-dark .progress.is-medium{height:1.25rem}html.theme--documenter-dark .progress.is-large{height:1.5rem}@keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}html.theme--documenter-dark .table{background-color:#343c3d;color:#fff}html.theme--documenter-dark .table td,html.theme--documenter-dark .table th{border:1px solid #5e6d6f;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--documenter-dark .table td.is-white,html.theme--documenter-dark .table th.is-white{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--documenter-dark .table td.is-black,html.theme--documenter-dark .table th.is-black{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--documenter-dark .table td.is-light,html.theme--documenter-dark .table th.is-light{background-color:#ecf0f1;border-color:#ecf0f1;color:#282f2f}html.theme--documenter-dark .table td.is-dark,html.theme--documenter-dark .table th.is-dark{background-color:#282f2f;border-color:#282f2f;color:#ecf0f1}html.theme--documenter-dark .table td.is-primary,html.theme--documenter-dark .table th.is-primary{background-color:#375a7f;border-color:#375a7f;color:#fff}html.theme--documenter-dark .table td.is-link,html.theme--documenter-dark .table th.is-link{background-color:#1abc9c;border-color:#1abc9c;color:#fff}html.theme--documenter-dark .table td.is-info,html.theme--documenter-dark .table th.is-info{background-color:#024c7d;border-color:#024c7d;color:#fff}html.theme--documenter-dark .table td.is-success,html.theme--documenter-dark .table th.is-success{background-color:#008438;border-color:#008438;color:#fff}html.theme--documenter-dark .table td.is-warning,html.theme--documenter-dark .table th.is-warning{background-color:#ad8100;border-color:#ad8100;color:#fff}html.theme--documenter-dark .table td.is-danger,html.theme--documenter-dark .table th.is-danger{background-color:#9e1b0d;border-color:#9e1b0d;color:#fff}html.theme--documenter-dark .table td.is-narrow,html.theme--documenter-dark .table th.is-narrow{white-space:nowrap;width:1%}html.theme--documenter-dark .table td.is-selected,html.theme--documenter-dark .table th.is-selected{background-color:#375a7f;color:#fff}html.theme--documenter-dark .table td.is-selected a,html.theme--documenter-dark .table td.is-selected strong,html.theme--documenter-dark .table th.is-selected a,html.theme--documenter-dark .table th.is-selected strong{color:currentColor}html.theme--documenter-dark .table th{color:#f2f2f2}html.theme--documenter-dark .table th:not([align]){text-align:left}html.theme--documenter-dark .table tr.is-selected{background-color:#375a7f;color:#fff}html.theme--documenter-dark .table tr.is-selected a,html.theme--documenter-dark .table tr.is-selected strong{color:currentColor}html.theme--documenter-dark .table tr.is-selected td,html.theme--documenter-dark .table tr.is-selected th{border-color:#fff;color:currentColor}html.theme--documenter-dark .table thead{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .table thead td,html.theme--documenter-dark .table thead th{border-width:0 0 2px;color:#f2f2f2}html.theme--documenter-dark .table tfoot{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .table tfoot td,html.theme--documenter-dark .table tfoot th{border-width:2px 0 0;color:#f2f2f2}html.theme--documenter-dark .table tbody{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .table tbody tr:last-child td,html.theme--documenter-dark .table tbody tr:last-child th{border-bottom-width:0}html.theme--documenter-dark .table.is-bordered td,html.theme--documenter-dark .table.is-bordered th{border-width:1px}html.theme--documenter-dark .table.is-bordered tr:last-child td,html.theme--documenter-dark .table.is-bordered tr:last-child th{border-bottom-width:1px}html.theme--documenter-dark .table.is-fullwidth{width:100%}html.theme--documenter-dark .table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#282f2f}html.theme--documenter-dark .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover{background-color:#282f2f}html.theme--documenter-dark .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even){background-color:#2d3435}html.theme--documenter-dark .table.is-narrow td,html.theme--documenter-dark .table.is-narrow th{padding:0.25em 0.5em}html.theme--documenter-dark .table.is-striped tbody tr:not(.is-selected):nth-child(even){background-color:#282f2f}html.theme--documenter-dark .table-container{-webkit-overflow-scrolling:touch;overflow:auto;overflow-y:hidden;max-width:100%}html.theme--documenter-dark .tags{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--documenter-dark .tags .tag,html.theme--documenter-dark .tags .content kbd,html.theme--documenter-dark .content .tags kbd,html.theme--documenter-dark .tags .docstring>section>a.docs-sourcelink{margin-bottom:0.5rem}html.theme--documenter-dark .tags .tag:not(:last-child),html.theme--documenter-dark .tags .content kbd:not(:last-child),html.theme--documenter-dark .content .tags kbd:not(:last-child),html.theme--documenter-dark .tags .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:0.5rem}html.theme--documenter-dark .tags:last-child{margin-bottom:-0.5rem}html.theme--documenter-dark .tags:not(:last-child){margin-bottom:1rem}html.theme--documenter-dark .tags.are-medium .tag:not(.is-normal):not(.is-large),html.theme--documenter-dark .tags.are-medium .content kbd:not(.is-normal):not(.is-large),html.theme--documenter-dark .content .tags.are-medium kbd:not(.is-normal):not(.is-large),html.theme--documenter-dark .tags.are-medium .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-large){font-size:15px}html.theme--documenter-dark .tags.are-large .tag:not(.is-normal):not(.is-medium),html.theme--documenter-dark .tags.are-large .content kbd:not(.is-normal):not(.is-medium),html.theme--documenter-dark .content .tags.are-large kbd:not(.is-normal):not(.is-medium),html.theme--documenter-dark .tags.are-large .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-medium){font-size:1.25rem}html.theme--documenter-dark .tags.is-centered{justify-content:center}html.theme--documenter-dark .tags.is-centered .tag,html.theme--documenter-dark .tags.is-centered .content kbd,html.theme--documenter-dark .content .tags.is-centered kbd,html.theme--documenter-dark .tags.is-centered .docstring>section>a.docs-sourcelink{margin-right:0.25rem;margin-left:0.25rem}html.theme--documenter-dark .tags.is-right{justify-content:flex-end}html.theme--documenter-dark .tags.is-right .tag:not(:first-child),html.theme--documenter-dark .tags.is-right .content kbd:not(:first-child),html.theme--documenter-dark .content .tags.is-right kbd:not(:first-child),html.theme--documenter-dark .tags.is-right .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0.5rem}html.theme--documenter-dark .tags.is-right .tag:not(:last-child),html.theme--documenter-dark .tags.is-right .content kbd:not(:last-child),html.theme--documenter-dark .content .tags.is-right kbd:not(:last-child),html.theme--documenter-dark .tags.is-right .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:0}html.theme--documenter-dark .tags.has-addons .tag,html.theme--documenter-dark .tags.has-addons .content kbd,html.theme--documenter-dark .content .tags.has-addons kbd,html.theme--documenter-dark .tags.has-addons .docstring>section>a.docs-sourcelink{margin-right:0}html.theme--documenter-dark .tags.has-addons .tag:not(:first-child),html.theme--documenter-dark .tags.has-addons .content kbd:not(:first-child),html.theme--documenter-dark .content .tags.has-addons kbd:not(:first-child),html.theme--documenter-dark .tags.has-addons .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0;border-bottom-left-radius:0;border-top-left-radius:0}html.theme--documenter-dark .tags.has-addons .tag:not(:last-child),html.theme--documenter-dark .tags.has-addons .content kbd:not(:last-child),html.theme--documenter-dark .content .tags.has-addons kbd:not(:last-child),html.theme--documenter-dark .tags.has-addons .docstring>section>a.docs-sourcelink:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}html.theme--documenter-dark .tag:not(body),html.theme--documenter-dark .content kbd:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body){align-items:center;background-color:#282f2f;border-radius:.4em;color:#fff;display:inline-flex;font-size:.85em;height:2em;justify-content:center;line-height:1.5;padding-left:0.75em;padding-right:0.75em;white-space:nowrap}html.theme--documenter-dark .tag:not(body) .delete,html.theme--documenter-dark .content kbd:not(body) .delete,html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .delete{margin-left:0.25rem;margin-right:-0.375rem}html.theme--documenter-dark .tag.is-white:not(body),html.theme--documenter-dark .content kbd.is-white:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-white:not(body){background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .tag.is-black:not(body),html.theme--documenter-dark .content kbd.is-black:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-black:not(body){background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .tag.is-light:not(body),html.theme--documenter-dark .content kbd.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#ecf0f1;color:#282f2f}html.theme--documenter-dark .tag.is-dark:not(body),html.theme--documenter-dark .content kbd:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-dark:not(body),html.theme--documenter-dark .content .docstring>section>kbd:not(body){background-color:#282f2f;color:#ecf0f1}html.theme--documenter-dark .tag.is-primary:not(body),html.theme--documenter-dark .content kbd.is-primary:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body){background-color:#375a7f;color:#fff}html.theme--documenter-dark .tag.is-link:not(body),html.theme--documenter-dark .content kbd.is-link:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-link:not(body){background-color:#1abc9c;color:#fff}html.theme--documenter-dark .tag.is-info:not(body),html.theme--documenter-dark .content kbd.is-info:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-info:not(body){background-color:#024c7d;color:#fff}html.theme--documenter-dark .tag.is-success:not(body),html.theme--documenter-dark .content kbd.is-success:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-success:not(body){background-color:#008438;color:#fff}html.theme--documenter-dark .tag.is-warning:not(body),html.theme--documenter-dark .content kbd.is-warning:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-warning:not(body){background-color:#ad8100;color:#fff}html.theme--documenter-dark .tag.is-danger:not(body),html.theme--documenter-dark .content kbd.is-danger:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-danger:not(body){background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .tag.is-normal:not(body),html.theme--documenter-dark .content kbd.is-normal:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-normal:not(body){font-size:.85em}html.theme--documenter-dark .tag.is-medium:not(body),html.theme--documenter-dark .content kbd.is-medium:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-medium:not(body){font-size:15px}html.theme--documenter-dark .tag.is-large:not(body),html.theme--documenter-dark .content kbd.is-large:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-large:not(body){font-size:1.25rem}html.theme--documenter-dark .tag:not(body) .icon:first-child:not(:last-child),html.theme--documenter-dark .content kbd:not(body) .icon:first-child:not(:last-child),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:not(:last-child){margin-left:-0.375em;margin-right:0.1875em}html.theme--documenter-dark .tag:not(body) .icon:last-child:not(:first-child),html.theme--documenter-dark .content kbd:not(body) .icon:last-child:not(:first-child),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .icon:last-child:not(:first-child){margin-left:0.1875em;margin-right:-0.375em}html.theme--documenter-dark .tag:not(body) .icon:first-child:last-child,html.theme--documenter-dark .content kbd:not(body) .icon:first-child:last-child,html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:last-child{margin-left:-0.375em;margin-right:-0.375em}html.theme--documenter-dark .tag.is-delete:not(body),html.theme--documenter-dark .content kbd.is-delete:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body){margin-left:1px;padding:0;position:relative;width:2em}html.theme--documenter-dark .tag.is-delete:not(body)::before,html.theme--documenter-dark .content kbd.is-delete:not(body)::before,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::before,html.theme--documenter-dark .tag.is-delete:not(body)::after,html.theme--documenter-dark .content kbd.is-delete:not(body)::after,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{background-color:currentColor;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--documenter-dark .tag.is-delete:not(body)::before,html.theme--documenter-dark .content kbd.is-delete:not(body)::before,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::before{height:1px;width:50%}html.theme--documenter-dark .tag.is-delete:not(body)::after,html.theme--documenter-dark .content kbd.is-delete:not(body)::after,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{height:50%;width:1px}html.theme--documenter-dark .tag.is-delete:not(body):hover,html.theme--documenter-dark .content kbd.is-delete:not(body):hover,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body):hover,html.theme--documenter-dark .tag.is-delete:not(body):focus,html.theme--documenter-dark .content kbd.is-delete:not(body):focus,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body):focus{background-color:#1d2122}html.theme--documenter-dark .tag.is-delete:not(body):active,html.theme--documenter-dark .content kbd.is-delete:not(body):active,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body):active{background-color:#111414}html.theme--documenter-dark .tag.is-rounded:not(body),html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:not(body),html.theme--documenter-dark .content kbd.is-rounded:not(body),html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search>input:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-rounded:not(body){border-radius:290486px}html.theme--documenter-dark a.tag:hover,html.theme--documenter-dark .docstring>section>a.docs-sourcelink:hover{text-decoration:underline}html.theme--documenter-dark .title,html.theme--documenter-dark .subtitle{word-break:break-word}html.theme--documenter-dark .title em,html.theme--documenter-dark .title span,html.theme--documenter-dark .subtitle em,html.theme--documenter-dark .subtitle span{font-weight:inherit}html.theme--documenter-dark .title sub,html.theme--documenter-dark .subtitle sub{font-size:.75em}html.theme--documenter-dark .title sup,html.theme--documenter-dark .subtitle sup{font-size:.75em}html.theme--documenter-dark .title .tag,html.theme--documenter-dark .title .content kbd,html.theme--documenter-dark .content .title kbd,html.theme--documenter-dark .title .docstring>section>a.docs-sourcelink,html.theme--documenter-dark .subtitle .tag,html.theme--documenter-dark .subtitle .content kbd,html.theme--documenter-dark .content .subtitle kbd,html.theme--documenter-dark .subtitle .docstring>section>a.docs-sourcelink{vertical-align:middle}html.theme--documenter-dark .title{color:#fff;font-size:2rem;font-weight:500;line-height:1.125}html.theme--documenter-dark .title strong{color:inherit;font-weight:inherit}html.theme--documenter-dark .title+.highlight{margin-top:-0.75rem}html.theme--documenter-dark .title:not(.is-spaced)+.subtitle{margin-top:-1.25rem}html.theme--documenter-dark .title.is-1{font-size:3rem}html.theme--documenter-dark .title.is-2{font-size:2.5rem}html.theme--documenter-dark .title.is-3{font-size:2rem}html.theme--documenter-dark .title.is-4{font-size:1.5rem}html.theme--documenter-dark .title.is-5{font-size:1.25rem}html.theme--documenter-dark .title.is-6{font-size:15px}html.theme--documenter-dark .title.is-7{font-size:.85em}html.theme--documenter-dark .subtitle{color:#8c9b9d;font-size:1.25rem;font-weight:400;line-height:1.25}html.theme--documenter-dark .subtitle strong{color:#8c9b9d;font-weight:600}html.theme--documenter-dark .subtitle:not(.is-spaced)+.title{margin-top:-1.25rem}html.theme--documenter-dark .subtitle.is-1{font-size:3rem}html.theme--documenter-dark .subtitle.is-2{font-size:2.5rem}html.theme--documenter-dark .subtitle.is-3{font-size:2rem}html.theme--documenter-dark .subtitle.is-4{font-size:1.5rem}html.theme--documenter-dark .subtitle.is-5{font-size:1.25rem}html.theme--documenter-dark .subtitle.is-6{font-size:15px}html.theme--documenter-dark .subtitle.is-7{font-size:.85em}html.theme--documenter-dark .heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}html.theme--documenter-dark .highlight{font-weight:400;max-width:100%;overflow:hidden;padding:0}html.theme--documenter-dark .highlight pre{overflow:auto;max-width:100%}html.theme--documenter-dark .number{align-items:center;background-color:#282f2f;border-radius:290486px;display:inline-flex;font-size:1.25rem;height:2em;justify-content:center;margin-right:1.5rem;min-width:2.5em;padding:0.25rem 0.5rem;text-align:center;vertical-align:top}html.theme--documenter-dark .select select,html.theme--documenter-dark .textarea,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{background-color:#1f2424;border-color:#5e6d6f;border-radius:.4em;color:#dbdee0}html.theme--documenter-dark .select select::-moz-placeholder,html.theme--documenter-dark .textarea::-moz-placeholder,html.theme--documenter-dark .input::-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:rgba(219,222,224,0.3)}html.theme--documenter-dark .select select::-webkit-input-placeholder,html.theme--documenter-dark .textarea::-webkit-input-placeholder,html.theme--documenter-dark .input::-webkit-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:rgba(219,222,224,0.3)}html.theme--documenter-dark .select select:-moz-placeholder,html.theme--documenter-dark .textarea:-moz-placeholder,html.theme--documenter-dark .input:-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:rgba(219,222,224,0.3)}html.theme--documenter-dark .select select:-ms-input-placeholder,html.theme--documenter-dark .textarea:-ms-input-placeholder,html.theme--documenter-dark .input:-ms-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:rgba(219,222,224,0.3)}html.theme--documenter-dark .select select:hover,html.theme--documenter-dark .textarea:hover,html.theme--documenter-dark .input:hover,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:hover,html.theme--documenter-dark .select select.is-hovered,html.theme--documenter-dark .is-hovered.textarea,html.theme--documenter-dark .is-hovered.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-hovered{border-color:#8c9b9d}html.theme--documenter-dark .select select:focus,html.theme--documenter-dark .textarea:focus,html.theme--documenter-dark .input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:focus,html.theme--documenter-dark .select select.is-focused,html.theme--documenter-dark .is-focused.textarea,html.theme--documenter-dark .is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .select select:active,html.theme--documenter-dark .textarea:active,html.theme--documenter-dark .input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:active,html.theme--documenter-dark .select select.is-active,html.theme--documenter-dark .is-active.textarea,html.theme--documenter-dark .is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{border-color:#1abc9c;box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .select select[disabled],html.theme--documenter-dark .textarea[disabled],html.theme--documenter-dark .input[disabled],html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled],fieldset[disabled] html.theme--documenter-dark .select select,fieldset[disabled] html.theme--documenter-dark .textarea,fieldset[disabled] html.theme--documenter-dark .input,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{background-color:#8c9b9d;border-color:#282f2f;box-shadow:none;color:#fff}html.theme--documenter-dark .select select[disabled]::-moz-placeholder,html.theme--documenter-dark .textarea[disabled]::-moz-placeholder,html.theme--documenter-dark .input[disabled]::-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .select select::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .input::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .select select[disabled]::-webkit-input-placeholder,html.theme--documenter-dark .textarea[disabled]::-webkit-input-placeholder,html.theme--documenter-dark .input[disabled]::-webkit-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark .select select::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark .input::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .select select[disabled]:-moz-placeholder,html.theme--documenter-dark .textarea[disabled]:-moz-placeholder,html.theme--documenter-dark .input[disabled]:-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .select select:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .input:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .select select[disabled]:-ms-input-placeholder,html.theme--documenter-dark .textarea[disabled]:-ms-input-placeholder,html.theme--documenter-dark .input[disabled]:-ms-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark .select select:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark .input:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .textarea,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{box-shadow:inset 0 1px 2px rgba(10,10,10,0.1);max-width:100%;width:100%}html.theme--documenter-dark .textarea[readonly],html.theme--documenter-dark .input[readonly],html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[readonly]{box-shadow:none}html.theme--documenter-dark .is-white.textarea,html.theme--documenter-dark .is-white.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-white{border-color:#fff}html.theme--documenter-dark .is-white.textarea:focus,html.theme--documenter-dark .is-white.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-white:focus,html.theme--documenter-dark .is-white.is-focused.textarea,html.theme--documenter-dark .is-white.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-white.textarea:active,html.theme--documenter-dark .is-white.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-white:active,html.theme--documenter-dark .is-white.is-active.textarea,html.theme--documenter-dark .is-white.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--documenter-dark .is-black.textarea,html.theme--documenter-dark .is-black.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-black{border-color:#0a0a0a}html.theme--documenter-dark .is-black.textarea:focus,html.theme--documenter-dark .is-black.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-black:focus,html.theme--documenter-dark .is-black.is-focused.textarea,html.theme--documenter-dark .is-black.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-black.textarea:active,html.theme--documenter-dark .is-black.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-black:active,html.theme--documenter-dark .is-black.is-active.textarea,html.theme--documenter-dark .is-black.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--documenter-dark .is-light.textarea,html.theme--documenter-dark .is-light.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-light{border-color:#ecf0f1}html.theme--documenter-dark .is-light.textarea:focus,html.theme--documenter-dark .is-light.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-light:focus,html.theme--documenter-dark .is-light.is-focused.textarea,html.theme--documenter-dark .is-light.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-light.textarea:active,html.theme--documenter-dark .is-light.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-light:active,html.theme--documenter-dark .is-light.is-active.textarea,html.theme--documenter-dark .is-light.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(236,240,241,0.25)}html.theme--documenter-dark .is-dark.textarea,html.theme--documenter-dark .content kbd.textarea,html.theme--documenter-dark .is-dark.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-dark,html.theme--documenter-dark .content kbd.input{border-color:#282f2f}html.theme--documenter-dark .is-dark.textarea:focus,html.theme--documenter-dark .content kbd.textarea:focus,html.theme--documenter-dark .is-dark.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-dark:focus,html.theme--documenter-dark .content kbd.input:focus,html.theme--documenter-dark .is-dark.is-focused.textarea,html.theme--documenter-dark .content kbd.is-focused.textarea,html.theme--documenter-dark .is-dark.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .content kbd.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search>input.is-focused,html.theme--documenter-dark .is-dark.textarea:active,html.theme--documenter-dark .content kbd.textarea:active,html.theme--documenter-dark .is-dark.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-dark:active,html.theme--documenter-dark .content kbd.input:active,html.theme--documenter-dark .is-dark.is-active.textarea,html.theme--documenter-dark .content kbd.is-active.textarea,html.theme--documenter-dark .is-dark.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--documenter-dark .content kbd.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(40,47,47,0.25)}html.theme--documenter-dark .is-primary.textarea,html.theme--documenter-dark .docstring>section>a.textarea.docs-sourcelink,html.theme--documenter-dark .is-primary.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-primary,html.theme--documenter-dark .docstring>section>a.input.docs-sourcelink{border-color:#375a7f}html.theme--documenter-dark .is-primary.textarea:focus,html.theme--documenter-dark .docstring>section>a.textarea.docs-sourcelink:focus,html.theme--documenter-dark .is-primary.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-primary:focus,html.theme--documenter-dark .docstring>section>a.input.docs-sourcelink:focus,html.theme--documenter-dark .is-primary.is-focused.textarea,html.theme--documenter-dark .docstring>section>a.is-focused.textarea.docs-sourcelink,html.theme--documenter-dark .is-primary.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .docstring>section>a.is-focused.input.docs-sourcelink,html.theme--documenter-dark .is-primary.textarea:active,html.theme--documenter-dark .docstring>section>a.textarea.docs-sourcelink:active,html.theme--documenter-dark .is-primary.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-primary:active,html.theme--documenter-dark .docstring>section>a.input.docs-sourcelink:active,html.theme--documenter-dark .is-primary.is-active.textarea,html.theme--documenter-dark .docstring>section>a.is-active.textarea.docs-sourcelink,html.theme--documenter-dark .is-primary.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--documenter-dark .docstring>section>a.is-active.input.docs-sourcelink{box-shadow:0 0 0 0.125em rgba(55,90,127,0.25)}html.theme--documenter-dark .is-link.textarea,html.theme--documenter-dark .is-link.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-link{border-color:#1abc9c}html.theme--documenter-dark .is-link.textarea:focus,html.theme--documenter-dark .is-link.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-link:focus,html.theme--documenter-dark .is-link.is-focused.textarea,html.theme--documenter-dark .is-link.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-link.textarea:active,html.theme--documenter-dark .is-link.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-link:active,html.theme--documenter-dark .is-link.is-active.textarea,html.theme--documenter-dark .is-link.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .is-info.textarea,html.theme--documenter-dark .is-info.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-info{border-color:#024c7d}html.theme--documenter-dark .is-info.textarea:focus,html.theme--documenter-dark .is-info.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-info:focus,html.theme--documenter-dark .is-info.is-focused.textarea,html.theme--documenter-dark .is-info.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-info.textarea:active,html.theme--documenter-dark .is-info.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-info:active,html.theme--documenter-dark .is-info.is-active.textarea,html.theme--documenter-dark .is-info.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(2,76,125,0.25)}html.theme--documenter-dark .is-success.textarea,html.theme--documenter-dark .is-success.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-success{border-color:#008438}html.theme--documenter-dark .is-success.textarea:focus,html.theme--documenter-dark .is-success.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-success:focus,html.theme--documenter-dark .is-success.is-focused.textarea,html.theme--documenter-dark .is-success.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-success.textarea:active,html.theme--documenter-dark .is-success.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-success:active,html.theme--documenter-dark .is-success.is-active.textarea,html.theme--documenter-dark .is-success.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(0,132,56,0.25)}html.theme--documenter-dark .is-warning.textarea,html.theme--documenter-dark .is-warning.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-warning{border-color:#ad8100}html.theme--documenter-dark .is-warning.textarea:focus,html.theme--documenter-dark .is-warning.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-warning:focus,html.theme--documenter-dark .is-warning.is-focused.textarea,html.theme--documenter-dark .is-warning.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-warning.textarea:active,html.theme--documenter-dark .is-warning.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-warning:active,html.theme--documenter-dark .is-warning.is-active.textarea,html.theme--documenter-dark .is-warning.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(173,129,0,0.25)}html.theme--documenter-dark .is-danger.textarea,html.theme--documenter-dark .is-danger.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-danger{border-color:#9e1b0d}html.theme--documenter-dark .is-danger.textarea:focus,html.theme--documenter-dark .is-danger.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-danger:focus,html.theme--documenter-dark .is-danger.is-focused.textarea,html.theme--documenter-dark .is-danger.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-danger.textarea:active,html.theme--documenter-dark .is-danger.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-danger:active,html.theme--documenter-dark .is-danger.is-active.textarea,html.theme--documenter-dark .is-danger.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(158,27,13,0.25)}html.theme--documenter-dark .is-small.textarea,html.theme--documenter-dark .is-small.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{border-radius:3px;font-size:.85em}html.theme--documenter-dark .is-medium.textarea,html.theme--documenter-dark .is-medium.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-medium{font-size:1.25rem}html.theme--documenter-dark .is-large.textarea,html.theme--documenter-dark .is-large.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-large{font-size:1.5rem}html.theme--documenter-dark .is-fullwidth.textarea,html.theme--documenter-dark .is-fullwidth.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-fullwidth{display:block;width:100%}html.theme--documenter-dark .is-inline.textarea,html.theme--documenter-dark .is-inline.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-inline{display:inline;width:auto}html.theme--documenter-dark .input.is-rounded,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{border-radius:290486px;padding-left:1em;padding-right:1em}html.theme--documenter-dark .input.is-static,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-static{background-color:transparent;border-color:transparent;box-shadow:none;padding-left:0;padding-right:0}html.theme--documenter-dark .textarea{display:block;max-width:100%;min-width:100%;padding:0.625em;resize:vertical}html.theme--documenter-dark .textarea:not([rows]){max-height:600px;min-height:120px}html.theme--documenter-dark .textarea[rows]{height:initial}html.theme--documenter-dark .textarea.has-fixed-size{resize:none}html.theme--documenter-dark .radio,html.theme--documenter-dark .checkbox{cursor:pointer;display:inline-block;line-height:1.25;position:relative}html.theme--documenter-dark .radio input,html.theme--documenter-dark .checkbox input{cursor:pointer}html.theme--documenter-dark .radio:hover,html.theme--documenter-dark .checkbox:hover{color:#8c9b9d}html.theme--documenter-dark .radio[disabled],html.theme--documenter-dark .checkbox[disabled],fieldset[disabled] html.theme--documenter-dark .radio,fieldset[disabled] html.theme--documenter-dark .checkbox{color:#fff;cursor:not-allowed}html.theme--documenter-dark .radio+.radio{margin-left:0.5em}html.theme--documenter-dark .select{display:inline-block;max-width:100%;position:relative;vertical-align:top}html.theme--documenter-dark .select:not(.is-multiple){height:2.25em}html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading)::after{border-color:#1abc9c;right:1.125em;z-index:4}html.theme--documenter-dark .select.is-rounded select,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.select select{border-radius:290486px;padding-left:1em}html.theme--documenter-dark .select select{cursor:pointer;display:block;font-size:1em;max-width:100%;outline:none}html.theme--documenter-dark .select select::-ms-expand{display:none}html.theme--documenter-dark .select select[disabled]:hover,fieldset[disabled] html.theme--documenter-dark .select select:hover{border-color:#282f2f}html.theme--documenter-dark .select select:not([multiple]){padding-right:2.5em}html.theme--documenter-dark .select select[multiple]{height:auto;padding:0}html.theme--documenter-dark .select select[multiple] option{padding:0.5em 1em}html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading):hover::after{border-color:#8c9b9d}html.theme--documenter-dark .select.is-white:not(:hover)::after{border-color:#fff}html.theme--documenter-dark .select.is-white select{border-color:#fff}html.theme--documenter-dark .select.is-white select:hover,html.theme--documenter-dark .select.is-white select.is-hovered{border-color:#f2f2f2}html.theme--documenter-dark .select.is-white select:focus,html.theme--documenter-dark .select.is-white select.is-focused,html.theme--documenter-dark .select.is-white select:active,html.theme--documenter-dark .select.is-white select.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--documenter-dark .select.is-black:not(:hover)::after{border-color:#0a0a0a}html.theme--documenter-dark .select.is-black select{border-color:#0a0a0a}html.theme--documenter-dark .select.is-black select:hover,html.theme--documenter-dark .select.is-black select.is-hovered{border-color:#000}html.theme--documenter-dark .select.is-black select:focus,html.theme--documenter-dark .select.is-black select.is-focused,html.theme--documenter-dark .select.is-black select:active,html.theme--documenter-dark .select.is-black select.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--documenter-dark .select.is-light:not(:hover)::after{border-color:#ecf0f1}html.theme--documenter-dark .select.is-light select{border-color:#ecf0f1}html.theme--documenter-dark .select.is-light select:hover,html.theme--documenter-dark .select.is-light select.is-hovered{border-color:#dde4e6}html.theme--documenter-dark .select.is-light select:focus,html.theme--documenter-dark .select.is-light select.is-focused,html.theme--documenter-dark .select.is-light select:active,html.theme--documenter-dark .select.is-light select.is-active{box-shadow:0 0 0 0.125em rgba(236,240,241,0.25)}html.theme--documenter-dark .select.is-dark:not(:hover)::after,html.theme--documenter-dark .content kbd.select:not(:hover)::after{border-color:#282f2f}html.theme--documenter-dark .select.is-dark select,html.theme--documenter-dark .content kbd.select select{border-color:#282f2f}html.theme--documenter-dark .select.is-dark select:hover,html.theme--documenter-dark .content kbd.select select:hover,html.theme--documenter-dark .select.is-dark select.is-hovered,html.theme--documenter-dark .content kbd.select select.is-hovered{border-color:#1d2122}html.theme--documenter-dark .select.is-dark select:focus,html.theme--documenter-dark .content kbd.select select:focus,html.theme--documenter-dark .select.is-dark select.is-focused,html.theme--documenter-dark .content kbd.select select.is-focused,html.theme--documenter-dark .select.is-dark select:active,html.theme--documenter-dark .content kbd.select select:active,html.theme--documenter-dark .select.is-dark select.is-active,html.theme--documenter-dark .content kbd.select select.is-active{box-shadow:0 0 0 0.125em rgba(40,47,47,0.25)}html.theme--documenter-dark .select.is-primary:not(:hover)::after,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink:not(:hover)::after{border-color:#375a7f}html.theme--documenter-dark .select.is-primary select,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select{border-color:#375a7f}html.theme--documenter-dark .select.is-primary select:hover,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select:hover,html.theme--documenter-dark .select.is-primary select.is-hovered,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select.is-hovered{border-color:#2f4d6d}html.theme--documenter-dark .select.is-primary select:focus,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select:focus,html.theme--documenter-dark .select.is-primary select.is-focused,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select.is-focused,html.theme--documenter-dark .select.is-primary select:active,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select:active,html.theme--documenter-dark .select.is-primary select.is-active,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select.is-active{box-shadow:0 0 0 0.125em rgba(55,90,127,0.25)}html.theme--documenter-dark .select.is-link:not(:hover)::after{border-color:#1abc9c}html.theme--documenter-dark .select.is-link select{border-color:#1abc9c}html.theme--documenter-dark .select.is-link select:hover,html.theme--documenter-dark .select.is-link select.is-hovered{border-color:#17a689}html.theme--documenter-dark .select.is-link select:focus,html.theme--documenter-dark .select.is-link select.is-focused,html.theme--documenter-dark .select.is-link select:active,html.theme--documenter-dark .select.is-link select.is-active{box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .select.is-info:not(:hover)::after{border-color:#024c7d}html.theme--documenter-dark .select.is-info select{border-color:#024c7d}html.theme--documenter-dark .select.is-info select:hover,html.theme--documenter-dark .select.is-info select.is-hovered{border-color:#023d64}html.theme--documenter-dark .select.is-info select:focus,html.theme--documenter-dark .select.is-info select.is-focused,html.theme--documenter-dark .select.is-info select:active,html.theme--documenter-dark .select.is-info select.is-active{box-shadow:0 0 0 0.125em rgba(2,76,125,0.25)}html.theme--documenter-dark .select.is-success:not(:hover)::after{border-color:#008438}html.theme--documenter-dark .select.is-success select{border-color:#008438}html.theme--documenter-dark .select.is-success select:hover,html.theme--documenter-dark .select.is-success select.is-hovered{border-color:#006b2d}html.theme--documenter-dark .select.is-success select:focus,html.theme--documenter-dark .select.is-success select.is-focused,html.theme--documenter-dark .select.is-success select:active,html.theme--documenter-dark .select.is-success select.is-active{box-shadow:0 0 0 0.125em rgba(0,132,56,0.25)}html.theme--documenter-dark .select.is-warning:not(:hover)::after{border-color:#ad8100}html.theme--documenter-dark .select.is-warning select{border-color:#ad8100}html.theme--documenter-dark .select.is-warning select:hover,html.theme--documenter-dark .select.is-warning select.is-hovered{border-color:#946e00}html.theme--documenter-dark .select.is-warning select:focus,html.theme--documenter-dark .select.is-warning select.is-focused,html.theme--documenter-dark .select.is-warning select:active,html.theme--documenter-dark .select.is-warning select.is-active{box-shadow:0 0 0 0.125em rgba(173,129,0,0.25)}html.theme--documenter-dark .select.is-danger:not(:hover)::after{border-color:#9e1b0d}html.theme--documenter-dark .select.is-danger select{border-color:#9e1b0d}html.theme--documenter-dark .select.is-danger select:hover,html.theme--documenter-dark .select.is-danger select.is-hovered{border-color:#86170b}html.theme--documenter-dark .select.is-danger select:focus,html.theme--documenter-dark .select.is-danger select.is-focused,html.theme--documenter-dark .select.is-danger select:active,html.theme--documenter-dark .select.is-danger select.is-active{box-shadow:0 0 0 0.125em rgba(158,27,13,0.25)}html.theme--documenter-dark .select.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.select{border-radius:3px;font-size:.85em}html.theme--documenter-dark .select.is-medium{font-size:1.25rem}html.theme--documenter-dark .select.is-large{font-size:1.5rem}html.theme--documenter-dark .select.is-disabled::after{border-color:#fff}html.theme--documenter-dark .select.is-fullwidth{width:100%}html.theme--documenter-dark .select.is-fullwidth select{width:100%}html.theme--documenter-dark .select.is-loading::after{margin-top:0;position:absolute;right:0.625em;top:0.625em;transform:none}html.theme--documenter-dark .select.is-loading.is-small:after,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.85em}html.theme--documenter-dark .select.is-loading.is-medium:after{font-size:1.25rem}html.theme--documenter-dark .select.is-loading.is-large:after{font-size:1.5rem}html.theme--documenter-dark .file{align-items:stretch;display:flex;justify-content:flex-start;position:relative}html.theme--documenter-dark .file.is-white .file-cta{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .file.is-white:hover .file-cta,html.theme--documenter-dark .file.is-white.is-hovered .file-cta{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .file.is-white:focus .file-cta,html.theme--documenter-dark .file.is-white.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,255,255,0.25);color:#0a0a0a}html.theme--documenter-dark .file.is-white:active .file-cta,html.theme--documenter-dark .file.is-white.is-active .file-cta{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .file.is-black .file-cta{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-black:hover .file-cta,html.theme--documenter-dark .file.is-black.is-hovered .file-cta{background-color:#040404;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-black:focus .file-cta,html.theme--documenter-dark .file.is-black.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(10,10,10,0.25);color:#fff}html.theme--documenter-dark .file.is-black:active .file-cta,html.theme--documenter-dark .file.is-black.is-active .file-cta{background-color:#000;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-light .file-cta{background-color:#ecf0f1;border-color:transparent;color:#282f2f}html.theme--documenter-dark .file.is-light:hover .file-cta,html.theme--documenter-dark .file.is-light.is-hovered .file-cta{background-color:#e5eaec;border-color:transparent;color:#282f2f}html.theme--documenter-dark .file.is-light:focus .file-cta,html.theme--documenter-dark .file.is-light.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(236,240,241,0.25);color:#282f2f}html.theme--documenter-dark .file.is-light:active .file-cta,html.theme--documenter-dark .file.is-light.is-active .file-cta{background-color:#dde4e6;border-color:transparent;color:#282f2f}html.theme--documenter-dark .file.is-dark .file-cta,html.theme--documenter-dark .content kbd.file .file-cta{background-color:#282f2f;border-color:transparent;color:#ecf0f1}html.theme--documenter-dark .file.is-dark:hover .file-cta,html.theme--documenter-dark .content kbd.file:hover .file-cta,html.theme--documenter-dark .file.is-dark.is-hovered .file-cta,html.theme--documenter-dark .content kbd.file.is-hovered .file-cta{background-color:#232829;border-color:transparent;color:#ecf0f1}html.theme--documenter-dark .file.is-dark:focus .file-cta,html.theme--documenter-dark .content kbd.file:focus .file-cta,html.theme--documenter-dark .file.is-dark.is-focused .file-cta,html.theme--documenter-dark .content kbd.file.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(40,47,47,0.25);color:#ecf0f1}html.theme--documenter-dark .file.is-dark:active .file-cta,html.theme--documenter-dark .content kbd.file:active .file-cta,html.theme--documenter-dark .file.is-dark.is-active .file-cta,html.theme--documenter-dark .content kbd.file.is-active .file-cta{background-color:#1d2122;border-color:transparent;color:#ecf0f1}html.theme--documenter-dark .file.is-primary .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink .file-cta{background-color:#375a7f;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-primary:hover .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink:hover .file-cta,html.theme--documenter-dark .file.is-primary.is-hovered .file-cta,html.theme--documenter-dark .docstring>section>a.file.is-hovered.docs-sourcelink .file-cta{background-color:#335476;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-primary:focus .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink:focus .file-cta,html.theme--documenter-dark .file.is-primary.is-focused .file-cta,html.theme--documenter-dark .docstring>section>a.file.is-focused.docs-sourcelink .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(55,90,127,0.25);color:#fff}html.theme--documenter-dark .file.is-primary:active .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink:active .file-cta,html.theme--documenter-dark .file.is-primary.is-active .file-cta,html.theme--documenter-dark .docstring>section>a.file.is-active.docs-sourcelink .file-cta{background-color:#2f4d6d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-link .file-cta{background-color:#1abc9c;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-link:hover .file-cta,html.theme--documenter-dark .file.is-link.is-hovered .file-cta{background-color:#18b193;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-link:focus .file-cta,html.theme--documenter-dark .file.is-link.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(26,188,156,0.25);color:#fff}html.theme--documenter-dark .file.is-link:active .file-cta,html.theme--documenter-dark .file.is-link.is-active .file-cta{background-color:#17a689;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-info .file-cta{background-color:#024c7d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-info:hover .file-cta,html.theme--documenter-dark .file.is-info.is-hovered .file-cta{background-color:#024470;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-info:focus .file-cta,html.theme--documenter-dark .file.is-info.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(2,76,125,0.25);color:#fff}html.theme--documenter-dark .file.is-info:active .file-cta,html.theme--documenter-dark .file.is-info.is-active .file-cta{background-color:#023d64;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-success .file-cta{background-color:#008438;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-success:hover .file-cta,html.theme--documenter-dark .file.is-success.is-hovered .file-cta{background-color:#073;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-success:focus .file-cta,html.theme--documenter-dark .file.is-success.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(0,132,56,0.25);color:#fff}html.theme--documenter-dark .file.is-success:active .file-cta,html.theme--documenter-dark .file.is-success.is-active .file-cta{background-color:#006b2d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-warning .file-cta{background-color:#ad8100;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-warning:hover .file-cta,html.theme--documenter-dark .file.is-warning.is-hovered .file-cta{background-color:#a07700;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-warning:focus .file-cta,html.theme--documenter-dark .file.is-warning.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(173,129,0,0.25);color:#fff}html.theme--documenter-dark .file.is-warning:active .file-cta,html.theme--documenter-dark .file.is-warning.is-active .file-cta{background-color:#946e00;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-danger .file-cta{background-color:#9e1b0d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-danger:hover .file-cta,html.theme--documenter-dark .file.is-danger.is-hovered .file-cta{background-color:#92190c;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-danger:focus .file-cta,html.theme--documenter-dark .file.is-danger.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(158,27,13,0.25);color:#fff}html.theme--documenter-dark .file.is-danger:active .file-cta,html.theme--documenter-dark .file.is-danger.is-active .file-cta{background-color:#86170b;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.file{font-size:.85em}html.theme--documenter-dark .file.is-medium{font-size:1.25rem}html.theme--documenter-dark .file.is-medium .file-icon .fa{font-size:21px}html.theme--documenter-dark .file.is-large{font-size:1.5rem}html.theme--documenter-dark .file.is-large .file-icon .fa{font-size:28px}html.theme--documenter-dark .file.has-name .file-cta{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--documenter-dark .file.has-name .file-name{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--documenter-dark .file.has-name.is-empty .file-cta{border-radius:.4em}html.theme--documenter-dark .file.has-name.is-empty .file-name{display:none}html.theme--documenter-dark .file.is-boxed .file-label{flex-direction:column}html.theme--documenter-dark .file.is-boxed .file-cta{flex-direction:column;height:auto;padding:1em 3em}html.theme--documenter-dark .file.is-boxed .file-name{border-width:0 1px 1px}html.theme--documenter-dark .file.is-boxed .file-icon{height:1.5em;width:1.5em}html.theme--documenter-dark .file.is-boxed .file-icon .fa{font-size:21px}html.theme--documenter-dark .file.is-boxed.is-small .file-icon .fa,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-boxed .file-icon .fa{font-size:14px}html.theme--documenter-dark .file.is-boxed.is-medium .file-icon .fa{font-size:28px}html.theme--documenter-dark .file.is-boxed.is-large .file-icon .fa{font-size:35px}html.theme--documenter-dark .file.is-boxed.has-name .file-cta{border-radius:.4em .4em 0 0}html.theme--documenter-dark .file.is-boxed.has-name .file-name{border-radius:0 0 .4em .4em;border-width:0 1px 1px}html.theme--documenter-dark .file.is-centered{justify-content:center}html.theme--documenter-dark .file.is-fullwidth .file-label{width:100%}html.theme--documenter-dark .file.is-fullwidth .file-name{flex-grow:1;max-width:none}html.theme--documenter-dark .file.is-right{justify-content:flex-end}html.theme--documenter-dark .file.is-right .file-cta{border-radius:0 .4em .4em 0}html.theme--documenter-dark .file.is-right .file-name{border-radius:.4em 0 0 .4em;border-width:1px 0 1px 1px;order:-1}html.theme--documenter-dark .file-label{align-items:stretch;display:flex;cursor:pointer;justify-content:flex-start;overflow:hidden;position:relative}html.theme--documenter-dark .file-label:hover .file-cta{background-color:#e5eaec;color:#282f2f}html.theme--documenter-dark .file-label:hover .file-name{border-color:#596668}html.theme--documenter-dark .file-label:active .file-cta{background-color:#dde4e6;color:#282f2f}html.theme--documenter-dark .file-label:active .file-name{border-color:#535f61}html.theme--documenter-dark .file-input{height:100%;left:0;opacity:0;outline:none;position:absolute;top:0;width:100%}html.theme--documenter-dark .file-cta,html.theme--documenter-dark .file-name{border-color:#5e6d6f;border-radius:.4em;font-size:1em;padding-left:1em;padding-right:1em;white-space:nowrap}html.theme--documenter-dark .file-cta{background-color:#ecf0f1;color:#343c3d}html.theme--documenter-dark .file-name{border-color:#5e6d6f;border-style:solid;border-width:1px 1px 1px 0;display:block;max-width:16em;overflow:hidden;text-align:left;text-overflow:ellipsis}html.theme--documenter-dark .file-icon{align-items:center;display:flex;height:1em;justify-content:center;margin-right:0.5em;width:1em}html.theme--documenter-dark .file-icon .fa{font-size:14px}html.theme--documenter-dark .label{color:#282f2f;display:block;font-size:15px;font-weight:700}html.theme--documenter-dark .label:not(:last-child){margin-bottom:0.5em}html.theme--documenter-dark .label.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.label{font-size:.85em}html.theme--documenter-dark .label.is-medium{font-size:1.25rem}html.theme--documenter-dark .label.is-large{font-size:1.5rem}html.theme--documenter-dark .help{display:block;font-size:.85em;margin-top:0.25rem}html.theme--documenter-dark .help.is-white{color:#fff}html.theme--documenter-dark .help.is-black{color:#0a0a0a}html.theme--documenter-dark .help.is-light{color:#ecf0f1}html.theme--documenter-dark .help.is-dark,html.theme--documenter-dark .content kbd.help{color:#282f2f}html.theme--documenter-dark .help.is-primary,html.theme--documenter-dark .docstring>section>a.help.docs-sourcelink{color:#375a7f}html.theme--documenter-dark .help.is-link{color:#1abc9c}html.theme--documenter-dark .help.is-info{color:#024c7d}html.theme--documenter-dark .help.is-success{color:#008438}html.theme--documenter-dark .help.is-warning{color:#ad8100}html.theme--documenter-dark .help.is-danger{color:#9e1b0d}html.theme--documenter-dark .field:not(:last-child){margin-bottom:0.75rem}html.theme--documenter-dark .field.has-addons{display:flex;justify-content:flex-start}html.theme--documenter-dark .field.has-addons .control:not(:last-child){margin-right:-1px}html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .button,html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .input,html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:not(:first-child):not(:last-child) form.docs-search>input,html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .select select{border-radius:0}html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .button,html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .input,html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:first-child:not(:only-child) form.docs-search>input,html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .select select{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .button,html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .input,html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:last-child:not(:only-child) form.docs-search>input,html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .select select{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .button.is-hovered:not([disabled]),html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .input.is-hovered:not([disabled]),html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-hovered:not([disabled]),html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-hovered:not([disabled]),html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .select select.is-hovered:not([disabled]){z-index:2}html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control .button.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control .button.is-active:not([disabled]),html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control .input.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]),html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control .input.is-active:not([disabled]),html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]),html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]),html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control .select select.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control .select select.is-active:not([disabled]){z-index:3}html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control .button.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control .button.is-active:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus:hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control .input.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]):hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active:hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control .input.is-active:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]):hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control .select select.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control .select select.is-active:not([disabled]):hover{z-index:4}html.theme--documenter-dark .field.has-addons .control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .field.has-addons.has-addons-centered{justify-content:center}html.theme--documenter-dark .field.has-addons.has-addons-right{justify-content:flex-end}html.theme--documenter-dark .field.has-addons.has-addons-fullwidth .control{flex-grow:1;flex-shrink:0}html.theme--documenter-dark .field.is-grouped{display:flex;justify-content:flex-start}html.theme--documenter-dark .field.is-grouped>.control{flex-shrink:0}html.theme--documenter-dark .field.is-grouped>.control:not(:last-child){margin-bottom:0;margin-right:0.75rem}html.theme--documenter-dark .field.is-grouped>.control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .field.is-grouped.is-grouped-centered{justify-content:center}html.theme--documenter-dark .field.is-grouped.is-grouped-right{justify-content:flex-end}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline{flex-wrap:wrap}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline>.control:last-child,html.theme--documenter-dark .field.is-grouped.is-grouped-multiline>.control:not(:last-child){margin-bottom:0.75rem}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline:last-child{margin-bottom:-0.75rem}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline:not(:last-child){margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--documenter-dark .field.is-horizontal{display:flex}}html.theme--documenter-dark .field-label .label{font-size:inherit}@media screen and (max-width: 768px){html.theme--documenter-dark .field-label{margin-bottom:0.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .field-label{flex-basis:0;flex-grow:1;flex-shrink:0;margin-right:1.5rem;text-align:right}html.theme--documenter-dark .field-label.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.field-label{font-size:.85em;padding-top:0.375em}html.theme--documenter-dark .field-label.is-normal{padding-top:0.375em}html.theme--documenter-dark .field-label.is-medium{font-size:1.25rem;padding-top:0.375em}html.theme--documenter-dark .field-label.is-large{font-size:1.5rem;padding-top:0.375em}}html.theme--documenter-dark .field-body .field .field{margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--documenter-dark .field-body{display:flex;flex-basis:0;flex-grow:5;flex-shrink:1}html.theme--documenter-dark .field-body .field{margin-bottom:0}html.theme--documenter-dark .field-body>.field{flex-shrink:1}html.theme--documenter-dark .field-body>.field:not(.is-narrow){flex-grow:1}html.theme--documenter-dark .field-body>.field:not(:last-child){margin-right:0.75rem}}html.theme--documenter-dark .control{box-sizing:border-box;clear:both;font-size:15px;position:relative;text-align:left}html.theme--documenter-dark .control.has-icons-left .input:focus~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input:focus~.icon,html.theme--documenter-dark .control.has-icons-left .select:focus~.icon,html.theme--documenter-dark .control.has-icons-right .input:focus~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input:focus~.icon,html.theme--documenter-dark .control.has-icons-right .select:focus~.icon{color:#5e6d6f}html.theme--documenter-dark .control.has-icons-left .input.is-small~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input~.icon,html.theme--documenter-dark .control.has-icons-left .select.is-small~.icon,html.theme--documenter-dark .control.has-icons-right .input.is-small~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input~.icon,html.theme--documenter-dark .control.has-icons-right .select.is-small~.icon{font-size:.85em}html.theme--documenter-dark .control.has-icons-left .input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-left .select.is-medium~.icon,html.theme--documenter-dark .control.has-icons-right .input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-right .select.is-medium~.icon{font-size:1.25rem}html.theme--documenter-dark .control.has-icons-left .input.is-large~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-large~.icon,html.theme--documenter-dark .control.has-icons-left .select.is-large~.icon,html.theme--documenter-dark .control.has-icons-right .input.is-large~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-large~.icon,html.theme--documenter-dark .control.has-icons-right .select.is-large~.icon{font-size:1.5rem}html.theme--documenter-dark .control.has-icons-left .icon,html.theme--documenter-dark .control.has-icons-right .icon{color:#dbdee0;height:2.25em;pointer-events:none;position:absolute;top:0;width:2.25em;z-index:4}html.theme--documenter-dark .control.has-icons-left .input,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input,html.theme--documenter-dark .control.has-icons-left .select select{padding-left:2.25em}html.theme--documenter-dark .control.has-icons-left .icon.is-left{left:0}html.theme--documenter-dark .control.has-icons-right .input,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input,html.theme--documenter-dark .control.has-icons-right .select select{padding-right:2.25em}html.theme--documenter-dark .control.has-icons-right .icon.is-right{right:0}html.theme--documenter-dark .control.is-loading::after{position:absolute !important;right:0.625em;top:0.625em;z-index:4}html.theme--documenter-dark .control.is-loading.is-small:after,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.85em}html.theme--documenter-dark .control.is-loading.is-medium:after{font-size:1.25rem}html.theme--documenter-dark .control.is-loading.is-large:after{font-size:1.5rem}html.theme--documenter-dark .breadcrumb{font-size:15px;white-space:nowrap}html.theme--documenter-dark .breadcrumb a{align-items:center;color:#1abc9c;display:flex;justify-content:center;padding:0 .75em}html.theme--documenter-dark .breadcrumb a:hover{color:#1dd2af}html.theme--documenter-dark .breadcrumb li{align-items:center;display:flex}html.theme--documenter-dark .breadcrumb li:first-child a{padding-left:0}html.theme--documenter-dark .breadcrumb li.is-active a{color:#f2f2f2;cursor:default;pointer-events:none}html.theme--documenter-dark .breadcrumb li+li::before{color:#8c9b9d;content:"\0002f"}html.theme--documenter-dark .breadcrumb ul,html.theme--documenter-dark .breadcrumb ol{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--documenter-dark .breadcrumb .icon:first-child{margin-right:0.5em}html.theme--documenter-dark .breadcrumb .icon:last-child{margin-left:0.5em}html.theme--documenter-dark .breadcrumb.is-centered ol,html.theme--documenter-dark .breadcrumb.is-centered ul{justify-content:center}html.theme--documenter-dark .breadcrumb.is-right ol,html.theme--documenter-dark .breadcrumb.is-right ul{justify-content:flex-end}html.theme--documenter-dark .breadcrumb.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.breadcrumb{font-size:.85em}html.theme--documenter-dark .breadcrumb.is-medium{font-size:1.25rem}html.theme--documenter-dark .breadcrumb.is-large{font-size:1.5rem}html.theme--documenter-dark .breadcrumb.has-arrow-separator li+li::before{content:"\02192"}html.theme--documenter-dark .breadcrumb.has-bullet-separator li+li::before{content:"\02022"}html.theme--documenter-dark .breadcrumb.has-dot-separator li+li::before{content:"\000b7"}html.theme--documenter-dark .breadcrumb.has-succeeds-separator li+li::before{content:"\0227B"}html.theme--documenter-dark .card{background-color:#fff;box-shadow:0 2px 3px rgba(10,10,10,0.1),0 0 0 1px rgba(10,10,10,0.1);color:#fff;max-width:100%;position:relative}html.theme--documenter-dark .card-header{background-color:rgba(0,0,0,0);align-items:stretch;box-shadow:0 1px 2px rgba(10,10,10,0.1);display:flex}html.theme--documenter-dark .card-header-title{align-items:center;color:#f2f2f2;display:flex;flex-grow:1;font-weight:700;padding:.75rem}html.theme--documenter-dark .card-header-title.is-centered{justify-content:center}html.theme--documenter-dark .card-header-icon{align-items:center;cursor:pointer;display:flex;justify-content:center;padding:.75rem}html.theme--documenter-dark .card-image{display:block;position:relative}html.theme--documenter-dark .card-content{background-color:rgba(0,0,0,0);padding:1.5rem}html.theme--documenter-dark .card-footer{background-color:rgba(0,0,0,0);border-top:1px solid #5e6d6f;align-items:stretch;display:flex}html.theme--documenter-dark .card-footer-item{align-items:center;display:flex;flex-basis:0;flex-grow:1;flex-shrink:0;justify-content:center;padding:.75rem}html.theme--documenter-dark .card-footer-item:not(:last-child){border-right:1px solid #5e6d6f}html.theme--documenter-dark .card .media:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .dropdown{display:inline-flex;position:relative;vertical-align:top}html.theme--documenter-dark .dropdown.is-active .dropdown-menu,html.theme--documenter-dark .dropdown.is-hoverable:hover .dropdown-menu{display:block}html.theme--documenter-dark .dropdown.is-right .dropdown-menu{left:auto;right:0}html.theme--documenter-dark .dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:initial;top:auto}html.theme--documenter-dark .dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:20}html.theme--documenter-dark .dropdown-content{background-color:#282f2f;border-radius:.4em;box-shadow:0 2px 3px rgba(10,10,10,0.1),0 0 0 1px rgba(10,10,10,0.1);padding-bottom:.5rem;padding-top:.5rem}html.theme--documenter-dark .dropdown-item{color:#fff;display:block;font-size:0.875rem;line-height:1.5;padding:0.375rem 1rem;position:relative}html.theme--documenter-dark a.dropdown-item,html.theme--documenter-dark button.dropdown-item{padding-right:3rem;text-align:left;white-space:nowrap;width:100%}html.theme--documenter-dark a.dropdown-item:hover,html.theme--documenter-dark button.dropdown-item:hover{background-color:#282f2f;color:#0a0a0a}html.theme--documenter-dark a.dropdown-item.is-active,html.theme--documenter-dark button.dropdown-item.is-active{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .dropdown-divider{background-color:#5e6d6f;border:none;display:block;height:1px;margin:0.5rem 0}html.theme--documenter-dark .level{align-items:center;justify-content:space-between}html.theme--documenter-dark .level code{border-radius:.4em}html.theme--documenter-dark .level img{display:inline-block;vertical-align:top}html.theme--documenter-dark .level.is-mobile{display:flex}html.theme--documenter-dark .level.is-mobile .level-left,html.theme--documenter-dark .level.is-mobile .level-right{display:flex}html.theme--documenter-dark .level.is-mobile .level-left+.level-right{margin-top:0}html.theme--documenter-dark .level.is-mobile .level-item:not(:last-child){margin-bottom:0;margin-right:.75rem}html.theme--documenter-dark .level.is-mobile .level-item:not(.is-narrow){flex-grow:1}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level{display:flex}html.theme--documenter-dark .level>.level-item:not(.is-narrow){flex-grow:1}}html.theme--documenter-dark .level-item{align-items:center;display:flex;flex-basis:auto;flex-grow:0;flex-shrink:0;justify-content:center}html.theme--documenter-dark .level-item .title,html.theme--documenter-dark .level-item .subtitle{margin-bottom:0}@media screen and (max-width: 768px){html.theme--documenter-dark .level-item:not(:last-child){margin-bottom:.75rem}}html.theme--documenter-dark .level-left,html.theme--documenter-dark .level-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--documenter-dark .level-left .level-item.is-flexible,html.theme--documenter-dark .level-right .level-item.is-flexible{flex-grow:1}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level-left .level-item:not(:last-child),html.theme--documenter-dark .level-right .level-item:not(:last-child){margin-right:.75rem}}html.theme--documenter-dark .level-left{align-items:center;justify-content:flex-start}@media screen and (max-width: 768px){html.theme--documenter-dark .level-left+.level-right{margin-top:1.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level-left{display:flex}}html.theme--documenter-dark .level-right{align-items:center;justify-content:flex-end}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level-right{display:flex}}html.theme--documenter-dark .list{background-color:#fff;border-radius:.4em;box-shadow:0 2px 3px rgba(10,10,10,0.1),0 0 0 1px rgba(10,10,10,0.1)}html.theme--documenter-dark .list-item{display:block;padding:0.5em 1em}html.theme--documenter-dark .list-item:not(a){color:#fff}html.theme--documenter-dark .list-item:first-child{border-top-left-radius:.4em;border-top-right-radius:.4em}html.theme--documenter-dark .list-item:last-child{border-bottom-left-radius:.4em;border-bottom-right-radius:.4em}html.theme--documenter-dark .list-item:not(:last-child){border-bottom:1px solid #5e6d6f}html.theme--documenter-dark .list-item.is-active{background-color:#1abc9c;color:#fff}html.theme--documenter-dark a.list-item{background-color:#282f2f;cursor:pointer}html.theme--documenter-dark .media{align-items:flex-start;display:flex;text-align:left}html.theme--documenter-dark .media .content:not(:last-child){margin-bottom:0.75rem}html.theme--documenter-dark .media .media{border-top:1px solid rgba(94,109,111,0.5);display:flex;padding-top:0.75rem}html.theme--documenter-dark .media .media .content:not(:last-child),html.theme--documenter-dark .media .media .control:not(:last-child){margin-bottom:0.5rem}html.theme--documenter-dark .media .media .media{padding-top:0.5rem}html.theme--documenter-dark .media .media .media+.media{margin-top:0.5rem}html.theme--documenter-dark .media+.media{border-top:1px solid rgba(94,109,111,0.5);margin-top:1rem;padding-top:1rem}html.theme--documenter-dark .media.is-large+.media{margin-top:1.5rem;padding-top:1.5rem}html.theme--documenter-dark .media-left,html.theme--documenter-dark .media-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--documenter-dark .media-left{margin-right:1rem}html.theme--documenter-dark .media-right{margin-left:1rem}html.theme--documenter-dark .media-content{flex-basis:auto;flex-grow:1;flex-shrink:1;text-align:left}@media screen and (max-width: 768px){html.theme--documenter-dark .media-content{overflow-x:auto}}html.theme--documenter-dark .menu{font-size:15px}html.theme--documenter-dark .menu.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.menu{font-size:.85em}html.theme--documenter-dark .menu.is-medium{font-size:1.25rem}html.theme--documenter-dark .menu.is-large{font-size:1.5rem}html.theme--documenter-dark .menu-list{line-height:1.25}html.theme--documenter-dark .menu-list a{border-radius:3px;color:#fff;display:block;padding:0.5em 0.75em}html.theme--documenter-dark .menu-list a:hover{background-color:#282f2f;color:#f2f2f2}html.theme--documenter-dark .menu-list a.is-active{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .menu-list li ul{border-left:1px solid #5e6d6f;margin:.75em;padding-left:.75em}html.theme--documenter-dark .menu-label{color:#fff;font-size:.75em;letter-spacing:.1em;text-transform:uppercase}html.theme--documenter-dark .menu-label:not(:first-child){margin-top:1em}html.theme--documenter-dark .menu-label:not(:last-child){margin-bottom:1em}html.theme--documenter-dark .message{background-color:#282f2f;border-radius:.4em;font-size:15px}html.theme--documenter-dark .message strong{color:currentColor}html.theme--documenter-dark .message a:not(.button):not(.tag):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--documenter-dark .message.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.message{font-size:.85em}html.theme--documenter-dark .message.is-medium{font-size:1.25rem}html.theme--documenter-dark .message.is-large{font-size:1.5rem}html.theme--documenter-dark .message.is-white{background-color:#fff}html.theme--documenter-dark .message.is-white .message-header{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .message.is-white .message-body{border-color:#fff;color:#4d4d4d}html.theme--documenter-dark .message.is-black{background-color:#fafafa}html.theme--documenter-dark .message.is-black .message-header{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .message.is-black .message-body{border-color:#0a0a0a;color:#090909}html.theme--documenter-dark .message.is-light{background-color:#f9fafb}html.theme--documenter-dark .message.is-light .message-header{background-color:#ecf0f1;color:#282f2f}html.theme--documenter-dark .message.is-light .message-body{border-color:#ecf0f1;color:#505050}html.theme--documenter-dark .message.is-dark,html.theme--documenter-dark .content kbd.message{background-color:#f9fafa}html.theme--documenter-dark .message.is-dark .message-header,html.theme--documenter-dark .content kbd.message .message-header{background-color:#282f2f;color:#ecf0f1}html.theme--documenter-dark .message.is-dark .message-body,html.theme--documenter-dark .content kbd.message .message-body{border-color:#282f2f;color:#212526}html.theme--documenter-dark .message.is-primary,html.theme--documenter-dark .docstring>section>a.message.docs-sourcelink{background-color:#f8fafc}html.theme--documenter-dark .message.is-primary .message-header,html.theme--documenter-dark .docstring>section>a.message.docs-sourcelink .message-header{background-color:#375a7f;color:#fff}html.theme--documenter-dark .message.is-primary .message-body,html.theme--documenter-dark .docstring>section>a.message.docs-sourcelink .message-body{border-color:#375a7f;color:#2b4159}html.theme--documenter-dark .message.is-link{background-color:#f6fefc}html.theme--documenter-dark .message.is-link .message-header{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .message.is-link .message-body{border-color:#1abc9c;color:#0b2f28}html.theme--documenter-dark .message.is-info{background-color:#f5fbff}html.theme--documenter-dark .message.is-info .message-header{background-color:#024c7d;color:#fff}html.theme--documenter-dark .message.is-info .message-body{border-color:#024c7d;color:#033659}html.theme--documenter-dark .message.is-success{background-color:#f5fff9}html.theme--documenter-dark .message.is-success .message-header{background-color:#008438;color:#fff}html.theme--documenter-dark .message.is-success .message-body{border-color:#008438;color:#023518}html.theme--documenter-dark .message.is-warning{background-color:#fffcf5}html.theme--documenter-dark .message.is-warning .message-header{background-color:#ad8100;color:#fff}html.theme--documenter-dark .message.is-warning .message-body{border-color:#ad8100;color:#3d2e03}html.theme--documenter-dark .message.is-danger{background-color:#fef6f6}html.theme--documenter-dark .message.is-danger .message-header{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .message.is-danger .message-body{border-color:#9e1b0d;color:#7a170c}html.theme--documenter-dark .message-header{align-items:center;background-color:#fff;border-radius:.4em .4em 0 0;color:rgba(0,0,0,0.7);display:flex;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.75em 1em;position:relative}html.theme--documenter-dark .message-header .delete{flex-grow:0;flex-shrink:0;margin-left:0.75em}html.theme--documenter-dark .message-header+.message-body{border-width:0;border-top-left-radius:0;border-top-right-radius:0}html.theme--documenter-dark .message-body{border-color:#5e6d6f;border-radius:.4em;border-style:solid;border-width:0 0 0 4px;color:#fff;padding:1.25em 1.5em}html.theme--documenter-dark .message-body code,html.theme--documenter-dark .message-body pre{background-color:#fff}html.theme--documenter-dark .message-body pre code{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .modal{align-items:center;display:none;flex-direction:column;justify-content:center;overflow:hidden;position:fixed;z-index:40}html.theme--documenter-dark .modal.is-active{display:flex}html.theme--documenter-dark .modal-background{background-color:rgba(10,10,10,0.86)}html.theme--documenter-dark .modal-content,html.theme--documenter-dark .modal-card{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width: 769px),print{html.theme--documenter-dark .modal-content,html.theme--documenter-dark .modal-card{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}html.theme--documenter-dark .modal-close{background:none;height:40px;position:fixed;right:20px;top:20px;width:40px}html.theme--documenter-dark .modal-card{display:flex;flex-direction:column;max-height:calc(100vh - 40px);overflow:hidden;-ms-overflow-y:visible}html.theme--documenter-dark .modal-card-head,html.theme--documenter-dark .modal-card-foot{align-items:center;background-color:#282f2f;display:flex;flex-shrink:0;justify-content:flex-start;padding:20px;position:relative}html.theme--documenter-dark .modal-card-head{border-bottom:1px solid #5e6d6f;border-top-left-radius:8px;border-top-right-radius:8px}html.theme--documenter-dark .modal-card-title{color:#f2f2f2;flex-grow:1;flex-shrink:0;font-size:1.5rem;line-height:1}html.theme--documenter-dark .modal-card-foot{border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid #5e6d6f}html.theme--documenter-dark .modal-card-foot .button:not(:last-child){margin-right:0.5em}html.theme--documenter-dark .modal-card-body{-webkit-overflow-scrolling:touch;background-color:#fff;flex-grow:1;flex-shrink:1;overflow:auto;padding:20px}html.theme--documenter-dark .navbar{background-color:#375a7f;min-height:4rem;position:relative;z-index:30}html.theme--documenter-dark .navbar.is-white{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link{color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-white .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-white .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link::after{border-color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-burger{color:#0a0a0a}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-white .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-white .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link{color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-white .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-white .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-white .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-white .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-white .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link::after{border-color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-dropdown a.navbar-item.is-active{background-color:#fff;color:#0a0a0a}}html.theme--documenter-dark .navbar.is-black{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-black .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-black .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link.is-active{background-color:#000;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-black .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-black .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-black .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-black .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-black .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-black .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-black .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link.is-active{background-color:#000;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link{background-color:#000;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-dropdown a.navbar-item.is-active{background-color:#0a0a0a;color:#fff}}html.theme--documenter-dark .navbar.is-light{background-color:#ecf0f1;color:#282f2f}html.theme--documenter-dark .navbar.is-light .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link{color:#282f2f}html.theme--documenter-dark .navbar.is-light .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-light .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-light .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link.is-active{background-color:#dde4e6;color:#282f2f}html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link::after{border-color:#282f2f}html.theme--documenter-dark .navbar.is-light .navbar-burger{color:#282f2f}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-light .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-light .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link{color:#282f2f}html.theme--documenter-dark .navbar.is-light .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-light .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-light .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-light .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-light .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-light .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link.is-active{background-color:#dde4e6;color:#282f2f}html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link::after{border-color:#282f2f}html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link{background-color:#dde4e6;color:#282f2f}html.theme--documenter-dark .navbar.is-light .navbar-dropdown a.navbar-item.is-active{background-color:#ecf0f1;color:#282f2f}}html.theme--documenter-dark .navbar.is-dark,html.theme--documenter-dark .content kbd.navbar{background-color:#282f2f;color:#ecf0f1}html.theme--documenter-dark .navbar.is-dark .navbar-brand>.navbar-item,html.theme--documenter-dark .content kbd.navbar .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link{color:#ecf0f1}html.theme--documenter-dark .navbar.is-dark .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .content kbd.navbar .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-dark .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .content kbd.navbar .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-dark .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link:focus,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link:hover,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link.is-active{background-color:#1d2122;color:#ecf0f1}html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link::after,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link::after{border-color:#ecf0f1}html.theme--documenter-dark .navbar.is-dark .navbar-burger,html.theme--documenter-dark .content kbd.navbar .navbar-burger{color:#ecf0f1}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-dark .navbar-start>.navbar-item,html.theme--documenter-dark .content kbd.navbar .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-dark .navbar-end>.navbar-item,html.theme--documenter-dark .content kbd.navbar .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link{color:#ecf0f1}html.theme--documenter-dark .navbar.is-dark .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .content kbd.navbar .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-dark .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .content kbd.navbar .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-dark .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link:focus,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link:hover,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .content kbd.navbar .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-dark .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .content kbd.navbar .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-dark .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link:focus,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link:hover,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link.is-active{background-color:#1d2122;color:#ecf0f1}html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link::after,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link::after,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link::after{border-color:#ecf0f1}html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown.is-active .navbar-link{background-color:#1d2122;color:#ecf0f1}html.theme--documenter-dark .navbar.is-dark .navbar-dropdown a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-dropdown a.navbar-item.is-active{background-color:#282f2f;color:#ecf0f1}}html.theme--documenter-dark .navbar.is-primary,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink{background-color:#375a7f;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-brand>.navbar-item,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-primary .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-primary .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link.is-active{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link::after,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-burger,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-primary .navbar-start>.navbar-item,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-primary .navbar-end>.navbar-item,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-primary .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-primary .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-primary .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-primary .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link.is-active{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link::after,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link::after,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown.is-active .navbar-link{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#375a7f;color:#fff}}html.theme--documenter-dark .navbar.is-link{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-link .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-link .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link.is-active{background-color:#17a689;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-link .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-link .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-link .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-link .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-link .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-link .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-link .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link.is-active{background-color:#17a689;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link{background-color:#17a689;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-dropdown a.navbar-item.is-active{background-color:#1abc9c;color:#fff}}html.theme--documenter-dark .navbar.is-info{background-color:#024c7d;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-info .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-info .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link.is-active{background-color:#023d64;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-info .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-info .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-info .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-info .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-info .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-info .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-info .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link.is-active{background-color:#023d64;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link{background-color:#023d64;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-dropdown a.navbar-item.is-active{background-color:#024c7d;color:#fff}}html.theme--documenter-dark .navbar.is-success{background-color:#008438;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-success .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-success .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link.is-active{background-color:#006b2d;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-success .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-success .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-success .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-success .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-success .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-success .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-success .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link.is-active{background-color:#006b2d;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link{background-color:#006b2d;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-dropdown a.navbar-item.is-active{background-color:#008438;color:#fff}}html.theme--documenter-dark .navbar.is-warning{background-color:#ad8100;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-warning .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-warning .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link.is-active{background-color:#946e00;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-warning .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-warning .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-warning .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-warning .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-warning .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-warning .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link.is-active{background-color:#946e00;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link{background-color:#946e00;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-dropdown a.navbar-item.is-active{background-color:#ad8100;color:#fff}}html.theme--documenter-dark .navbar.is-danger{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-danger .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-danger .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link.is-active{background-color:#86170b;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-danger .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-danger .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-danger .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-danger .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-danger .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-danger .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link.is-active{background-color:#86170b;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link{background-color:#86170b;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-dropdown a.navbar-item.is-active{background-color:#9e1b0d;color:#fff}}html.theme--documenter-dark .navbar>.container{align-items:stretch;display:flex;min-height:4rem;width:100%}html.theme--documenter-dark .navbar.has-shadow{box-shadow:0 2px 0 0 #282f2f}html.theme--documenter-dark .navbar.is-fixed-bottom,html.theme--documenter-dark .navbar.is-fixed-top{left:0;position:fixed;right:0;z-index:30}html.theme--documenter-dark .navbar.is-fixed-bottom{bottom:0}html.theme--documenter-dark .navbar.is-fixed-bottom.has-shadow{box-shadow:0 -2px 0 0 #282f2f}html.theme--documenter-dark .navbar.is-fixed-top{top:0}html.theme--documenter-dark html.has-navbar-fixed-top,html.theme--documenter-dark body.has-navbar-fixed-top{padding-top:4rem}html.theme--documenter-dark html.has-navbar-fixed-bottom,html.theme--documenter-dark body.has-navbar-fixed-bottom{padding-bottom:4rem}html.theme--documenter-dark .navbar-brand,html.theme--documenter-dark .navbar-tabs{align-items:stretch;display:flex;flex-shrink:0;min-height:4rem}html.theme--documenter-dark .navbar-brand a.navbar-item:focus,html.theme--documenter-dark .navbar-brand a.navbar-item:hover{background-color:transparent}html.theme--documenter-dark .navbar-tabs{-webkit-overflow-scrolling:touch;max-width:100vw;overflow-x:auto;overflow-y:hidden}html.theme--documenter-dark .navbar-burger{color:#fff;cursor:pointer;display:block;height:4rem;position:relative;width:4rem;margin-left:auto}html.theme--documenter-dark .navbar-burger span{background-color:currentColor;display:block;height:1px;left:calc(50% - 8px);position:absolute;transform-origin:center;transition-duration:86ms;transition-property:background-color, opacity, transform;transition-timing-function:ease-out;width:16px}html.theme--documenter-dark .navbar-burger span:nth-child(1){top:calc(50% - 6px)}html.theme--documenter-dark .navbar-burger span:nth-child(2){top:calc(50% - 1px)}html.theme--documenter-dark .navbar-burger span:nth-child(3){top:calc(50% + 4px)}html.theme--documenter-dark .navbar-burger:hover{background-color:rgba(0,0,0,0.05)}html.theme--documenter-dark .navbar-burger.is-active span:nth-child(1){transform:translateY(5px) rotate(45deg)}html.theme--documenter-dark .navbar-burger.is-active span:nth-child(2){opacity:0}html.theme--documenter-dark .navbar-burger.is-active span:nth-child(3){transform:translateY(-5px) rotate(-45deg)}html.theme--documenter-dark .navbar-menu{display:none}html.theme--documenter-dark .navbar-item,html.theme--documenter-dark .navbar-link{color:#fff;display:block;line-height:1.5;padding:0.5rem 0.75rem;position:relative}html.theme--documenter-dark .navbar-item .icon:only-child,html.theme--documenter-dark .navbar-link .icon:only-child{margin-left:-0.25rem;margin-right:-0.25rem}html.theme--documenter-dark a.navbar-item,html.theme--documenter-dark .navbar-link{cursor:pointer}html.theme--documenter-dark a.navbar-item:focus,html.theme--documenter-dark a.navbar-item:focus-within,html.theme--documenter-dark a.navbar-item:hover,html.theme--documenter-dark a.navbar-item.is-active,html.theme--documenter-dark .navbar-link:focus,html.theme--documenter-dark .navbar-link:focus-within,html.theme--documenter-dark .navbar-link:hover,html.theme--documenter-dark .navbar-link.is-active{background-color:rgba(0,0,0,0);color:#1abc9c}html.theme--documenter-dark .navbar-item{display:block;flex-grow:0;flex-shrink:0}html.theme--documenter-dark .navbar-item img{max-height:1.75rem}html.theme--documenter-dark .navbar-item.has-dropdown{padding:0}html.theme--documenter-dark .navbar-item.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .navbar-item.is-tab{border-bottom:1px solid transparent;min-height:4rem;padding-bottom:calc(0.5rem - 1px)}html.theme--documenter-dark .navbar-item.is-tab:focus,html.theme--documenter-dark .navbar-item.is-tab:hover{background-color:rgba(0,0,0,0);border-bottom-color:#1abc9c}html.theme--documenter-dark .navbar-item.is-tab.is-active{background-color:rgba(0,0,0,0);border-bottom-color:#1abc9c;border-bottom-style:solid;border-bottom-width:3px;color:#1abc9c;padding-bottom:calc(0.5rem - 3px)}html.theme--documenter-dark .navbar-content{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .navbar-link:not(.is-arrowless){padding-right:2.5em}html.theme--documenter-dark .navbar-link:not(.is-arrowless)::after{border-color:#fff;margin-top:-0.375em;right:1.125em}html.theme--documenter-dark .navbar-dropdown{font-size:0.875rem;padding-bottom:0.5rem;padding-top:0.5rem}html.theme--documenter-dark .navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}html.theme--documenter-dark .navbar-divider{background-color:rgba(0,0,0,0.2);border:none;display:none;height:2px;margin:0.5rem 0}@media screen and (max-width: 1055px){html.theme--documenter-dark .navbar>.container{display:block}html.theme--documenter-dark .navbar-brand .navbar-item,html.theme--documenter-dark .navbar-tabs .navbar-item{align-items:center;display:flex}html.theme--documenter-dark .navbar-link::after{display:none}html.theme--documenter-dark .navbar-menu{background-color:#375a7f;box-shadow:0 8px 16px rgba(10,10,10,0.1);padding:0.5rem 0}html.theme--documenter-dark .navbar-menu.is-active{display:block}html.theme--documenter-dark .navbar.is-fixed-bottom-touch,html.theme--documenter-dark .navbar.is-fixed-top-touch{left:0;position:fixed;right:0;z-index:30}html.theme--documenter-dark .navbar.is-fixed-bottom-touch{bottom:0}html.theme--documenter-dark .navbar.is-fixed-bottom-touch.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--documenter-dark .navbar.is-fixed-top-touch{top:0}html.theme--documenter-dark .navbar.is-fixed-top .navbar-menu,html.theme--documenter-dark .navbar.is-fixed-top-touch .navbar-menu{-webkit-overflow-scrolling:touch;max-height:calc(100vh - 4rem);overflow:auto}html.theme--documenter-dark html.has-navbar-fixed-top-touch,html.theme--documenter-dark body.has-navbar-fixed-top-touch{padding-top:4rem}html.theme--documenter-dark html.has-navbar-fixed-bottom-touch,html.theme--documenter-dark body.has-navbar-fixed-bottom-touch{padding-bottom:4rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar,html.theme--documenter-dark .navbar-menu,html.theme--documenter-dark .navbar-start,html.theme--documenter-dark .navbar-end{align-items:stretch;display:flex}html.theme--documenter-dark .navbar{min-height:4rem}html.theme--documenter-dark .navbar.is-spaced{padding:1rem 2rem}html.theme--documenter-dark .navbar.is-spaced .navbar-start,html.theme--documenter-dark .navbar.is-spaced .navbar-end{align-items:center}html.theme--documenter-dark .navbar.is-spaced a.navbar-item,html.theme--documenter-dark .navbar.is-spaced .navbar-link{border-radius:.4em}html.theme--documenter-dark .navbar.is-transparent a.navbar-item:focus,html.theme--documenter-dark .navbar.is-transparent a.navbar-item:hover,html.theme--documenter-dark .navbar.is-transparent a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-transparent .navbar-link:focus,html.theme--documenter-dark .navbar.is-transparent .navbar-link:hover,html.theme--documenter-dark .navbar.is-transparent .navbar-link.is-active{background-color:transparent !important}html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link,html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link,html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link,html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link{background-color:transparent !important}html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item:focus,html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#dbdee0}html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#1abc9c}html.theme--documenter-dark .navbar-burger{display:none}html.theme--documenter-dark .navbar-item,html.theme--documenter-dark .navbar-link{align-items:center;display:flex}html.theme--documenter-dark .navbar-item{display:flex}html.theme--documenter-dark .navbar-item.has-dropdown{align-items:stretch}html.theme--documenter-dark .navbar-item.has-dropdown-up .navbar-link::after{transform:rotate(135deg) translate(0.25em, -0.25em)}html.theme--documenter-dark .navbar-item.has-dropdown-up .navbar-dropdown{border-bottom:1px solid rgba(0,0,0,0.2);border-radius:8px 8px 0 0;border-top:none;bottom:100%;box-shadow:0 -8px 8px rgba(10,10,10,0.1);top:auto}html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed{opacity:1;pointer-events:auto;transform:translateY(0)}html.theme--documenter-dark .navbar-menu{flex-grow:1;flex-shrink:0}html.theme--documenter-dark .navbar-start{justify-content:flex-start;margin-right:auto}html.theme--documenter-dark .navbar-end{justify-content:flex-end;margin-left:auto}html.theme--documenter-dark .navbar-dropdown{background-color:#375a7f;border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid rgba(0,0,0,0.2);box-shadow:0 8px 8px rgba(10,10,10,0.1);display:none;font-size:0.875rem;left:0;min-width:100%;position:absolute;top:100%;z-index:20}html.theme--documenter-dark .navbar-dropdown .navbar-item{padding:0.375rem 1rem;white-space:nowrap}html.theme--documenter-dark .navbar-dropdown a.navbar-item{padding-right:3rem}html.theme--documenter-dark .navbar-dropdown a.navbar-item:focus,html.theme--documenter-dark .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#dbdee0}html.theme--documenter-dark .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#1abc9c}.navbar.is-spaced html.theme--documenter-dark .navbar-dropdown,html.theme--documenter-dark .navbar-dropdown.is-boxed{border-radius:8px;border-top:none;box-shadow:0 8px 8px rgba(10,10,10,0.1), 0 0 0 1px rgba(10,10,10,0.1);display:block;opacity:0;pointer-events:none;top:calc(100% + (-4px));transform:translateY(-5px);transition-duration:86ms;transition-property:opacity, transform}html.theme--documenter-dark .navbar-dropdown.is-right{left:auto;right:0}html.theme--documenter-dark .navbar-divider{display:block}html.theme--documenter-dark .navbar>.container .navbar-brand,html.theme--documenter-dark .container>.navbar .navbar-brand{margin-left:-.75rem}html.theme--documenter-dark .navbar>.container .navbar-menu,html.theme--documenter-dark .container>.navbar .navbar-menu{margin-right:-.75rem}html.theme--documenter-dark .navbar.is-fixed-bottom-desktop,html.theme--documenter-dark .navbar.is-fixed-top-desktop{left:0;position:fixed;right:0;z-index:30}html.theme--documenter-dark .navbar.is-fixed-bottom-desktop{bottom:0}html.theme--documenter-dark .navbar.is-fixed-bottom-desktop.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--documenter-dark .navbar.is-fixed-top-desktop{top:0}html.theme--documenter-dark html.has-navbar-fixed-top-desktop,html.theme--documenter-dark body.has-navbar-fixed-top-desktop{padding-top:4rem}html.theme--documenter-dark html.has-navbar-fixed-bottom-desktop,html.theme--documenter-dark body.has-navbar-fixed-bottom-desktop{padding-bottom:4rem}html.theme--documenter-dark html.has-spaced-navbar-fixed-top,html.theme--documenter-dark body.has-spaced-navbar-fixed-top{padding-top:6rem}html.theme--documenter-dark html.has-spaced-navbar-fixed-bottom,html.theme--documenter-dark body.has-spaced-navbar-fixed-bottom{padding-bottom:6rem}html.theme--documenter-dark a.navbar-item.is-active,html.theme--documenter-dark .navbar-link.is-active{color:#1abc9c}html.theme--documenter-dark a.navbar-item.is-active:not(:focus):not(:hover),html.theme--documenter-dark .navbar-link.is-active:not(:focus):not(:hover){background-color:rgba(0,0,0,0)}html.theme--documenter-dark .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar-item.has-dropdown.is-active .navbar-link{background-color:rgba(0,0,0,0)}}html.theme--documenter-dark .hero.is-fullheight-with-navbar{min-height:calc(100vh - 4rem)}html.theme--documenter-dark .pagination{font-size:15px;margin:-.25rem}html.theme--documenter-dark .pagination.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination{font-size:.85em}html.theme--documenter-dark .pagination.is-medium{font-size:1.25rem}html.theme--documenter-dark .pagination.is-large{font-size:1.5rem}html.theme--documenter-dark .pagination.is-rounded .pagination-previous,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination .pagination-previous,html.theme--documenter-dark .pagination.is-rounded .pagination-next,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination .pagination-next{padding-left:1em;padding-right:1em;border-radius:290486px}html.theme--documenter-dark .pagination.is-rounded .pagination-link,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination .pagination-link{border-radius:290486px}html.theme--documenter-dark .pagination,html.theme--documenter-dark .pagination-list{align-items:center;display:flex;justify-content:center;text-align:center}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis{font-size:1em;justify-content:center;margin:.25rem;padding-left:.5em;padding-right:.5em;text-align:center}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link{border-color:#5e6d6f;color:#1abc9c;min-width:2.25em}html.theme--documenter-dark .pagination-previous:hover,html.theme--documenter-dark .pagination-next:hover,html.theme--documenter-dark .pagination-link:hover{border-color:#8c9b9d;color:#1dd2af}html.theme--documenter-dark .pagination-previous:focus,html.theme--documenter-dark .pagination-next:focus,html.theme--documenter-dark .pagination-link:focus{border-color:#8c9b9d}html.theme--documenter-dark .pagination-previous:active,html.theme--documenter-dark .pagination-next:active,html.theme--documenter-dark .pagination-link:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2)}html.theme--documenter-dark .pagination-previous[disabled],html.theme--documenter-dark .pagination-next[disabled],html.theme--documenter-dark .pagination-link[disabled]{background-color:#dbdee0;border-color:#dbdee0;box-shadow:none;color:#5e6d6f;opacity:0.5}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next{padding-left:0.75em;padding-right:0.75em;white-space:nowrap}html.theme--documenter-dark .pagination-link.is-current{background-color:#1abc9c;border-color:#1abc9c;color:#fff}html.theme--documenter-dark .pagination-ellipsis{color:#8c9b9d;pointer-events:none}html.theme--documenter-dark .pagination-list{flex-wrap:wrap}@media screen and (max-width: 768px){html.theme--documenter-dark .pagination{flex-wrap:wrap}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .pagination-list li{flex-grow:1;flex-shrink:1}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .pagination-list{flex-grow:1;flex-shrink:1;justify-content:flex-start;order:1}html.theme--documenter-dark .pagination-previous{order:2}html.theme--documenter-dark .pagination-next{order:3}html.theme--documenter-dark .pagination{justify-content:space-between}html.theme--documenter-dark .pagination.is-centered .pagination-previous{order:1}html.theme--documenter-dark .pagination.is-centered .pagination-list{justify-content:center;order:2}html.theme--documenter-dark .pagination.is-centered .pagination-next{order:3}html.theme--documenter-dark .pagination.is-right .pagination-previous{order:1}html.theme--documenter-dark .pagination.is-right .pagination-next{order:2}html.theme--documenter-dark .pagination.is-right .pagination-list{justify-content:flex-end;order:3}}html.theme--documenter-dark .panel{font-size:15px}html.theme--documenter-dark .panel:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .panel-heading,html.theme--documenter-dark .panel-tabs,html.theme--documenter-dark .panel-block{border-bottom:1px solid #5e6d6f;border-left:1px solid #5e6d6f;border-right:1px solid #5e6d6f}html.theme--documenter-dark .panel-heading:first-child,html.theme--documenter-dark .panel-tabs:first-child,html.theme--documenter-dark .panel-block:first-child{border-top:1px solid #5e6d6f}html.theme--documenter-dark .panel-heading{background-color:#282f2f;border-radius:.4em .4em 0 0;color:#f2f2f2;font-size:1.25em;font-weight:300;line-height:1.25;padding:0.5em 0.75em}html.theme--documenter-dark .panel-tabs{align-items:flex-end;display:flex;font-size:.875em;justify-content:center}html.theme--documenter-dark .panel-tabs a{border-bottom:1px solid #5e6d6f;margin-bottom:-1px;padding:0.5em}html.theme--documenter-dark .panel-tabs a.is-active{border-bottom-color:#343c3d;color:#17a689}html.theme--documenter-dark .panel-list a{color:#fff}html.theme--documenter-dark .panel-list a:hover{color:#1abc9c}html.theme--documenter-dark .panel-block{align-items:center;color:#f2f2f2;display:flex;justify-content:flex-start;padding:0.5em 0.75em}html.theme--documenter-dark .panel-block input[type="checkbox"]{margin-right:0.75em}html.theme--documenter-dark .panel-block>.control{flex-grow:1;flex-shrink:1;width:100%}html.theme--documenter-dark .panel-block.is-wrapped{flex-wrap:wrap}html.theme--documenter-dark .panel-block.is-active{border-left-color:#1abc9c;color:#17a689}html.theme--documenter-dark .panel-block.is-active .panel-icon{color:#1abc9c}html.theme--documenter-dark a.panel-block,html.theme--documenter-dark label.panel-block{cursor:pointer}html.theme--documenter-dark a.panel-block:hover,html.theme--documenter-dark label.panel-block:hover{background-color:#282f2f}html.theme--documenter-dark .panel-icon{display:inline-block;font-size:14px;height:1em;line-height:1em;text-align:center;vertical-align:top;width:1em;color:#fff;margin-right:0.75em}html.theme--documenter-dark .panel-icon .fa{font-size:inherit;line-height:inherit}html.theme--documenter-dark .tabs{-webkit-overflow-scrolling:touch;align-items:stretch;display:flex;font-size:15px;justify-content:space-between;overflow:hidden;overflow-x:auto;white-space:nowrap}html.theme--documenter-dark .tabs a{align-items:center;border-bottom-color:#5e6d6f;border-bottom-style:solid;border-bottom-width:1px;color:#fff;display:flex;justify-content:center;margin-bottom:-1px;padding:0.5em 1em;vertical-align:top}html.theme--documenter-dark .tabs a:hover{border-bottom-color:#f2f2f2;color:#f2f2f2}html.theme--documenter-dark .tabs li{display:block}html.theme--documenter-dark .tabs li.is-active a{border-bottom-color:#1abc9c;color:#1abc9c}html.theme--documenter-dark .tabs ul{align-items:center;border-bottom-color:#5e6d6f;border-bottom-style:solid;border-bottom-width:1px;display:flex;flex-grow:1;flex-shrink:0;justify-content:flex-start}html.theme--documenter-dark .tabs ul.is-left{padding-right:0.75em}html.theme--documenter-dark .tabs ul.is-center{flex:none;justify-content:center;padding-left:0.75em;padding-right:0.75em}html.theme--documenter-dark .tabs ul.is-right{justify-content:flex-end;padding-left:0.75em}html.theme--documenter-dark .tabs .icon:first-child{margin-right:0.5em}html.theme--documenter-dark .tabs .icon:last-child{margin-left:0.5em}html.theme--documenter-dark .tabs.is-centered ul{justify-content:center}html.theme--documenter-dark .tabs.is-right ul{justify-content:flex-end}html.theme--documenter-dark .tabs.is-boxed a{border:1px solid transparent;border-radius:.4em .4em 0 0}html.theme--documenter-dark .tabs.is-boxed a:hover{background-color:#282f2f;border-bottom-color:#5e6d6f}html.theme--documenter-dark .tabs.is-boxed li.is-active a{background-color:#fff;border-color:#5e6d6f;border-bottom-color:rgba(0,0,0,0) !important}html.theme--documenter-dark .tabs.is-fullwidth li{flex-grow:1;flex-shrink:0}html.theme--documenter-dark .tabs.is-toggle a{border-color:#5e6d6f;border-style:solid;border-width:1px;margin-bottom:0;position:relative}html.theme--documenter-dark .tabs.is-toggle a:hover{background-color:#282f2f;border-color:#8c9b9d;z-index:2}html.theme--documenter-dark .tabs.is-toggle li+li{margin-left:-1px}html.theme--documenter-dark .tabs.is-toggle li:first-child a{border-radius:.4em 0 0 .4em}html.theme--documenter-dark .tabs.is-toggle li:last-child a{border-radius:0 .4em .4em 0}html.theme--documenter-dark .tabs.is-toggle li.is-active a{background-color:#1abc9c;border-color:#1abc9c;color:#fff;z-index:1}html.theme--documenter-dark .tabs.is-toggle ul{border-bottom:none}html.theme--documenter-dark .tabs.is-toggle.is-toggle-rounded li:first-child a{border-bottom-left-radius:290486px;border-top-left-radius:290486px;padding-left:1.25em}html.theme--documenter-dark .tabs.is-toggle.is-toggle-rounded li:last-child a{border-bottom-right-radius:290486px;border-top-right-radius:290486px;padding-right:1.25em}html.theme--documenter-dark .tabs.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.tabs{font-size:.85em}html.theme--documenter-dark .tabs.is-medium{font-size:1.25rem}html.theme--documenter-dark .tabs.is-large{font-size:1.5rem}html.theme--documenter-dark .column{display:block;flex-basis:0;flex-grow:1;flex-shrink:1;padding:.75rem}.columns.is-mobile>html.theme--documenter-dark .column.is-narrow{flex:none}.columns.is-mobile>html.theme--documenter-dark .column.is-full{flex:none;width:100%}.columns.is-mobile>html.theme--documenter-dark .column.is-three-quarters{flex:none;width:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-two-thirds{flex:none;width:66.6666%}.columns.is-mobile>html.theme--documenter-dark .column.is-half{flex:none;width:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-one-third{flex:none;width:33.3333%}.columns.is-mobile>html.theme--documenter-dark .column.is-one-quarter{flex:none;width:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-one-fifth{flex:none;width:20%}.columns.is-mobile>html.theme--documenter-dark .column.is-two-fifths{flex:none;width:40%}.columns.is-mobile>html.theme--documenter-dark .column.is-three-fifths{flex:none;width:60%}.columns.is-mobile>html.theme--documenter-dark .column.is-four-fifths{flex:none;width:80%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-three-quarters{margin-left:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-two-thirds{margin-left:66.6666%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-half{margin-left:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-one-third{margin-left:33.3333%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-one-quarter{margin-left:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-one-fifth{margin-left:20%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-two-fifths{margin-left:40%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-three-fifths{margin-left:60%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-four-fifths{margin-left:80%}.columns.is-mobile>html.theme--documenter-dark .column.is-0{flex:none;width:0%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-0{margin-left:0%}.columns.is-mobile>html.theme--documenter-dark .column.is-1{flex:none;width:8.3333333333%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-1{margin-left:8.3333333333%}.columns.is-mobile>html.theme--documenter-dark .column.is-2{flex:none;width:16.6666666667%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-2{margin-left:16.6666666667%}.columns.is-mobile>html.theme--documenter-dark .column.is-3{flex:none;width:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-3{margin-left:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-4{flex:none;width:33.3333333333%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-4{margin-left:33.3333333333%}.columns.is-mobile>html.theme--documenter-dark .column.is-5{flex:none;width:41.6666666667%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-5{margin-left:41.6666666667%}.columns.is-mobile>html.theme--documenter-dark .column.is-6{flex:none;width:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-6{margin-left:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-7{flex:none;width:58.3333333333%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-7{margin-left:58.3333333333%}.columns.is-mobile>html.theme--documenter-dark .column.is-8{flex:none;width:66.6666666667%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-8{margin-left:66.6666666667%}.columns.is-mobile>html.theme--documenter-dark .column.is-9{flex:none;width:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-9{margin-left:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-10{flex:none;width:83.3333333333%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-10{margin-left:83.3333333333%}.columns.is-mobile>html.theme--documenter-dark .column.is-11{flex:none;width:91.6666666667%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-11{margin-left:91.6666666667%}.columns.is-mobile>html.theme--documenter-dark .column.is-12{flex:none;width:100%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-12{margin-left:100%}@media screen and (max-width: 768px){html.theme--documenter-dark .column.is-narrow-mobile{flex:none}html.theme--documenter-dark .column.is-full-mobile{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-mobile{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-mobile{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-mobile{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-mobile{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-mobile{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-mobile{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-mobile{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-mobile{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-mobile{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-mobile{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-mobile{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-mobile{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-mobile{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-mobile{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-mobile{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-mobile{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-mobile{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-mobile{margin-left:80%}html.theme--documenter-dark .column.is-0-mobile{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-mobile{margin-left:0%}html.theme--documenter-dark .column.is-1-mobile{flex:none;width:8.3333333333%}html.theme--documenter-dark .column.is-offset-1-mobile{margin-left:8.3333333333%}html.theme--documenter-dark .column.is-2-mobile{flex:none;width:16.6666666667%}html.theme--documenter-dark .column.is-offset-2-mobile{margin-left:16.6666666667%}html.theme--documenter-dark .column.is-3-mobile{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-mobile{margin-left:25%}html.theme--documenter-dark .column.is-4-mobile{flex:none;width:33.3333333333%}html.theme--documenter-dark .column.is-offset-4-mobile{margin-left:33.3333333333%}html.theme--documenter-dark .column.is-5-mobile{flex:none;width:41.6666666667%}html.theme--documenter-dark .column.is-offset-5-mobile{margin-left:41.6666666667%}html.theme--documenter-dark .column.is-6-mobile{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-mobile{margin-left:50%}html.theme--documenter-dark .column.is-7-mobile{flex:none;width:58.3333333333%}html.theme--documenter-dark .column.is-offset-7-mobile{margin-left:58.3333333333%}html.theme--documenter-dark .column.is-8-mobile{flex:none;width:66.6666666667%}html.theme--documenter-dark .column.is-offset-8-mobile{margin-left:66.6666666667%}html.theme--documenter-dark .column.is-9-mobile{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-mobile{margin-left:75%}html.theme--documenter-dark .column.is-10-mobile{flex:none;width:83.3333333333%}html.theme--documenter-dark .column.is-offset-10-mobile{margin-left:83.3333333333%}html.theme--documenter-dark .column.is-11-mobile{flex:none;width:91.6666666667%}html.theme--documenter-dark .column.is-offset-11-mobile{margin-left:91.6666666667%}html.theme--documenter-dark .column.is-12-mobile{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-mobile{margin-left:100%}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .column.is-narrow,html.theme--documenter-dark .column.is-narrow-tablet{flex:none}html.theme--documenter-dark .column.is-full,html.theme--documenter-dark .column.is-full-tablet{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters,html.theme--documenter-dark .column.is-three-quarters-tablet{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds,html.theme--documenter-dark .column.is-two-thirds-tablet{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half,html.theme--documenter-dark .column.is-half-tablet{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third,html.theme--documenter-dark .column.is-one-third-tablet{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter,html.theme--documenter-dark .column.is-one-quarter-tablet{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth,html.theme--documenter-dark .column.is-one-fifth-tablet{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths,html.theme--documenter-dark .column.is-two-fifths-tablet{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths,html.theme--documenter-dark .column.is-three-fifths-tablet{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths,html.theme--documenter-dark .column.is-four-fifths-tablet{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters,html.theme--documenter-dark .column.is-offset-three-quarters-tablet{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds,html.theme--documenter-dark .column.is-offset-two-thirds-tablet{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half,html.theme--documenter-dark .column.is-offset-half-tablet{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third,html.theme--documenter-dark .column.is-offset-one-third-tablet{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter,html.theme--documenter-dark .column.is-offset-one-quarter-tablet{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth,html.theme--documenter-dark .column.is-offset-one-fifth-tablet{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths,html.theme--documenter-dark .column.is-offset-two-fifths-tablet{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths,html.theme--documenter-dark .column.is-offset-three-fifths-tablet{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths,html.theme--documenter-dark .column.is-offset-four-fifths-tablet{margin-left:80%}html.theme--documenter-dark .column.is-0,html.theme--documenter-dark .column.is-0-tablet{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0,html.theme--documenter-dark .column.is-offset-0-tablet{margin-left:0%}html.theme--documenter-dark .column.is-1,html.theme--documenter-dark .column.is-1-tablet{flex:none;width:8.3333333333%}html.theme--documenter-dark .column.is-offset-1,html.theme--documenter-dark .column.is-offset-1-tablet{margin-left:8.3333333333%}html.theme--documenter-dark .column.is-2,html.theme--documenter-dark .column.is-2-tablet{flex:none;width:16.6666666667%}html.theme--documenter-dark .column.is-offset-2,html.theme--documenter-dark .column.is-offset-2-tablet{margin-left:16.6666666667%}html.theme--documenter-dark .column.is-3,html.theme--documenter-dark .column.is-3-tablet{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3,html.theme--documenter-dark .column.is-offset-3-tablet{margin-left:25%}html.theme--documenter-dark .column.is-4,html.theme--documenter-dark .column.is-4-tablet{flex:none;width:33.3333333333%}html.theme--documenter-dark .column.is-offset-4,html.theme--documenter-dark .column.is-offset-4-tablet{margin-left:33.3333333333%}html.theme--documenter-dark .column.is-5,html.theme--documenter-dark .column.is-5-tablet{flex:none;width:41.6666666667%}html.theme--documenter-dark .column.is-offset-5,html.theme--documenter-dark .column.is-offset-5-tablet{margin-left:41.6666666667%}html.theme--documenter-dark .column.is-6,html.theme--documenter-dark .column.is-6-tablet{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6,html.theme--documenter-dark .column.is-offset-6-tablet{margin-left:50%}html.theme--documenter-dark .column.is-7,html.theme--documenter-dark .column.is-7-tablet{flex:none;width:58.3333333333%}html.theme--documenter-dark .column.is-offset-7,html.theme--documenter-dark .column.is-offset-7-tablet{margin-left:58.3333333333%}html.theme--documenter-dark .column.is-8,html.theme--documenter-dark .column.is-8-tablet{flex:none;width:66.6666666667%}html.theme--documenter-dark .column.is-offset-8,html.theme--documenter-dark .column.is-offset-8-tablet{margin-left:66.6666666667%}html.theme--documenter-dark .column.is-9,html.theme--documenter-dark .column.is-9-tablet{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9,html.theme--documenter-dark .column.is-offset-9-tablet{margin-left:75%}html.theme--documenter-dark .column.is-10,html.theme--documenter-dark .column.is-10-tablet{flex:none;width:83.3333333333%}html.theme--documenter-dark .column.is-offset-10,html.theme--documenter-dark .column.is-offset-10-tablet{margin-left:83.3333333333%}html.theme--documenter-dark .column.is-11,html.theme--documenter-dark .column.is-11-tablet{flex:none;width:91.6666666667%}html.theme--documenter-dark .column.is-offset-11,html.theme--documenter-dark .column.is-offset-11-tablet{margin-left:91.6666666667%}html.theme--documenter-dark .column.is-12,html.theme--documenter-dark .column.is-12-tablet{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12,html.theme--documenter-dark .column.is-offset-12-tablet{margin-left:100%}}@media screen and (max-width: 1055px){html.theme--documenter-dark .column.is-narrow-touch{flex:none}html.theme--documenter-dark .column.is-full-touch{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-touch{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-touch{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-touch{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-touch{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-touch{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-touch{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-touch{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-touch{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-touch{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-touch{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-touch{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-touch{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-touch{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-touch{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-touch{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-touch{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-touch{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-touch{margin-left:80%}html.theme--documenter-dark .column.is-0-touch{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-touch{margin-left:0%}html.theme--documenter-dark .column.is-1-touch{flex:none;width:8.3333333333%}html.theme--documenter-dark .column.is-offset-1-touch{margin-left:8.3333333333%}html.theme--documenter-dark .column.is-2-touch{flex:none;width:16.6666666667%}html.theme--documenter-dark .column.is-offset-2-touch{margin-left:16.6666666667%}html.theme--documenter-dark .column.is-3-touch{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-touch{margin-left:25%}html.theme--documenter-dark .column.is-4-touch{flex:none;width:33.3333333333%}html.theme--documenter-dark .column.is-offset-4-touch{margin-left:33.3333333333%}html.theme--documenter-dark .column.is-5-touch{flex:none;width:41.6666666667%}html.theme--documenter-dark .column.is-offset-5-touch{margin-left:41.6666666667%}html.theme--documenter-dark .column.is-6-touch{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-touch{margin-left:50%}html.theme--documenter-dark .column.is-7-touch{flex:none;width:58.3333333333%}html.theme--documenter-dark .column.is-offset-7-touch{margin-left:58.3333333333%}html.theme--documenter-dark .column.is-8-touch{flex:none;width:66.6666666667%}html.theme--documenter-dark .column.is-offset-8-touch{margin-left:66.6666666667%}html.theme--documenter-dark .column.is-9-touch{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-touch{margin-left:75%}html.theme--documenter-dark .column.is-10-touch{flex:none;width:83.3333333333%}html.theme--documenter-dark .column.is-offset-10-touch{margin-left:83.3333333333%}html.theme--documenter-dark .column.is-11-touch{flex:none;width:91.6666666667%}html.theme--documenter-dark .column.is-offset-11-touch{margin-left:91.6666666667%}html.theme--documenter-dark .column.is-12-touch{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-touch{margin-left:100%}}@media screen and (min-width: 1056px){html.theme--documenter-dark .column.is-narrow-desktop{flex:none}html.theme--documenter-dark .column.is-full-desktop{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-desktop{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-desktop{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-desktop{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-desktop{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-desktop{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-desktop{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-desktop{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-desktop{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-desktop{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-desktop{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-desktop{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-desktop{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-desktop{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-desktop{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-desktop{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-desktop{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-desktop{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-desktop{margin-left:80%}html.theme--documenter-dark .column.is-0-desktop{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-desktop{margin-left:0%}html.theme--documenter-dark .column.is-1-desktop{flex:none;width:8.3333333333%}html.theme--documenter-dark .column.is-offset-1-desktop{margin-left:8.3333333333%}html.theme--documenter-dark .column.is-2-desktop{flex:none;width:16.6666666667%}html.theme--documenter-dark .column.is-offset-2-desktop{margin-left:16.6666666667%}html.theme--documenter-dark .column.is-3-desktop{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-desktop{margin-left:25%}html.theme--documenter-dark .column.is-4-desktop{flex:none;width:33.3333333333%}html.theme--documenter-dark .column.is-offset-4-desktop{margin-left:33.3333333333%}html.theme--documenter-dark .column.is-5-desktop{flex:none;width:41.6666666667%}html.theme--documenter-dark .column.is-offset-5-desktop{margin-left:41.6666666667%}html.theme--documenter-dark .column.is-6-desktop{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-desktop{margin-left:50%}html.theme--documenter-dark .column.is-7-desktop{flex:none;width:58.3333333333%}html.theme--documenter-dark .column.is-offset-7-desktop{margin-left:58.3333333333%}html.theme--documenter-dark .column.is-8-desktop{flex:none;width:66.6666666667%}html.theme--documenter-dark .column.is-offset-8-desktop{margin-left:66.6666666667%}html.theme--documenter-dark .column.is-9-desktop{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-desktop{margin-left:75%}html.theme--documenter-dark .column.is-10-desktop{flex:none;width:83.3333333333%}html.theme--documenter-dark .column.is-offset-10-desktop{margin-left:83.3333333333%}html.theme--documenter-dark .column.is-11-desktop{flex:none;width:91.6666666667%}html.theme--documenter-dark .column.is-offset-11-desktop{margin-left:91.6666666667%}html.theme--documenter-dark .column.is-12-desktop{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-desktop{margin-left:100%}}@media screen and (min-width: 1216px){html.theme--documenter-dark .column.is-narrow-widescreen{flex:none}html.theme--documenter-dark .column.is-full-widescreen{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-widescreen{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-widescreen{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-widescreen{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-widescreen{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-widescreen{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-widescreen{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-widescreen{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-widescreen{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-widescreen{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-widescreen{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-widescreen{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-widescreen{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-widescreen{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-widescreen{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-widescreen{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-widescreen{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-widescreen{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-widescreen{margin-left:80%}html.theme--documenter-dark .column.is-0-widescreen{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-widescreen{margin-left:0%}html.theme--documenter-dark .column.is-1-widescreen{flex:none;width:8.3333333333%}html.theme--documenter-dark .column.is-offset-1-widescreen{margin-left:8.3333333333%}html.theme--documenter-dark .column.is-2-widescreen{flex:none;width:16.6666666667%}html.theme--documenter-dark .column.is-offset-2-widescreen{margin-left:16.6666666667%}html.theme--documenter-dark .column.is-3-widescreen{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-widescreen{margin-left:25%}html.theme--documenter-dark .column.is-4-widescreen{flex:none;width:33.3333333333%}html.theme--documenter-dark .column.is-offset-4-widescreen{margin-left:33.3333333333%}html.theme--documenter-dark .column.is-5-widescreen{flex:none;width:41.6666666667%}html.theme--documenter-dark .column.is-offset-5-widescreen{margin-left:41.6666666667%}html.theme--documenter-dark .column.is-6-widescreen{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-widescreen{margin-left:50%}html.theme--documenter-dark .column.is-7-widescreen{flex:none;width:58.3333333333%}html.theme--documenter-dark .column.is-offset-7-widescreen{margin-left:58.3333333333%}html.theme--documenter-dark .column.is-8-widescreen{flex:none;width:66.6666666667%}html.theme--documenter-dark .column.is-offset-8-widescreen{margin-left:66.6666666667%}html.theme--documenter-dark .column.is-9-widescreen{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-widescreen{margin-left:75%}html.theme--documenter-dark .column.is-10-widescreen{flex:none;width:83.3333333333%}html.theme--documenter-dark .column.is-offset-10-widescreen{margin-left:83.3333333333%}html.theme--documenter-dark .column.is-11-widescreen{flex:none;width:91.6666666667%}html.theme--documenter-dark .column.is-offset-11-widescreen{margin-left:91.6666666667%}html.theme--documenter-dark .column.is-12-widescreen{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-widescreen{margin-left:100%}}@media screen and (min-width: 1408px){html.theme--documenter-dark .column.is-narrow-fullhd{flex:none}html.theme--documenter-dark .column.is-full-fullhd{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-fullhd{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-fullhd{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-fullhd{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-fullhd{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-fullhd{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-fullhd{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-fullhd{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-fullhd{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-fullhd{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-fullhd{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-fullhd{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-fullhd{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-fullhd{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-fullhd{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-fullhd{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-fullhd{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-fullhd{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-fullhd{margin-left:80%}html.theme--documenter-dark .column.is-0-fullhd{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-fullhd{margin-left:0%}html.theme--documenter-dark .column.is-1-fullhd{flex:none;width:8.3333333333%}html.theme--documenter-dark .column.is-offset-1-fullhd{margin-left:8.3333333333%}html.theme--documenter-dark .column.is-2-fullhd{flex:none;width:16.6666666667%}html.theme--documenter-dark .column.is-offset-2-fullhd{margin-left:16.6666666667%}html.theme--documenter-dark .column.is-3-fullhd{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-fullhd{margin-left:25%}html.theme--documenter-dark .column.is-4-fullhd{flex:none;width:33.3333333333%}html.theme--documenter-dark .column.is-offset-4-fullhd{margin-left:33.3333333333%}html.theme--documenter-dark .column.is-5-fullhd{flex:none;width:41.6666666667%}html.theme--documenter-dark .column.is-offset-5-fullhd{margin-left:41.6666666667%}html.theme--documenter-dark .column.is-6-fullhd{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-fullhd{margin-left:50%}html.theme--documenter-dark .column.is-7-fullhd{flex:none;width:58.3333333333%}html.theme--documenter-dark .column.is-offset-7-fullhd{margin-left:58.3333333333%}html.theme--documenter-dark .column.is-8-fullhd{flex:none;width:66.6666666667%}html.theme--documenter-dark .column.is-offset-8-fullhd{margin-left:66.6666666667%}html.theme--documenter-dark .column.is-9-fullhd{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-fullhd{margin-left:75%}html.theme--documenter-dark .column.is-10-fullhd{flex:none;width:83.3333333333%}html.theme--documenter-dark .column.is-offset-10-fullhd{margin-left:83.3333333333%}html.theme--documenter-dark .column.is-11-fullhd{flex:none;width:91.6666666667%}html.theme--documenter-dark .column.is-offset-11-fullhd{margin-left:91.6666666667%}html.theme--documenter-dark .column.is-12-fullhd{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-fullhd{margin-left:100%}}html.theme--documenter-dark .columns{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--documenter-dark .columns:last-child{margin-bottom:-.75rem}html.theme--documenter-dark .columns:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}html.theme--documenter-dark .columns.is-centered{justify-content:center}html.theme--documenter-dark .columns.is-gapless{margin-left:0;margin-right:0;margin-top:0}html.theme--documenter-dark .columns.is-gapless>.column{margin:0;padding:0 !important}html.theme--documenter-dark .columns.is-gapless:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .columns.is-gapless:last-child{margin-bottom:0}html.theme--documenter-dark .columns.is-mobile{display:flex}html.theme--documenter-dark .columns.is-multiline{flex-wrap:wrap}html.theme--documenter-dark .columns.is-vcentered{align-items:center}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns:not(.is-desktop){display:flex}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-desktop{display:flex}}html.theme--documenter-dark .columns.is-variable{--columnGap: 0.75rem;margin-left:calc(-1 * var(--columnGap));margin-right:calc(-1 * var(--columnGap))}html.theme--documenter-dark .columns.is-variable .column{padding-left:var(--columnGap);padding-right:var(--columnGap)}html.theme--documenter-dark .columns.is-variable.is-0{--columnGap: 0rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-0-mobile{--columnGap: 0rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-0-tablet{--columnGap: 0rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-0-tablet-only{--columnGap: 0rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-0-touch{--columnGap: 0rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-0-desktop{--columnGap: 0rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-0-desktop-only{--columnGap: 0rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-0-widescreen{--columnGap: 0rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-0-widescreen-only{--columnGap: 0rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-0-fullhd{--columnGap: 0rem}}html.theme--documenter-dark .columns.is-variable.is-1{--columnGap: .25rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-1-mobile{--columnGap: .25rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-1-tablet{--columnGap: .25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-1-tablet-only{--columnGap: .25rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-1-touch{--columnGap: .25rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-1-desktop{--columnGap: .25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-1-desktop-only{--columnGap: .25rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-1-widescreen{--columnGap: .25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-1-widescreen-only{--columnGap: .25rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-1-fullhd{--columnGap: .25rem}}html.theme--documenter-dark .columns.is-variable.is-2{--columnGap: .5rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-2-mobile{--columnGap: .5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-2-tablet{--columnGap: .5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-2-tablet-only{--columnGap: .5rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-2-touch{--columnGap: .5rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-2-desktop{--columnGap: .5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-2-desktop-only{--columnGap: .5rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-2-widescreen{--columnGap: .5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-2-widescreen-only{--columnGap: .5rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-2-fullhd{--columnGap: .5rem}}html.theme--documenter-dark .columns.is-variable.is-3{--columnGap: .75rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-3-mobile{--columnGap: .75rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-3-tablet{--columnGap: .75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-3-tablet-only{--columnGap: .75rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-3-touch{--columnGap: .75rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-3-desktop{--columnGap: .75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-3-desktop-only{--columnGap: .75rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-3-widescreen{--columnGap: .75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-3-widescreen-only{--columnGap: .75rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-3-fullhd{--columnGap: .75rem}}html.theme--documenter-dark .columns.is-variable.is-4{--columnGap: 1rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-4-mobile{--columnGap: 1rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-4-tablet{--columnGap: 1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-4-tablet-only{--columnGap: 1rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-4-touch{--columnGap: 1rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-4-desktop{--columnGap: 1rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-4-desktop-only{--columnGap: 1rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-4-widescreen{--columnGap: 1rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-4-widescreen-only{--columnGap: 1rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-4-fullhd{--columnGap: 1rem}}html.theme--documenter-dark .columns.is-variable.is-5{--columnGap: 1.25rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-5-mobile{--columnGap: 1.25rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-5-tablet{--columnGap: 1.25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-5-tablet-only{--columnGap: 1.25rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-5-touch{--columnGap: 1.25rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-5-desktop{--columnGap: 1.25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-5-desktop-only{--columnGap: 1.25rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-5-widescreen{--columnGap: 1.25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-5-widescreen-only{--columnGap: 1.25rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-5-fullhd{--columnGap: 1.25rem}}html.theme--documenter-dark .columns.is-variable.is-6{--columnGap: 1.5rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-6-mobile{--columnGap: 1.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-6-tablet{--columnGap: 1.5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-6-tablet-only{--columnGap: 1.5rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-6-touch{--columnGap: 1.5rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-6-desktop{--columnGap: 1.5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-6-desktop-only{--columnGap: 1.5rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-6-widescreen{--columnGap: 1.5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-6-widescreen-only{--columnGap: 1.5rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-6-fullhd{--columnGap: 1.5rem}}html.theme--documenter-dark .columns.is-variable.is-7{--columnGap: 1.75rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-7-mobile{--columnGap: 1.75rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-7-tablet{--columnGap: 1.75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-7-tablet-only{--columnGap: 1.75rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-7-touch{--columnGap: 1.75rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-7-desktop{--columnGap: 1.75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-7-desktop-only{--columnGap: 1.75rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-7-widescreen{--columnGap: 1.75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-7-widescreen-only{--columnGap: 1.75rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-7-fullhd{--columnGap: 1.75rem}}html.theme--documenter-dark .columns.is-variable.is-8{--columnGap: 2rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-8-mobile{--columnGap: 2rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-8-tablet{--columnGap: 2rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-8-tablet-only{--columnGap: 2rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-8-touch{--columnGap: 2rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-8-desktop{--columnGap: 2rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-8-desktop-only{--columnGap: 2rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-8-widescreen{--columnGap: 2rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-8-widescreen-only{--columnGap: 2rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-8-fullhd{--columnGap: 2rem}}html.theme--documenter-dark .tile{align-items:stretch;display:block;flex-basis:0;flex-grow:1;flex-shrink:1;min-height:min-content}html.theme--documenter-dark .tile.is-ancestor{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--documenter-dark .tile.is-ancestor:last-child{margin-bottom:-.75rem}html.theme--documenter-dark .tile.is-ancestor:not(:last-child){margin-bottom:.75rem}html.theme--documenter-dark .tile.is-child{margin:0 !important}html.theme--documenter-dark .tile.is-parent{padding:.75rem}html.theme--documenter-dark .tile.is-vertical{flex-direction:column}html.theme--documenter-dark .tile.is-vertical>.tile.is-child:not(:last-child){margin-bottom:1.5rem !important}@media screen and (min-width: 769px),print{html.theme--documenter-dark .tile:not(.is-child){display:flex}html.theme--documenter-dark .tile.is-1{flex:none;width:8.3333333333%}html.theme--documenter-dark .tile.is-2{flex:none;width:16.6666666667%}html.theme--documenter-dark .tile.is-3{flex:none;width:25%}html.theme--documenter-dark .tile.is-4{flex:none;width:33.3333333333%}html.theme--documenter-dark .tile.is-5{flex:none;width:41.6666666667%}html.theme--documenter-dark .tile.is-6{flex:none;width:50%}html.theme--documenter-dark .tile.is-7{flex:none;width:58.3333333333%}html.theme--documenter-dark .tile.is-8{flex:none;width:66.6666666667%}html.theme--documenter-dark .tile.is-9{flex:none;width:75%}html.theme--documenter-dark .tile.is-10{flex:none;width:83.3333333333%}html.theme--documenter-dark .tile.is-11{flex:none;width:91.6666666667%}html.theme--documenter-dark .tile.is-12{flex:none;width:100%}}html.theme--documenter-dark .hero{align-items:stretch;display:flex;flex-direction:column;justify-content:space-between}html.theme--documenter-dark .hero .navbar{background:none}html.theme--documenter-dark .hero .tabs ul{border-bottom:none}html.theme--documenter-dark .hero.is-white{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-white strong{color:inherit}html.theme--documenter-dark .hero.is-white .title{color:#0a0a0a}html.theme--documenter-dark .hero.is-white .subtitle{color:rgba(10,10,10,0.9)}html.theme--documenter-dark .hero.is-white .subtitle a:not(.button),html.theme--documenter-dark .hero.is-white .subtitle strong{color:#0a0a0a}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-white .navbar-menu{background-color:#fff}}html.theme--documenter-dark .hero.is-white .navbar-item,html.theme--documenter-dark .hero.is-white .navbar-link{color:rgba(10,10,10,0.7)}html.theme--documenter-dark .hero.is-white a.navbar-item:hover,html.theme--documenter-dark .hero.is-white a.navbar-item.is-active,html.theme--documenter-dark .hero.is-white .navbar-link:hover,html.theme--documenter-dark .hero.is-white .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .hero.is-white .tabs a{color:#0a0a0a;opacity:0.9}html.theme--documenter-dark .hero.is-white .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-white .tabs li.is-active a{opacity:1}html.theme--documenter-dark .hero.is-white .tabs.is-boxed a,html.theme--documenter-dark .hero.is-white .tabs.is-toggle a{color:#0a0a0a}html.theme--documenter-dark .hero.is-white .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-white .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-white .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-white .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-white .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-white .tabs.is-toggle li.is-active a:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--documenter-dark .hero.is-white.is-bold{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-white.is-bold .navbar-menu{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}}html.theme--documenter-dark .hero.is-black{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-black strong{color:inherit}html.theme--documenter-dark .hero.is-black .title{color:#fff}html.theme--documenter-dark .hero.is-black .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-black .subtitle a:not(.button),html.theme--documenter-dark .hero.is-black .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-black .navbar-menu{background-color:#0a0a0a}}html.theme--documenter-dark .hero.is-black .navbar-item,html.theme--documenter-dark .hero.is-black .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-black a.navbar-item:hover,html.theme--documenter-dark .hero.is-black a.navbar-item.is-active,html.theme--documenter-dark .hero.is-black .navbar-link:hover,html.theme--documenter-dark .hero.is-black .navbar-link.is-active{background-color:#000;color:#fff}html.theme--documenter-dark .hero.is-black .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-black .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-black .tabs li.is-active a{opacity:1}html.theme--documenter-dark .hero.is-black .tabs.is-boxed a,html.theme--documenter-dark .hero.is-black .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-black .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-black .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-black .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-black .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-black .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-black .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--documenter-dark .hero.is-black.is-bold{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-black.is-bold .navbar-menu{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}}html.theme--documenter-dark .hero.is-light{background-color:#ecf0f1;color:#282f2f}html.theme--documenter-dark .hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-light strong{color:inherit}html.theme--documenter-dark .hero.is-light .title{color:#282f2f}html.theme--documenter-dark .hero.is-light .subtitle{color:rgba(40,47,47,0.9)}html.theme--documenter-dark .hero.is-light .subtitle a:not(.button),html.theme--documenter-dark .hero.is-light .subtitle strong{color:#282f2f}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-light .navbar-menu{background-color:#ecf0f1}}html.theme--documenter-dark .hero.is-light .navbar-item,html.theme--documenter-dark .hero.is-light .navbar-link{color:rgba(40,47,47,0.7)}html.theme--documenter-dark .hero.is-light a.navbar-item:hover,html.theme--documenter-dark .hero.is-light a.navbar-item.is-active,html.theme--documenter-dark .hero.is-light .navbar-link:hover,html.theme--documenter-dark .hero.is-light .navbar-link.is-active{background-color:#dde4e6;color:#282f2f}html.theme--documenter-dark .hero.is-light .tabs a{color:#282f2f;opacity:0.9}html.theme--documenter-dark .hero.is-light .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-light .tabs li.is-active a{opacity:1}html.theme--documenter-dark .hero.is-light .tabs.is-boxed a,html.theme--documenter-dark .hero.is-light .tabs.is-toggle a{color:#282f2f}html.theme--documenter-dark .hero.is-light .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-light .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-light .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-light .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-light .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-light .tabs.is-toggle li.is-active a:hover{background-color:#282f2f;border-color:#282f2f;color:#ecf0f1}html.theme--documenter-dark .hero.is-light.is-bold{background-image:linear-gradient(141deg, #cadfe0 0%, #ecf0f1 71%, #fafbfc 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-light.is-bold .navbar-menu{background-image:linear-gradient(141deg, #cadfe0 0%, #ecf0f1 71%, #fafbfc 100%)}}html.theme--documenter-dark .hero.is-dark,html.theme--documenter-dark .content kbd.hero{background-color:#282f2f;color:#ecf0f1}html.theme--documenter-dark .hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .content kbd.hero a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-dark strong,html.theme--documenter-dark .content kbd.hero strong{color:inherit}html.theme--documenter-dark .hero.is-dark .title,html.theme--documenter-dark .content kbd.hero .title{color:#ecf0f1}html.theme--documenter-dark .hero.is-dark .subtitle,html.theme--documenter-dark .content kbd.hero .subtitle{color:rgba(236,240,241,0.9)}html.theme--documenter-dark .hero.is-dark .subtitle a:not(.button),html.theme--documenter-dark .content kbd.hero .subtitle a:not(.button),html.theme--documenter-dark .hero.is-dark .subtitle strong,html.theme--documenter-dark .content kbd.hero .subtitle strong{color:#ecf0f1}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-dark .navbar-menu,html.theme--documenter-dark .content kbd.hero .navbar-menu{background-color:#282f2f}}html.theme--documenter-dark .hero.is-dark .navbar-item,html.theme--documenter-dark .content kbd.hero .navbar-item,html.theme--documenter-dark .hero.is-dark .navbar-link,html.theme--documenter-dark .content kbd.hero .navbar-link{color:rgba(236,240,241,0.7)}html.theme--documenter-dark .hero.is-dark a.navbar-item:hover,html.theme--documenter-dark .content kbd.hero a.navbar-item:hover,html.theme--documenter-dark .hero.is-dark a.navbar-item.is-active,html.theme--documenter-dark .content kbd.hero a.navbar-item.is-active,html.theme--documenter-dark .hero.is-dark .navbar-link:hover,html.theme--documenter-dark .content kbd.hero .navbar-link:hover,html.theme--documenter-dark .hero.is-dark .navbar-link.is-active,html.theme--documenter-dark .content kbd.hero .navbar-link.is-active{background-color:#1d2122;color:#ecf0f1}html.theme--documenter-dark .hero.is-dark .tabs a,html.theme--documenter-dark .content kbd.hero .tabs a{color:#ecf0f1;opacity:0.9}html.theme--documenter-dark .hero.is-dark .tabs a:hover,html.theme--documenter-dark .content kbd.hero .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-dark .tabs li.is-active a,html.theme--documenter-dark .content kbd.hero .tabs li.is-active a{opacity:1}html.theme--documenter-dark .hero.is-dark .tabs.is-boxed a,html.theme--documenter-dark .content kbd.hero .tabs.is-boxed a,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle a,html.theme--documenter-dark .content kbd.hero .tabs.is-toggle a{color:#ecf0f1}html.theme--documenter-dark .hero.is-dark .tabs.is-boxed a:hover,html.theme--documenter-dark .content kbd.hero .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle a:hover,html.theme--documenter-dark .content kbd.hero .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-dark .tabs.is-boxed li.is-active a,html.theme--documenter-dark .content kbd.hero .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-dark .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle li.is-active a,html.theme--documenter-dark .content kbd.hero .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle li.is-active a:hover{background-color:#ecf0f1;border-color:#ecf0f1;color:#282f2f}html.theme--documenter-dark .hero.is-dark.is-bold,html.theme--documenter-dark .content kbd.hero.is-bold{background-image:linear-gradient(141deg, #0f1615 0%, #282f2f 71%, #313c40 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-dark.is-bold .navbar-menu,html.theme--documenter-dark .content kbd.hero.is-bold .navbar-menu{background-image:linear-gradient(141deg, #0f1615 0%, #282f2f 71%, #313c40 100%)}}html.theme--documenter-dark .hero.is-primary,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink{background-color:#375a7f;color:#fff}html.theme--documenter-dark .hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-primary strong,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink strong{color:inherit}html.theme--documenter-dark .hero.is-primary .title,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .title{color:#fff}html.theme--documenter-dark .hero.is-primary .subtitle,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-primary .subtitle a:not(.button),html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .subtitle a:not(.button),html.theme--documenter-dark .hero.is-primary .subtitle strong,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-primary .navbar-menu,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-menu{background-color:#375a7f}}html.theme--documenter-dark .hero.is-primary .navbar-item,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-item,html.theme--documenter-dark .hero.is-primary .navbar-link,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-primary a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink a.navbar-item:hover,html.theme--documenter-dark .hero.is-primary a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink a.navbar-item.is-active,html.theme--documenter-dark .hero.is-primary .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-link:hover,html.theme--documenter-dark .hero.is-primary .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-link.is-active{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .hero.is-primary .tabs a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-primary .tabs a:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-primary .tabs li.is-active a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs li.is-active a{opacity:1}html.theme--documenter-dark .hero.is-primary .tabs.is-boxed a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-primary .tabs.is-boxed a:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle a:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-primary .tabs.is-boxed li.is-active a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-primary .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle li.is-active a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#375a7f}html.theme--documenter-dark .hero.is-primary.is-bold,html.theme--documenter-dark .docstring>section>a.hero.is-bold.docs-sourcelink{background-image:linear-gradient(141deg, #214b62 0%, #375a7f 71%, #3a5796 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-primary.is-bold .navbar-menu,html.theme--documenter-dark .docstring>section>a.hero.is-bold.docs-sourcelink .navbar-menu{background-image:linear-gradient(141deg, #214b62 0%, #375a7f 71%, #3a5796 100%)}}html.theme--documenter-dark .hero.is-link{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-link strong{color:inherit}html.theme--documenter-dark .hero.is-link .title{color:#fff}html.theme--documenter-dark .hero.is-link .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-link .subtitle a:not(.button),html.theme--documenter-dark .hero.is-link .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-link .navbar-menu{background-color:#1abc9c}}html.theme--documenter-dark .hero.is-link .navbar-item,html.theme--documenter-dark .hero.is-link .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-link a.navbar-item:hover,html.theme--documenter-dark .hero.is-link a.navbar-item.is-active,html.theme--documenter-dark .hero.is-link .navbar-link:hover,html.theme--documenter-dark .hero.is-link .navbar-link.is-active{background-color:#17a689;color:#fff}html.theme--documenter-dark .hero.is-link .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-link .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-link .tabs li.is-active a{opacity:1}html.theme--documenter-dark .hero.is-link .tabs.is-boxed a,html.theme--documenter-dark .hero.is-link .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-link .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-link .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-link .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-link .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-link .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-link .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#1abc9c}html.theme--documenter-dark .hero.is-link.is-bold{background-image:linear-gradient(141deg, #0c9764 0%, #1abc9c 71%, #17d8d2 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-link.is-bold .navbar-menu{background-image:linear-gradient(141deg, #0c9764 0%, #1abc9c 71%, #17d8d2 100%)}}html.theme--documenter-dark .hero.is-info{background-color:#024c7d;color:#fff}html.theme--documenter-dark .hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-info strong{color:inherit}html.theme--documenter-dark .hero.is-info .title{color:#fff}html.theme--documenter-dark .hero.is-info .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-info .subtitle a:not(.button),html.theme--documenter-dark .hero.is-info .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-info .navbar-menu{background-color:#024c7d}}html.theme--documenter-dark .hero.is-info .navbar-item,html.theme--documenter-dark .hero.is-info .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-info a.navbar-item:hover,html.theme--documenter-dark .hero.is-info a.navbar-item.is-active,html.theme--documenter-dark .hero.is-info .navbar-link:hover,html.theme--documenter-dark .hero.is-info .navbar-link.is-active{background-color:#023d64;color:#fff}html.theme--documenter-dark .hero.is-info .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-info .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-info .tabs li.is-active a{opacity:1}html.theme--documenter-dark .hero.is-info .tabs.is-boxed a,html.theme--documenter-dark .hero.is-info .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-info .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-info .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-info .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-info .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-info .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-info .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#024c7d}html.theme--documenter-dark .hero.is-info.is-bold{background-image:linear-gradient(141deg, #003a4c 0%, #024c7d 71%, #004299 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-info.is-bold .navbar-menu{background-image:linear-gradient(141deg, #003a4c 0%, #024c7d 71%, #004299 100%)}}html.theme--documenter-dark .hero.is-success{background-color:#008438;color:#fff}html.theme--documenter-dark .hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-success strong{color:inherit}html.theme--documenter-dark .hero.is-success .title{color:#fff}html.theme--documenter-dark .hero.is-success .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-success .subtitle a:not(.button),html.theme--documenter-dark .hero.is-success .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-success .navbar-menu{background-color:#008438}}html.theme--documenter-dark .hero.is-success .navbar-item,html.theme--documenter-dark .hero.is-success .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-success a.navbar-item:hover,html.theme--documenter-dark .hero.is-success a.navbar-item.is-active,html.theme--documenter-dark .hero.is-success .navbar-link:hover,html.theme--documenter-dark .hero.is-success .navbar-link.is-active{background-color:#006b2d;color:#fff}html.theme--documenter-dark .hero.is-success .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-success .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-success .tabs li.is-active a{opacity:1}html.theme--documenter-dark .hero.is-success .tabs.is-boxed a,html.theme--documenter-dark .hero.is-success .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-success .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-success .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-success .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-success .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-success .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-success .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#008438}html.theme--documenter-dark .hero.is-success.is-bold{background-image:linear-gradient(141deg, #005115 0%, #008438 71%, #009e5d 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-success.is-bold .navbar-menu{background-image:linear-gradient(141deg, #005115 0%, #008438 71%, #009e5d 100%)}}html.theme--documenter-dark .hero.is-warning{background-color:#ad8100;color:#fff}html.theme--documenter-dark .hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-warning strong{color:inherit}html.theme--documenter-dark .hero.is-warning .title{color:#fff}html.theme--documenter-dark .hero.is-warning .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-warning .subtitle a:not(.button),html.theme--documenter-dark .hero.is-warning .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-warning .navbar-menu{background-color:#ad8100}}html.theme--documenter-dark .hero.is-warning .navbar-item,html.theme--documenter-dark .hero.is-warning .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-warning a.navbar-item:hover,html.theme--documenter-dark .hero.is-warning a.navbar-item.is-active,html.theme--documenter-dark .hero.is-warning .navbar-link:hover,html.theme--documenter-dark .hero.is-warning .navbar-link.is-active{background-color:#946e00;color:#fff}html.theme--documenter-dark .hero.is-warning .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-warning .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-warning .tabs li.is-active a{opacity:1}html.theme--documenter-dark .hero.is-warning .tabs.is-boxed a,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-warning .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-warning .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-warning .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#ad8100}html.theme--documenter-dark .hero.is-warning.is-bold{background-image:linear-gradient(141deg, #7a4700 0%, #ad8100 71%, #c7b500 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-warning.is-bold .navbar-menu{background-image:linear-gradient(141deg, #7a4700 0%, #ad8100 71%, #c7b500 100%)}}html.theme--documenter-dark .hero.is-danger{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-danger strong{color:inherit}html.theme--documenter-dark .hero.is-danger .title{color:#fff}html.theme--documenter-dark .hero.is-danger .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-danger .subtitle a:not(.button),html.theme--documenter-dark .hero.is-danger .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-danger .navbar-menu{background-color:#9e1b0d}}html.theme--documenter-dark .hero.is-danger .navbar-item,html.theme--documenter-dark .hero.is-danger .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-danger a.navbar-item:hover,html.theme--documenter-dark .hero.is-danger a.navbar-item.is-active,html.theme--documenter-dark .hero.is-danger .navbar-link:hover,html.theme--documenter-dark .hero.is-danger .navbar-link.is-active{background-color:#86170b;color:#fff}html.theme--documenter-dark .hero.is-danger .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-danger .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-danger .tabs li.is-active a{opacity:1}html.theme--documenter-dark .hero.is-danger .tabs.is-boxed a,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-danger .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-danger .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-danger .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#9e1b0d}html.theme--documenter-dark .hero.is-danger.is-bold{background-image:linear-gradient(141deg, #75030b 0%, #9e1b0d 71%, #ba380a 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-danger.is-bold .navbar-menu{background-image:linear-gradient(141deg, #75030b 0%, #9e1b0d 71%, #ba380a 100%)}}html.theme--documenter-dark .hero.is-small .hero-body,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.hero .hero-body{padding-bottom:1.5rem;padding-top:1.5rem}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero.is-medium .hero-body{padding-bottom:9rem;padding-top:9rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero.is-large .hero-body{padding-bottom:18rem;padding-top:18rem}}html.theme--documenter-dark .hero.is-halfheight .hero-body,html.theme--documenter-dark .hero.is-fullheight .hero-body,html.theme--documenter-dark .hero.is-fullheight-with-navbar .hero-body{align-items:center;display:flex}html.theme--documenter-dark .hero.is-halfheight .hero-body>.container,html.theme--documenter-dark .hero.is-fullheight .hero-body>.container,html.theme--documenter-dark .hero.is-fullheight-with-navbar .hero-body>.container{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .hero.is-halfheight{min-height:50vh}html.theme--documenter-dark .hero.is-fullheight{min-height:100vh}html.theme--documenter-dark .hero-video{overflow:hidden}html.theme--documenter-dark .hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;transform:translate3d(-50%, -50%, 0)}html.theme--documenter-dark .hero-video.is-transparent{opacity:0.3}@media screen and (max-width: 768px){html.theme--documenter-dark .hero-video{display:none}}html.theme--documenter-dark .hero-buttons{margin-top:1.5rem}@media screen and (max-width: 768px){html.theme--documenter-dark .hero-buttons .button{display:flex}html.theme--documenter-dark .hero-buttons .button:not(:last-child){margin-bottom:0.75rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero-buttons{display:flex;justify-content:center}html.theme--documenter-dark .hero-buttons .button:not(:last-child){margin-right:1.5rem}}html.theme--documenter-dark .hero-head,html.theme--documenter-dark .hero-foot{flex-grow:0;flex-shrink:0}html.theme--documenter-dark .hero-body{flex-grow:1;flex-shrink:0;padding:3rem 1.5rem}html.theme--documenter-dark .section{padding:3rem 1.5rem}@media screen and (min-width: 1056px){html.theme--documenter-dark .section.is-medium{padding:9rem 1.5rem}html.theme--documenter-dark .section.is-large{padding:18rem 1.5rem}}html.theme--documenter-dark .footer{background-color:#282f2f;padding:3rem 1.5rem 6rem}html.theme--documenter-dark hr{height:1px}html.theme--documenter-dark h6{text-transform:uppercase;letter-spacing:0.5px}html.theme--documenter-dark .hero{background-color:#343c3d}html.theme--documenter-dark a{transition:all 200ms ease}html.theme--documenter-dark .button{transition:all 200ms ease;border-width:1px;color:#fff}html.theme--documenter-dark .button.is-active,html.theme--documenter-dark .button.is-focused,html.theme--documenter-dark .button:active,html.theme--documenter-dark .button:focus{box-shadow:0 0 0 2px rgba(140,155,157,0.5)}html.theme--documenter-dark .button.is-white.is-hovered,html.theme--documenter-dark .button.is-white:hover{background-color:#fff}html.theme--documenter-dark .button.is-white.is-active,html.theme--documenter-dark .button.is-white.is-focused,html.theme--documenter-dark .button.is-white:active,html.theme--documenter-dark .button.is-white:focus{border-color:#fff;box-shadow:0 0 0 2px rgba(255,255,255,0.5)}html.theme--documenter-dark .button.is-black.is-hovered,html.theme--documenter-dark .button.is-black:hover{background-color:#1d1d1d}html.theme--documenter-dark .button.is-black.is-active,html.theme--documenter-dark .button.is-black.is-focused,html.theme--documenter-dark .button.is-black:active,html.theme--documenter-dark .button.is-black:focus{border-color:#0a0a0a;box-shadow:0 0 0 2px rgba(10,10,10,0.5)}html.theme--documenter-dark .button.is-light.is-hovered,html.theme--documenter-dark .button.is-light:hover{background-color:#fff}html.theme--documenter-dark .button.is-light.is-active,html.theme--documenter-dark .button.is-light.is-focused,html.theme--documenter-dark .button.is-light:active,html.theme--documenter-dark .button.is-light:focus{border-color:#ecf0f1;box-shadow:0 0 0 2px rgba(236,240,241,0.5)}html.theme--documenter-dark .button.is-dark.is-hovered,html.theme--documenter-dark .content kbd.button.is-hovered,html.theme--documenter-dark .button.is-dark:hover,html.theme--documenter-dark .content kbd.button:hover{background-color:#3a4344}html.theme--documenter-dark .button.is-dark.is-active,html.theme--documenter-dark .content kbd.button.is-active,html.theme--documenter-dark .button.is-dark.is-focused,html.theme--documenter-dark .content kbd.button.is-focused,html.theme--documenter-dark .button.is-dark:active,html.theme--documenter-dark .content kbd.button:active,html.theme--documenter-dark .button.is-dark:focus,html.theme--documenter-dark .content kbd.button:focus{border-color:#282f2f;box-shadow:0 0 0 2px rgba(40,47,47,0.5)}html.theme--documenter-dark .button.is-primary.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-hovered.docs-sourcelink,html.theme--documenter-dark .button.is-primary:hover,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:hover{background-color:#436d9a}html.theme--documenter-dark .button.is-primary.is-active,html.theme--documenter-dark .docstring>section>a.button.is-active.docs-sourcelink,html.theme--documenter-dark .button.is-primary.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-focused.docs-sourcelink,html.theme--documenter-dark .button.is-primary:active,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:active,html.theme--documenter-dark .button.is-primary:focus,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:focus{border-color:#375a7f;box-shadow:0 0 0 2px rgba(55,90,127,0.5)}html.theme--documenter-dark .button.is-link.is-hovered,html.theme--documenter-dark .button.is-link:hover{background-color:#1fdeb8}html.theme--documenter-dark .button.is-link.is-active,html.theme--documenter-dark .button.is-link.is-focused,html.theme--documenter-dark .button.is-link:active,html.theme--documenter-dark .button.is-link:focus{border-color:#1abc9c;box-shadow:0 0 0 2px rgba(26,188,156,0.5)}html.theme--documenter-dark .button.is-info.is-hovered,html.theme--documenter-dark .button.is-info:hover{background-color:#0363a3}html.theme--documenter-dark .button.is-info.is-active,html.theme--documenter-dark .button.is-info.is-focused,html.theme--documenter-dark .button.is-info:active,html.theme--documenter-dark .button.is-info:focus{border-color:#024c7d;box-shadow:0 0 0 2px rgba(2,76,125,0.5)}html.theme--documenter-dark .button.is-success.is-hovered,html.theme--documenter-dark .button.is-success:hover{background-color:#00aa48}html.theme--documenter-dark .button.is-success.is-active,html.theme--documenter-dark .button.is-success.is-focused,html.theme--documenter-dark .button.is-success:active,html.theme--documenter-dark .button.is-success:focus{border-color:#008438;box-shadow:0 0 0 2px rgba(0,132,56,0.5)}html.theme--documenter-dark .button.is-warning.is-hovered,html.theme--documenter-dark .button.is-warning:hover{background-color:#d39e00}html.theme--documenter-dark .button.is-warning.is-active,html.theme--documenter-dark .button.is-warning.is-focused,html.theme--documenter-dark .button.is-warning:active,html.theme--documenter-dark .button.is-warning:focus{border-color:#ad8100;box-shadow:0 0 0 2px rgba(173,129,0,0.5)}html.theme--documenter-dark .button.is-danger.is-hovered,html.theme--documenter-dark .button.is-danger:hover{background-color:#c12110}html.theme--documenter-dark .button.is-danger.is-active,html.theme--documenter-dark .button.is-danger.is-focused,html.theme--documenter-dark .button.is-danger:active,html.theme--documenter-dark .button.is-danger:focus{border-color:#9e1b0d;box-shadow:0 0 0 2px rgba(158,27,13,0.5)}html.theme--documenter-dark .label{color:#dbdee0}html.theme--documenter-dark .button,html.theme--documenter-dark .control.has-icons-left .icon,html.theme--documenter-dark .control.has-icons-right .icon,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .select,html.theme--documenter-dark .select select,html.theme--documenter-dark .textarea{height:2.5em}html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark .textarea{transition:all 200ms ease;box-shadow:none;border-width:1px;padding-left:1em;padding-right:1em}html.theme--documenter-dark .select:after,html.theme--documenter-dark .select select{border-width:1px}html.theme--documenter-dark .control.has-addons .button,html.theme--documenter-dark .control.has-addons .input,html.theme--documenter-dark .control.has-addons #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .control.has-addons form.docs-search>input,html.theme--documenter-dark .control.has-addons .select{margin-right:-1px}html.theme--documenter-dark .notification{background-color:#343c3d}html.theme--documenter-dark .card{box-shadow:none;border:1px solid #343c3d;background-color:#282f2f;border-radius:.4em}html.theme--documenter-dark .card .card-image img{border-radius:.4em .4em 0 0}html.theme--documenter-dark .card .card-header{box-shadow:none;background-color:rgba(18,18,18,0.2);border-radius:.4em .4em 0 0}html.theme--documenter-dark .card .card-footer{background-color:rgba(18,18,18,0.2)}html.theme--documenter-dark .card .card-footer,html.theme--documenter-dark .card .card-footer-item{border-width:1px;border-color:#343c3d}html.theme--documenter-dark .notification.is-white a:not(.button){color:#0a0a0a;text-decoration:underline}html.theme--documenter-dark .notification.is-black a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-light a:not(.button){color:#282f2f;text-decoration:underline}html.theme--documenter-dark .notification.is-dark a:not(.button),html.theme--documenter-dark .content kbd.notification a:not(.button){color:#ecf0f1;text-decoration:underline}html.theme--documenter-dark .notification.is-primary a:not(.button),html.theme--documenter-dark .docstring>section>a.notification.docs-sourcelink a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-link a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-info a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-success a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-warning a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-danger a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .tag,html.theme--documenter-dark .content kbd,html.theme--documenter-dark .docstring>section>a.docs-sourcelink{border-radius:.4em}html.theme--documenter-dark .menu-list a{transition:all 300ms ease}html.theme--documenter-dark .modal-card-body{background-color:#282f2f}html.theme--documenter-dark .modal-card-foot,html.theme--documenter-dark .modal-card-head{border-color:#343c3d}html.theme--documenter-dark .message-header{font-weight:700;background-color:#343c3d;color:#fff}html.theme--documenter-dark .message-body{border-width:1px;border-color:#343c3d}html.theme--documenter-dark .navbar{border-radius:.4em}html.theme--documenter-dark .navbar.is-transparent{background:none}html.theme--documenter-dark .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#1abc9c}@media screen and (max-width: 1055px){html.theme--documenter-dark .navbar .navbar-menu{background-color:#375a7f;border-radius:0 0 .4em .4em}}html.theme--documenter-dark .hero .navbar,html.theme--documenter-dark body>.navbar{border-radius:0}html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-previous{border-width:1px}html.theme--documenter-dark .panel-block,html.theme--documenter-dark .panel-heading,html.theme--documenter-dark .panel-tabs{border-width:1px}html.theme--documenter-dark .panel-block:first-child,html.theme--documenter-dark .panel-heading:first-child,html.theme--documenter-dark .panel-tabs:first-child{border-top-width:1px}html.theme--documenter-dark .panel-heading{font-weight:700}html.theme--documenter-dark .panel-tabs a{border-width:1px;margin-bottom:-1px}html.theme--documenter-dark .panel-tabs a.is-active{border-bottom-color:#17a689}html.theme--documenter-dark .panel-block:hover{color:#1dd2af}html.theme--documenter-dark .panel-block:hover .panel-icon{color:#1dd2af}html.theme--documenter-dark .panel-block.is-active .panel-icon{color:#17a689}html.theme--documenter-dark .tabs a{border-bottom-width:1px;margin-bottom:-1px}html.theme--documenter-dark .tabs ul{border-bottom-width:1px}html.theme--documenter-dark .tabs.is-boxed a{border-width:1px}html.theme--documenter-dark .tabs.is-boxed li.is-active a{background-color:#1f2424}html.theme--documenter-dark .tabs.is-toggle li a{border-width:1px;margin-bottom:0}html.theme--documenter-dark .tabs.is-toggle li+li{margin-left:-1px}html.theme--documenter-dark .hero.is-white .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-black .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-light .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-dark .navbar .navbar-dropdown .navbar-item:hover,html.theme--documenter-dark .content kbd.hero .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-primary .navbar .navbar-dropdown .navbar-item:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-link .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-info .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-success .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-warning .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-danger .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark h1 .docs-heading-anchor,html.theme--documenter-dark h1 .docs-heading-anchor:hover,html.theme--documenter-dark h1 .docs-heading-anchor:visited,html.theme--documenter-dark h2 .docs-heading-anchor,html.theme--documenter-dark h2 .docs-heading-anchor:hover,html.theme--documenter-dark h2 .docs-heading-anchor:visited,html.theme--documenter-dark h3 .docs-heading-anchor,html.theme--documenter-dark h3 .docs-heading-anchor:hover,html.theme--documenter-dark h3 .docs-heading-anchor:visited,html.theme--documenter-dark h4 .docs-heading-anchor,html.theme--documenter-dark h4 .docs-heading-anchor:hover,html.theme--documenter-dark h4 .docs-heading-anchor:visited,html.theme--documenter-dark h5 .docs-heading-anchor,html.theme--documenter-dark h5 .docs-heading-anchor:hover,html.theme--documenter-dark h5 .docs-heading-anchor:visited,html.theme--documenter-dark h6 .docs-heading-anchor,html.theme--documenter-dark h6 .docs-heading-anchor:hover,html.theme--documenter-dark h6 .docs-heading-anchor:visited{color:#f2f2f2}html.theme--documenter-dark h1 .docs-heading-anchor-permalink,html.theme--documenter-dark h2 .docs-heading-anchor-permalink,html.theme--documenter-dark h3 .docs-heading-anchor-permalink,html.theme--documenter-dark h4 .docs-heading-anchor-permalink,html.theme--documenter-dark h5 .docs-heading-anchor-permalink,html.theme--documenter-dark h6 .docs-heading-anchor-permalink{visibility:hidden;vertical-align:middle;margin-left:0.5em;font-size:0.7rem}html.theme--documenter-dark h1 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h2 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h3 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h4 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h5 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h6 .docs-heading-anchor-permalink::before{font-family:"Font Awesome 5 Free";font-weight:900;content:"\f0c1"}html.theme--documenter-dark h1:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h2:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h3:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h4:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h5:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h6:hover .docs-heading-anchor-permalink{visibility:visible}html.theme--documenter-dark .docs-light-only{display:none !important}html.theme--documenter-dark pre{position:relative;overflow:hidden}html.theme--documenter-dark pre code,html.theme--documenter-dark pre code.hljs{padding:0 .75rem !important;overflow:auto;display:block}html.theme--documenter-dark pre code:first-of-type,html.theme--documenter-dark pre code.hljs:first-of-type{padding-top:0.5rem !important}html.theme--documenter-dark pre code:last-of-type,html.theme--documenter-dark pre code.hljs:last-of-type{padding-bottom:0.5rem !important}html.theme--documenter-dark pre .copy-button{opacity:0.2;transition:opacity 0.2s;position:absolute;right:0em;top:0em;padding:0.5em;width:2.5em;height:2.5em;background:transparent;border:none;font-family:"Font Awesome 5 Free";color:#fff;cursor:pointer;text-align:center}html.theme--documenter-dark pre .copy-button:focus,html.theme--documenter-dark pre .copy-button:hover{opacity:1;background:rgba(255,255,255,0.1);color:#1abc9c}html.theme--documenter-dark pre .copy-button.success{color:#259a12;opacity:1}html.theme--documenter-dark pre .copy-button.error{color:#cb3c33;opacity:1}html.theme--documenter-dark pre:hover .copy-button{opacity:1}html.theme--documenter-dark .admonition{background-color:#282f2f;border-style:solid;border-width:1px;border-color:#5e6d6f;border-radius:.4em;font-size:15px}html.theme--documenter-dark .admonition strong{color:currentColor}html.theme--documenter-dark .admonition.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.admonition{font-size:.85em}html.theme--documenter-dark .admonition.is-medium{font-size:1.25rem}html.theme--documenter-dark .admonition.is-large{font-size:1.5rem}html.theme--documenter-dark .admonition.is-default{background-color:#282f2f;border-color:#5e6d6f}html.theme--documenter-dark .admonition.is-default>.admonition-header{background-color:#5e6d6f;color:#fff}html.theme--documenter-dark .admonition.is-default>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-info{background-color:#282f2f;border-color:#024c7d}html.theme--documenter-dark .admonition.is-info>.admonition-header{background-color:#024c7d;color:#fff}html.theme--documenter-dark .admonition.is-info>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-success{background-color:#282f2f;border-color:#008438}html.theme--documenter-dark .admonition.is-success>.admonition-header{background-color:#008438;color:#fff}html.theme--documenter-dark .admonition.is-success>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-warning{background-color:#282f2f;border-color:#ad8100}html.theme--documenter-dark .admonition.is-warning>.admonition-header{background-color:#ad8100;color:#fff}html.theme--documenter-dark .admonition.is-warning>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-danger{background-color:#282f2f;border-color:#9e1b0d}html.theme--documenter-dark .admonition.is-danger>.admonition-header{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .admonition.is-danger>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-compat{background-color:#282f2f;border-color:#137886}html.theme--documenter-dark .admonition.is-compat>.admonition-header{background-color:#137886;color:#fff}html.theme--documenter-dark .admonition.is-compat>.admonition-body{color:#fff}html.theme--documenter-dark .admonition-header{color:#fff;background-color:#5e6d6f;align-items:center;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.5rem .75rem;position:relative}html.theme--documenter-dark .admonition-header:before{font-family:"Font Awesome 5 Free";font-weight:900;margin-right:.75rem;content:"\f06a"}html.theme--documenter-dark .admonition-body{color:#fff;padding:0.5rem .75rem}html.theme--documenter-dark .admonition-body pre{background-color:#282f2f}html.theme--documenter-dark .admonition-body code{background-color:rgba(255,255,255,0.05)}html.theme--documenter-dark .docstring{margin-bottom:1em;background-color:rgba(0,0,0,0);border:1px solid #5e6d6f;box-shadow:none;max-width:100%}html.theme--documenter-dark .docstring>header{display:flex;flex-grow:1;align-items:stretch;padding:0.5rem .75rem;background-color:#282f2f;box-shadow:0 1px 2px rgba(10,10,10,0.1);box-shadow:none;border-bottom:1px solid #5e6d6f}html.theme--documenter-dark .docstring>header code{background-color:transparent}html.theme--documenter-dark .docstring>header .docstring-binding{margin-right:0.3em}html.theme--documenter-dark .docstring>header .docstring-category{margin-left:0.3em}html.theme--documenter-dark .docstring>section{position:relative;padding:.75rem .75rem;border-bottom:1px solid #5e6d6f}html.theme--documenter-dark .docstring>section:last-child{border-bottom:none}html.theme--documenter-dark .docstring>section>a.docs-sourcelink{transition:opacity 0.3s;opacity:0;position:absolute;right:.375rem;bottom:.375rem}html.theme--documenter-dark .docstring>section>a.docs-sourcelink:focus{opacity:1 !important}html.theme--documenter-dark .docstring:hover>section>a.docs-sourcelink{opacity:0.2}html.theme--documenter-dark .docstring:focus-within>section>a.docs-sourcelink{opacity:0.2}html.theme--documenter-dark .docstring>section:hover a.docs-sourcelink{opacity:1}html.theme--documenter-dark .documenter-example-output{background-color:#1f2424}html.theme--documenter-dark .outdated-warning-overlay{position:fixed;top:0;left:0;right:0;box-shadow:0 0 10px rgba(0,0,0,0.3);z-index:999;background-color:#282f2f;color:#fff;border-bottom:3px solid #9e1b0d;padding:10px 35px;text-align:center;font-size:15px}html.theme--documenter-dark .outdated-warning-overlay .outdated-warning-closer{position:absolute;top:calc(50% - 10px);right:18px;cursor:pointer;width:12px}html.theme--documenter-dark .outdated-warning-overlay a{color:#1abc9c}html.theme--documenter-dark .outdated-warning-overlay a:hover{color:#1dd2af}html.theme--documenter-dark .content pre{border:1px solid #5e6d6f}html.theme--documenter-dark .content code{font-weight:inherit}html.theme--documenter-dark .content a code{color:#1abc9c}html.theme--documenter-dark .content h1 code,html.theme--documenter-dark .content h2 code,html.theme--documenter-dark .content h3 code,html.theme--documenter-dark .content h4 code,html.theme--documenter-dark .content h5 code,html.theme--documenter-dark .content h6 code{color:#f2f2f2}html.theme--documenter-dark .content table{display:block;width:initial;max-width:100%;overflow-x:auto}html.theme--documenter-dark .content blockquote>ul:first-child,html.theme--documenter-dark .content blockquote>ol:first-child,html.theme--documenter-dark .content .admonition-body>ul:first-child,html.theme--documenter-dark .content .admonition-body>ol:first-child{margin-top:0}html.theme--documenter-dark pre,html.theme--documenter-dark code{font-variant-ligatures:no-contextual}html.theme--documenter-dark .breadcrumb a.is-disabled{cursor:default;pointer-events:none}html.theme--documenter-dark .breadcrumb a.is-disabled,html.theme--documenter-dark .breadcrumb a.is-disabled:hover{color:#f2f2f2}html.theme--documenter-dark .hljs{background:initial !important}html.theme--documenter-dark .katex .katex-mathml{top:0;right:0}html.theme--documenter-dark .katex-display,html.theme--documenter-dark mjx-container,html.theme--documenter-dark .MathJax_Display{margin:0.5em 0 !important}html.theme--documenter-dark html{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto}html.theme--documenter-dark li.no-marker{list-style:none}html.theme--documenter-dark #documenter .docs-main>article{overflow-wrap:break-word}html.theme--documenter-dark #documenter .docs-main>article .math-container{overflow-x:auto;overflow-y:hidden}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-main{max-width:52rem;margin-left:20rem;padding-right:1rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main{width:100%}html.theme--documenter-dark #documenter .docs-main>article{max-width:52rem;margin-left:auto;margin-right:auto;margin-bottom:1rem;padding:0 1rem}html.theme--documenter-dark #documenter .docs-main>header,html.theme--documenter-dark #documenter .docs-main>nav{max-width:100%;width:100%;margin:0}}html.theme--documenter-dark #documenter .docs-main header.docs-navbar{background-color:#1f2424;border-bottom:1px solid #5e6d6f;z-index:2;min-height:4rem;margin-bottom:1rem;display:flex}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .breadcrumb{flex-grow:1}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right{display:flex;white-space:nowrap}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-icon,html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-label,html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-sidebar-button{display:inline-block}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-label{padding:0;margin-left:0.3em}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-settings-button{margin:auto 0 auto 1rem}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-sidebar-button{font-size:1.5rem;margin:auto 0 auto 1rem}html.theme--documenter-dark #documenter .docs-main header.docs-navbar>*{margin:auto 0}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main header.docs-navbar{position:sticky;top:0;padding:0 1rem;transition-property:top, box-shadow;-webkit-transition-property:top, box-shadow;transition-duration:0.3s;-webkit-transition-duration:0.3s}html.theme--documenter-dark #documenter .docs-main header.docs-navbar.headroom--not-top{box-shadow:.2rem 0rem .4rem #171717;transition-duration:0.7s;-webkit-transition-duration:0.7s}html.theme--documenter-dark #documenter .docs-main header.docs-navbar.headroom--unpinned.headroom--not-top.headroom--not-bottom{top:-4.5rem;transition-duration:0.7s;-webkit-transition-duration:0.7s}}html.theme--documenter-dark #documenter .docs-main section.footnotes{border-top:1px solid #5e6d6f}html.theme--documenter-dark #documenter .docs-main section.footnotes li .tag:first-child,html.theme--documenter-dark #documenter .docs-main section.footnotes li .docstring>section>a.docs-sourcelink:first-child,html.theme--documenter-dark #documenter .docs-main section.footnotes li .content kbd:first-child,html.theme--documenter-dark .content #documenter .docs-main section.footnotes li kbd:first-child{margin-right:1em;margin-bottom:0.4em}html.theme--documenter-dark #documenter .docs-main .docs-footer{display:flex;flex-wrap:wrap;margin-left:0;margin-right:0;border-top:1px solid #5e6d6f;padding-top:1rem;padding-bottom:1rem}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main .docs-footer{padding-left:1rem;padding-right:1rem}}html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-nextpage,html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-prevpage{flex-grow:1}html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-nextpage{text-align:right}html.theme--documenter-dark #documenter .docs-main .docs-footer .flexbox-break{flex-basis:100%;height:0}html.theme--documenter-dark #documenter .docs-main .docs-footer .footer-message{font-size:0.8em;margin:0.5em auto 0 auto;text-align:center}html.theme--documenter-dark #documenter .docs-sidebar{display:flex;flex-direction:column;color:#fff;background-color:#282f2f;border-right:1px solid #5e6d6f;padding:0;flex:0 0 18rem;z-index:5;font-size:15px;position:fixed;left:-18rem;width:18rem;height:100%;transition:left 0.3s}html.theme--documenter-dark #documenter .docs-sidebar.visible{left:0;box-shadow:.4rem 0rem .8rem #171717}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-sidebar.visible{box-shadow:none}}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-sidebar{left:0;top:0}}html.theme--documenter-dark #documenter .docs-sidebar .docs-logo{margin-top:1rem;padding:0 1rem}html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img{max-height:6rem;margin:auto}html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name{flex-shrink:0;font-size:1.5rem;font-weight:700;text-align:center;white-space:nowrap;overflow:hidden;padding:0.5rem 0}html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name .docs-autofit{max-width:16.2rem}html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name a,html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name a:hover{color:#fff}html.theme--documenter-dark #documenter .docs-sidebar .docs-version-selector{border-top:1px solid #5e6d6f;display:none;padding:0.5rem}html.theme--documenter-dark #documenter .docs-sidebar .docs-version-selector.visible{display:flex}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu{flex-grow:1;user-select:none;border-top:1px solid #5e6d6f;padding-bottom:1.5rem}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu>li>.tocitem{font-weight:bold}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu>li li{font-size:14.25px;margin-left:1em;border-left:1px solid #5e6d6f}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input.collapse-toggle{display:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.collapsed{display:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input:checked~ul.collapsed{display:block}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem{display:flex}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-label{flex-grow:2}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-size:11.25px;margin-left:1rem;margin-top:auto;margin-bottom:auto}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron::before{font-family:"Font Awesome 5 Free";font-weight:900;content:"\f054"}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input:checked~label.tocitem .docs-chevron::before{content:"\f078"}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem{display:block;padding:0.5rem 0.5rem}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem,html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem:hover{color:#fff;background:#282f2f}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu a.tocitem:hover,html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem:hover{color:#fff;background-color:#32393a}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active{border-top:1px solid #5e6d6f;border-bottom:1px solid #5e6d6f;background-color:#1f2424}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem,html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem:hover{background-color:#1f2424;color:#fff}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active ul.internal .tocitem:hover{background-color:#32393a;color:#fff}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu>li.is-active:first-child{border-top:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal{margin:0 0.5rem 0.5rem;border-top:1px solid #5e6d6f}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal li{font-size:12.75px;border-left:none;margin-left:0;margin-top:0.5rem}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem{width:100%;padding:0}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem::before{content:"⚬";margin-right:0.4em}html.theme--documenter-dark #documenter .docs-sidebar form.docs-search{margin:auto;margin-top:0.5rem;margin-bottom:0.5rem}html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{width:14.4rem}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar{width:.3rem;background:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#3b4445}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb:hover{background:#4e5a5c}}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-sidebar{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar{width:.3rem;background:none}html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#3b4445}html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar-thumb:hover{background:#4e5a5c}}html.theme--documenter-dark #documenter .docs-main #documenter-search-info{margin-bottom:1rem}html.theme--documenter-dark #documenter .docs-main #documenter-search-results{list-style-type:circle;list-style-position:outside}html.theme--documenter-dark #documenter .docs-main #documenter-search-results li{margin-left:2rem}html.theme--documenter-dark #documenter .docs-main #documenter-search-results .docs-highlight{background-color:yellow}html.theme--documenter-dark{background-color:#1f2424;font-size:16px;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--documenter-dark .ansi span.sgr1{font-weight:bolder}html.theme--documenter-dark .ansi span.sgr2{font-weight:lighter}html.theme--documenter-dark .ansi span.sgr3{font-style:italic}html.theme--documenter-dark .ansi span.sgr4{text-decoration:underline}html.theme--documenter-dark .ansi span.sgr7{color:#1f2424;background-color:#fff}html.theme--documenter-dark .ansi span.sgr8{color:transparent}html.theme--documenter-dark .ansi span.sgr8 span{color:transparent}html.theme--documenter-dark .ansi span.sgr9{text-decoration:line-through}html.theme--documenter-dark .ansi span.sgr30{color:#242424}html.theme--documenter-dark .ansi span.sgr31{color:#f6705f}html.theme--documenter-dark .ansi span.sgr32{color:#4fb43a}html.theme--documenter-dark .ansi span.sgr33{color:#f4c72f}html.theme--documenter-dark .ansi span.sgr34{color:#7587f0}html.theme--documenter-dark .ansi span.sgr35{color:#bc89d3}html.theme--documenter-dark .ansi span.sgr36{color:#49b6ca}html.theme--documenter-dark .ansi span.sgr37{color:#b3bdbe}html.theme--documenter-dark .ansi span.sgr40{background-color:#242424}html.theme--documenter-dark .ansi span.sgr41{background-color:#f6705f}html.theme--documenter-dark .ansi span.sgr42{background-color:#4fb43a}html.theme--documenter-dark .ansi span.sgr43{background-color:#f4c72f}html.theme--documenter-dark .ansi span.sgr44{background-color:#7587f0}html.theme--documenter-dark .ansi span.sgr45{background-color:#bc89d3}html.theme--documenter-dark .ansi span.sgr46{background-color:#49b6ca}html.theme--documenter-dark .ansi span.sgr47{background-color:#b3bdbe}html.theme--documenter-dark .ansi span.sgr90{color:#92a0a2}html.theme--documenter-dark .ansi span.sgr91{color:#ff8674}html.theme--documenter-dark .ansi span.sgr92{color:#79d462}html.theme--documenter-dark .ansi span.sgr93{color:#ffe76b}html.theme--documenter-dark .ansi span.sgr94{color:#8a98ff}html.theme--documenter-dark .ansi span.sgr95{color:#d2a4e6}html.theme--documenter-dark .ansi span.sgr96{color:#6bc8db}html.theme--documenter-dark .ansi span.sgr97{color:#ecf0f1}html.theme--documenter-dark .ansi span.sgr100{background-color:#92a0a2}html.theme--documenter-dark .ansi span.sgr101{background-color:#ff8674}html.theme--documenter-dark .ansi span.sgr102{background-color:#79d462}html.theme--documenter-dark .ansi span.sgr103{background-color:#ffe76b}html.theme--documenter-dark .ansi span.sgr104{background-color:#8a98ff}html.theme--documenter-dark .ansi span.sgr105{background-color:#d2a4e6}html.theme--documenter-dark .ansi span.sgr106{background-color:#6bc8db}html.theme--documenter-dark .ansi span.sgr107{background-color:#ecf0f1}html.theme--documenter-dark code.language-julia-repl>span.hljs-meta{color:#4fb43a;font-weight:bolder}html.theme--documenter-dark .hljs{background:#2b2b2b;color:#f8f8f2}html.theme--documenter-dark .hljs-comment,html.theme--documenter-dark .hljs-quote{color:#d4d0ab}html.theme--documenter-dark .hljs-variable,html.theme--documenter-dark .hljs-template-variable,html.theme--documenter-dark .hljs-tag,html.theme--documenter-dark .hljs-name,html.theme--documenter-dark .hljs-selector-id,html.theme--documenter-dark .hljs-selector-class,html.theme--documenter-dark .hljs-regexp,html.theme--documenter-dark .hljs-deletion{color:#ffa07a}html.theme--documenter-dark .hljs-number,html.theme--documenter-dark .hljs-built_in,html.theme--documenter-dark .hljs-literal,html.theme--documenter-dark .hljs-type,html.theme--documenter-dark .hljs-params,html.theme--documenter-dark .hljs-meta,html.theme--documenter-dark .hljs-link{color:#f5ab35}html.theme--documenter-dark .hljs-attribute{color:#ffd700}html.theme--documenter-dark .hljs-string,html.theme--documenter-dark .hljs-symbol,html.theme--documenter-dark .hljs-bullet,html.theme--documenter-dark .hljs-addition{color:#abe338}html.theme--documenter-dark .hljs-title,html.theme--documenter-dark .hljs-section{color:#00e0e0}html.theme--documenter-dark .hljs-keyword,html.theme--documenter-dark .hljs-selector-tag{color:#dcc6e0}html.theme--documenter-dark .hljs-emphasis{font-style:italic}html.theme--documenter-dark .hljs-strong{font-weight:bold}@media screen and (-ms-high-contrast: active){html.theme--documenter-dark .hljs-addition,html.theme--documenter-dark .hljs-attribute,html.theme--documenter-dark .hljs-built_in,html.theme--documenter-dark .hljs-bullet,html.theme--documenter-dark .hljs-comment,html.theme--documenter-dark .hljs-link,html.theme--documenter-dark .hljs-literal,html.theme--documenter-dark .hljs-meta,html.theme--documenter-dark .hljs-number,html.theme--documenter-dark .hljs-params,html.theme--documenter-dark .hljs-string,html.theme--documenter-dark .hljs-symbol,html.theme--documenter-dark .hljs-type,html.theme--documenter-dark .hljs-quote{color:highlight}html.theme--documenter-dark .hljs-keyword,html.theme--documenter-dark .hljs-selector-tag{font-weight:bold}}html.theme--documenter-dark .hljs-subst{color:#f8f8f2} +*/}html.theme--documenter-dark html{background-color:#1f2424;font-size:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--documenter-dark article,html.theme--documenter-dark aside,html.theme--documenter-dark figure,html.theme--documenter-dark footer,html.theme--documenter-dark header,html.theme--documenter-dark hgroup,html.theme--documenter-dark section{display:block}html.theme--documenter-dark body,html.theme--documenter-dark button,html.theme--documenter-dark input,html.theme--documenter-dark optgroup,html.theme--documenter-dark select,html.theme--documenter-dark textarea{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif}html.theme--documenter-dark code,html.theme--documenter-dark pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}html.theme--documenter-dark body{color:#fff;font-size:1em;font-weight:400;line-height:1.5}html.theme--documenter-dark a{color:#1abc9c;cursor:pointer;text-decoration:none}html.theme--documenter-dark a strong{color:currentColor}html.theme--documenter-dark a:hover{color:#1dd2af}html.theme--documenter-dark code{background-color:rgba(255,255,255,0.05);color:#ececec;font-size:.875em;font-weight:normal;padding:.1em}html.theme--documenter-dark hr{background-color:#282f2f;border:none;display:block;height:2px;margin:1.5rem 0}html.theme--documenter-dark img{height:auto;max-width:100%}html.theme--documenter-dark input[type="checkbox"],html.theme--documenter-dark input[type="radio"]{vertical-align:baseline}html.theme--documenter-dark small{font-size:.875em}html.theme--documenter-dark span{font-style:inherit;font-weight:inherit}html.theme--documenter-dark strong{color:#f2f2f2;font-weight:700}html.theme--documenter-dark fieldset{border:none}html.theme--documenter-dark pre{-webkit-overflow-scrolling:touch;background-color:#282f2f;color:#fff;font-size:.875em;overflow-x:auto;padding:1.25rem 1.5rem;white-space:pre;word-wrap:normal}html.theme--documenter-dark pre code{background-color:transparent;color:currentColor;font-size:1em;padding:0}html.theme--documenter-dark table td,html.theme--documenter-dark table th{vertical-align:top}html.theme--documenter-dark table td:not([align]),html.theme--documenter-dark table th:not([align]){text-align:inherit}html.theme--documenter-dark table th{color:#f2f2f2}html.theme--documenter-dark .box{background-color:#343c3d;border-radius:8px;box-shadow:none;color:#fff;display:block;padding:1.25rem}html.theme--documenter-dark a.box:hover,html.theme--documenter-dark a.box:focus{box-shadow:0 0.5em 1em -0.125em rgba(10,10,10,0.1),0 0 0 1px #1abc9c}html.theme--documenter-dark a.box:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2),0 0 0 1px #1abc9c}html.theme--documenter-dark .button{background-color:#282f2f;border-color:#4c5759;border-width:1px;color:#375a7f;cursor:pointer;justify-content:center;padding-bottom:calc(0.5em - 1px);padding-left:1em;padding-right:1em;padding-top:calc(0.5em - 1px);text-align:center;white-space:nowrap}html.theme--documenter-dark .button strong{color:inherit}html.theme--documenter-dark .button .icon,html.theme--documenter-dark .button .icon.is-small,html.theme--documenter-dark .button #documenter .docs-sidebar form.docs-search>input.icon,html.theme--documenter-dark #documenter .docs-sidebar .button form.docs-search>input.icon,html.theme--documenter-dark .button .icon.is-medium,html.theme--documenter-dark .button .icon.is-large{height:1.5em;width:1.5em}html.theme--documenter-dark .button .icon:first-child:not(:last-child){margin-left:calc(-0.5em - 1px);margin-right:.25em}html.theme--documenter-dark .button .icon:last-child:not(:first-child){margin-left:.25em;margin-right:calc(-0.5em - 1px)}html.theme--documenter-dark .button .icon:first-child:last-child{margin-left:calc(-0.5em - 1px);margin-right:calc(-0.5em - 1px)}html.theme--documenter-dark .button:hover,html.theme--documenter-dark .button.is-hovered{border-color:#8c9b9d;color:#f2f2f2}html.theme--documenter-dark .button:focus,html.theme--documenter-dark .button.is-focused{border-color:#8c9b9d;color:#17a689}html.theme--documenter-dark .button:focus:not(:active),html.theme--documenter-dark .button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .button:active,html.theme--documenter-dark .button.is-active{border-color:#343c3d;color:#f2f2f2}html.theme--documenter-dark .button.is-text{background-color:transparent;border-color:transparent;color:#fff;text-decoration:underline}html.theme--documenter-dark .button.is-text:hover,html.theme--documenter-dark .button.is-text.is-hovered,html.theme--documenter-dark .button.is-text:focus,html.theme--documenter-dark .button.is-text.is-focused{background-color:#282f2f;color:#f2f2f2}html.theme--documenter-dark .button.is-text:active,html.theme--documenter-dark .button.is-text.is-active{background-color:#1d2122;color:#f2f2f2}html.theme--documenter-dark .button.is-text[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-text{background-color:transparent;border-color:transparent;box-shadow:none}html.theme--documenter-dark .button.is-ghost{background:none;border-color:rgba(0,0,0,0);color:#1abc9c;text-decoration:none}html.theme--documenter-dark .button.is-ghost:hover,html.theme--documenter-dark .button.is-ghost.is-hovered{color:#1abc9c;text-decoration:underline}html.theme--documenter-dark .button.is-white{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white:hover,html.theme--documenter-dark .button.is-white.is-hovered{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white:focus,html.theme--documenter-dark .button.is-white.is-focused{border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white:focus:not(:active),html.theme--documenter-dark .button.is-white.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--documenter-dark .button.is-white:active,html.theme--documenter-dark .button.is-white.is-active{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .button.is-white[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white{background-color:#fff;border-color:#fff;box-shadow:none}html.theme--documenter-dark .button.is-white.is-inverted{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .button.is-white.is-inverted:hover,html.theme--documenter-dark .button.is-white.is-inverted.is-hovered{background-color:#000}html.theme--documenter-dark .button.is-white.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white.is-inverted{background-color:#0a0a0a;border-color:transparent;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-white.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-white.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-white.is-outlined:hover,html.theme--documenter-dark .button.is-white.is-outlined.is-hovered,html.theme--documenter-dark .button.is-white.is-outlined:focus,html.theme--documenter-dark .button.is-white.is-outlined.is-focused{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--documenter-dark .button.is-white.is-outlined.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-white.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-white.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-white.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-white.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-white.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-focused{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-white.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-white.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--documenter-dark .button.is-black{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black:hover,html.theme--documenter-dark .button.is-black.is-hovered{background-color:#040404;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black:focus,html.theme--documenter-dark .button.is-black.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black:focus:not(:active),html.theme--documenter-dark .button.is-black.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--documenter-dark .button.is-black:active,html.theme--documenter-dark .button.is-black.is-active{background-color:#000;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-black[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black{background-color:#0a0a0a;border-color:#0a0a0a;box-shadow:none}html.theme--documenter-dark .button.is-black.is-inverted{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-inverted:hover,html.theme--documenter-dark .button.is-black.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-black.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-outlined:hover,html.theme--documenter-dark .button.is-black.is-outlined.is-hovered,html.theme--documenter-dark .button.is-black.is-outlined:focus,html.theme--documenter-dark .button.is-black.is-outlined.is-focused{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--documenter-dark .button.is-black.is-outlined.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-black.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-black.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-black.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-black.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-black.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-focused{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-black.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}html.theme--documenter-dark .button.is-black.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-light{background-color:#ecf0f1;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light:hover,html.theme--documenter-dark .button.is-light.is-hovered{background-color:#e5eaec;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light:focus,html.theme--documenter-dark .button.is-light.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light:focus:not(:active),html.theme--documenter-dark .button.is-light.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(236,240,241,0.25)}html.theme--documenter-dark .button.is-light:active,html.theme--documenter-dark .button.is-light.is-active{background-color:#dde4e6;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light{background-color:#ecf0f1;border-color:#ecf0f1;box-shadow:none}html.theme--documenter-dark .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-inverted:hover,html.theme--documenter-dark .button.is-light.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--documenter-dark .button.is-light.is-outlined{background-color:transparent;border-color:#ecf0f1;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-outlined:hover,html.theme--documenter-dark .button.is-light.is-outlined.is-hovered,html.theme--documenter-dark .button.is-light.is-outlined:focus,html.theme--documenter-dark .button.is-light.is-outlined.is-focused{background-color:#ecf0f1;border-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light.is-outlined.is-loading::after{border-color:transparent transparent #ecf0f1 #ecf0f1 !important}html.theme--documenter-dark .button.is-light.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-light.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-light.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-light.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}html.theme--documenter-dark .button.is-light.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light.is-outlined{background-color:transparent;border-color:#ecf0f1;box-shadow:none;color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#ecf0f1}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-light.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #ecf0f1 #ecf0f1 !important}html.theme--documenter-dark .button.is-light.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .button.is-dark,html.theme--documenter-dark .content kbd.button{background-color:#282f2f;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark:hover,html.theme--documenter-dark .content kbd.button:hover,html.theme--documenter-dark .button.is-dark.is-hovered,html.theme--documenter-dark .content kbd.button.is-hovered{background-color:#232829;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark:focus,html.theme--documenter-dark .content kbd.button:focus,html.theme--documenter-dark .button.is-dark.is-focused,html.theme--documenter-dark .content kbd.button.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark:focus:not(:active),html.theme--documenter-dark .content kbd.button:focus:not(:active),html.theme--documenter-dark .button.is-dark.is-focused:not(:active),html.theme--documenter-dark .content kbd.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(40,47,47,0.25)}html.theme--documenter-dark .button.is-dark:active,html.theme--documenter-dark .content kbd.button:active,html.theme--documenter-dark .button.is-dark.is-active,html.theme--documenter-dark .content kbd.button.is-active{background-color:#1d2122;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-dark[disabled],html.theme--documenter-dark .content kbd.button[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark,fieldset[disabled] html.theme--documenter-dark .content kbd.button{background-color:#282f2f;border-color:#282f2f;box-shadow:none}html.theme--documenter-dark .button.is-dark.is-inverted,html.theme--documenter-dark .content kbd.button.is-inverted{background-color:#fff;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-inverted:hover,html.theme--documenter-dark .content kbd.button.is-inverted:hover,html.theme--documenter-dark .button.is-dark.is-inverted.is-hovered,html.theme--documenter-dark .content kbd.button.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-dark.is-inverted[disabled],html.theme--documenter-dark .content kbd.button.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-inverted,fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-loading::after,html.theme--documenter-dark .content kbd.button.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-dark.is-outlined,html.theme--documenter-dark .content kbd.button.is-outlined{background-color:transparent;border-color:#282f2f;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-outlined:hover,html.theme--documenter-dark .content kbd.button.is-outlined:hover,html.theme--documenter-dark .button.is-dark.is-outlined.is-hovered,html.theme--documenter-dark .content kbd.button.is-outlined.is-hovered,html.theme--documenter-dark .button.is-dark.is-outlined:focus,html.theme--documenter-dark .content kbd.button.is-outlined:focus,html.theme--documenter-dark .button.is-dark.is-outlined.is-focused,html.theme--documenter-dark .content kbd.button.is-outlined.is-focused{background-color:#282f2f;border-color:#282f2f;color:#fff}html.theme--documenter-dark .button.is-dark.is-outlined.is-loading::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading::after{border-color:transparent transparent #282f2f #282f2f !important}html.theme--documenter-dark .button.is-dark.is-outlined.is-loading:hover::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-dark.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-dark.is-outlined.is-loading:focus::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-dark.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .content kbd.button.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-dark.is-outlined[disabled],html.theme--documenter-dark .content kbd.button.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-outlined,fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-outlined{background-color:transparent;border-color:#282f2f;box-shadow:none;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined:hover,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined:focus,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-focused,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-focused{background-color:#fff;color:#282f2f}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #282f2f #282f2f !important}html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined[disabled],html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-dark.is-inverted.is-outlined,fieldset[disabled] html.theme--documenter-dark .content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-primary,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink{background-color:#375a7f;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary:hover,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-hovered.docs-sourcelink{background-color:#335476;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary:focus,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:focus,html.theme--documenter-dark .button.is-primary.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-focused.docs-sourcelink{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary:focus:not(:active),html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:focus:not(:active),html.theme--documenter-dark .button.is-primary.is-focused:not(:active),html.theme--documenter-dark .docstring>section>a.button.is-focused.docs-sourcelink:not(:active){box-shadow:0 0 0 0.125em rgba(55,90,127,0.25)}html.theme--documenter-dark .button.is-primary:active,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:active,html.theme--documenter-dark .button.is-primary.is-active,html.theme--documenter-dark .docstring>section>a.button.is-active.docs-sourcelink{background-color:#2f4d6d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-primary[disabled],html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink{background-color:#375a7f;border-color:#375a7f;box-shadow:none}html.theme--documenter-dark .button.is-primary.is-inverted,html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-inverted:hover,html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-inverted.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-hovered.docs-sourcelink{background-color:#f2f2f2}html.theme--documenter-dark .button.is-primary.is-inverted[disabled],html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-inverted,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;border-color:transparent;box-shadow:none;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-loading::after,html.theme--documenter-dark .docstring>section>a.button.is-loading.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-primary.is-outlined,html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#375a7f;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-outlined:hover,html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-outlined.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-hovered.docs-sourcelink,html.theme--documenter-dark .button.is-primary.is-outlined:focus,html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink:focus,html.theme--documenter-dark .button.is-primary.is-outlined.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-focused.docs-sourcelink{background-color:#375a7f;border-color:#375a7f;color:#fff}html.theme--documenter-dark .button.is-primary.is-outlined.is-loading::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink::after{border-color:transparent transparent #375a7f #375a7f !important}html.theme--documenter-dark .button.is-primary.is-outlined.is-loading:hover::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--documenter-dark .button.is-primary.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--documenter-dark .button.is-primary.is-outlined.is-loading:focus::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--documenter-dark .button.is-primary.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .docstring>section>a.button.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-primary.is-outlined[disabled],html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-outlined,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#375a7f;box-shadow:none;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined:hover,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-hovered.docs-sourcelink,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined:focus,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:focus,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-focused.docs-sourcelink{background-color:#fff;color:#375a7f}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:hover::after,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-hovered.docs-sourcelink::after,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:focus::after,html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after,html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #375a7f #375a7f !important}html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined[disabled],html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-primary.is-inverted.is-outlined,fieldset[disabled] html.theme--documenter-dark .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-primary.is-light,html.theme--documenter-dark .docstring>section>a.button.is-light.docs-sourcelink{background-color:#f1f5f9;color:#4d7eb2}html.theme--documenter-dark .button.is-primary.is-light:hover,html.theme--documenter-dark .docstring>section>a.button.is-light.docs-sourcelink:hover,html.theme--documenter-dark .button.is-primary.is-light.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-light.is-hovered.docs-sourcelink{background-color:#e8eef5;border-color:transparent;color:#4d7eb2}html.theme--documenter-dark .button.is-primary.is-light:active,html.theme--documenter-dark .docstring>section>a.button.is-light.docs-sourcelink:active,html.theme--documenter-dark .button.is-primary.is-light.is-active,html.theme--documenter-dark .docstring>section>a.button.is-light.is-active.docs-sourcelink{background-color:#dfe8f1;border-color:transparent;color:#4d7eb2}html.theme--documenter-dark .button.is-link{background-color:#1abc9c;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link:hover,html.theme--documenter-dark .button.is-link.is-hovered{background-color:#18b193;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link:focus,html.theme--documenter-dark .button.is-link.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link:focus:not(:active),html.theme--documenter-dark .button.is-link.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .button.is-link:active,html.theme--documenter-dark .button.is-link.is-active{background-color:#17a689;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-link[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link{background-color:#1abc9c;border-color:#1abc9c;box-shadow:none}html.theme--documenter-dark .button.is-link.is-inverted{background-color:#fff;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-inverted:hover,html.theme--documenter-dark .button.is-link.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-link.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-link.is-outlined{background-color:transparent;border-color:#1abc9c;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-outlined:hover,html.theme--documenter-dark .button.is-link.is-outlined.is-hovered,html.theme--documenter-dark .button.is-link.is-outlined:focus,html.theme--documenter-dark .button.is-link.is-outlined.is-focused{background-color:#1abc9c;border-color:#1abc9c;color:#fff}html.theme--documenter-dark .button.is-link.is-outlined.is-loading::after{border-color:transparent transparent #1abc9c #1abc9c !important}html.theme--documenter-dark .button.is-link.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-link.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-link.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-link.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-link.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link.is-outlined{background-color:transparent;border-color:#1abc9c;box-shadow:none;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-focused{background-color:#fff;color:#1abc9c}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-link.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #1abc9c #1abc9c !important}html.theme--documenter-dark .button.is-link.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-link.is-light{background-color:#edfdf9;color:#15987e}html.theme--documenter-dark .button.is-link.is-light:hover,html.theme--documenter-dark .button.is-link.is-light.is-hovered{background-color:#e2fbf6;border-color:transparent;color:#15987e}html.theme--documenter-dark .button.is-link.is-light:active,html.theme--documenter-dark .button.is-link.is-light.is-active{background-color:#d7f9f3;border-color:transparent;color:#15987e}html.theme--documenter-dark .button.is-info{background-color:#024c7d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info:hover,html.theme--documenter-dark .button.is-info.is-hovered{background-color:#024470;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info:focus,html.theme--documenter-dark .button.is-info.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info:focus:not(:active),html.theme--documenter-dark .button.is-info.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(2,76,125,0.25)}html.theme--documenter-dark .button.is-info:active,html.theme--documenter-dark .button.is-info.is-active{background-color:#023d64;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-info[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info{background-color:#024c7d;border-color:#024c7d;box-shadow:none}html.theme--documenter-dark .button.is-info.is-inverted{background-color:#fff;color:#024c7d}html.theme--documenter-dark .button.is-info.is-inverted:hover,html.theme--documenter-dark .button.is-info.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-info.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#024c7d}html.theme--documenter-dark .button.is-info.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-info.is-outlined{background-color:transparent;border-color:#024c7d;color:#024c7d}html.theme--documenter-dark .button.is-info.is-outlined:hover,html.theme--documenter-dark .button.is-info.is-outlined.is-hovered,html.theme--documenter-dark .button.is-info.is-outlined:focus,html.theme--documenter-dark .button.is-info.is-outlined.is-focused{background-color:#024c7d;border-color:#024c7d;color:#fff}html.theme--documenter-dark .button.is-info.is-outlined.is-loading::after{border-color:transparent transparent #024c7d #024c7d !important}html.theme--documenter-dark .button.is-info.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-info.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-info.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-info.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-info.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info.is-outlined{background-color:transparent;border-color:#024c7d;box-shadow:none;color:#024c7d}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-focused{background-color:#fff;color:#024c7d}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-info.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #024c7d #024c7d !important}html.theme--documenter-dark .button.is-info.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-info.is-light{background-color:#ebf7ff;color:#0e9dfb}html.theme--documenter-dark .button.is-info.is-light:hover,html.theme--documenter-dark .button.is-info.is-light.is-hovered{background-color:#def2fe;border-color:transparent;color:#0e9dfb}html.theme--documenter-dark .button.is-info.is-light:active,html.theme--documenter-dark .button.is-info.is-light.is-active{background-color:#d2edfe;border-color:transparent;color:#0e9dfb}html.theme--documenter-dark .button.is-success{background-color:#008438;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success:hover,html.theme--documenter-dark .button.is-success.is-hovered{background-color:#073;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success:focus,html.theme--documenter-dark .button.is-success.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success:focus:not(:active),html.theme--documenter-dark .button.is-success.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(0,132,56,0.25)}html.theme--documenter-dark .button.is-success:active,html.theme--documenter-dark .button.is-success.is-active{background-color:#006b2d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-success[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success{background-color:#008438;border-color:#008438;box-shadow:none}html.theme--documenter-dark .button.is-success.is-inverted{background-color:#fff;color:#008438}html.theme--documenter-dark .button.is-success.is-inverted:hover,html.theme--documenter-dark .button.is-success.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-success.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#008438}html.theme--documenter-dark .button.is-success.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-success.is-outlined{background-color:transparent;border-color:#008438;color:#008438}html.theme--documenter-dark .button.is-success.is-outlined:hover,html.theme--documenter-dark .button.is-success.is-outlined.is-hovered,html.theme--documenter-dark .button.is-success.is-outlined:focus,html.theme--documenter-dark .button.is-success.is-outlined.is-focused{background-color:#008438;border-color:#008438;color:#fff}html.theme--documenter-dark .button.is-success.is-outlined.is-loading::after{border-color:transparent transparent #008438 #008438 !important}html.theme--documenter-dark .button.is-success.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-success.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-success.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-success.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-success.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success.is-outlined{background-color:transparent;border-color:#008438;box-shadow:none;color:#008438}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-focused{background-color:#fff;color:#008438}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-success.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #008438 #008438 !important}html.theme--documenter-dark .button.is-success.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-success.is-light{background-color:#ebfff3;color:#00eb64}html.theme--documenter-dark .button.is-success.is-light:hover,html.theme--documenter-dark .button.is-success.is-light.is-hovered{background-color:#deffec;border-color:transparent;color:#00eb64}html.theme--documenter-dark .button.is-success.is-light:active,html.theme--documenter-dark .button.is-success.is-light.is-active{background-color:#d1ffe5;border-color:transparent;color:#00eb64}html.theme--documenter-dark .button.is-warning{background-color:#ad8100;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning:hover,html.theme--documenter-dark .button.is-warning.is-hovered{background-color:#a07700;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning:focus,html.theme--documenter-dark .button.is-warning.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning:focus:not(:active),html.theme--documenter-dark .button.is-warning.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(173,129,0,0.25)}html.theme--documenter-dark .button.is-warning:active,html.theme--documenter-dark .button.is-warning.is-active{background-color:#946e00;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-warning[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning{background-color:#ad8100;border-color:#ad8100;box-shadow:none}html.theme--documenter-dark .button.is-warning.is-inverted{background-color:#fff;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-inverted:hover,html.theme--documenter-dark .button.is-warning.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-warning.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-warning.is-outlined{background-color:transparent;border-color:#ad8100;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-outlined:hover,html.theme--documenter-dark .button.is-warning.is-outlined.is-hovered,html.theme--documenter-dark .button.is-warning.is-outlined:focus,html.theme--documenter-dark .button.is-warning.is-outlined.is-focused{background-color:#ad8100;border-color:#ad8100;color:#fff}html.theme--documenter-dark .button.is-warning.is-outlined.is-loading::after{border-color:transparent transparent #ad8100 #ad8100 !important}html.theme--documenter-dark .button.is-warning.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-warning.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-warning.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-warning.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-warning.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-outlined{background-color:transparent;border-color:#ad8100;box-shadow:none;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-focused{background-color:#fff;color:#ad8100}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #ad8100 #ad8100 !important}html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-warning.is-light{background-color:#fffaeb;color:#d19c00}html.theme--documenter-dark .button.is-warning.is-light:hover,html.theme--documenter-dark .button.is-warning.is-light.is-hovered{background-color:#fff7de;border-color:transparent;color:#d19c00}html.theme--documenter-dark .button.is-warning.is-light:active,html.theme--documenter-dark .button.is-warning.is-light.is-active{background-color:#fff3d1;border-color:transparent;color:#d19c00}html.theme--documenter-dark .button.is-danger{background-color:#9e1b0d;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger:hover,html.theme--documenter-dark .button.is-danger.is-hovered{background-color:#92190c;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger:focus,html.theme--documenter-dark .button.is-danger.is-focused{border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger:focus:not(:active),html.theme--documenter-dark .button.is-danger.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(158,27,13,0.25)}html.theme--documenter-dark .button.is-danger:active,html.theme--documenter-dark .button.is-danger.is-active{background-color:#86170b;border-color:transparent;color:#fff}html.theme--documenter-dark .button.is-danger[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger{background-color:#9e1b0d;border-color:#9e1b0d;box-shadow:none}html.theme--documenter-dark .button.is-danger.is-inverted{background-color:#fff;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-inverted:hover,html.theme--documenter-dark .button.is-danger.is-inverted.is-hovered{background-color:#f2f2f2}html.theme--documenter-dark .button.is-danger.is-inverted[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-loading::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-danger.is-outlined{background-color:transparent;border-color:#9e1b0d;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-outlined:hover,html.theme--documenter-dark .button.is-danger.is-outlined.is-hovered,html.theme--documenter-dark .button.is-danger.is-outlined:focus,html.theme--documenter-dark .button.is-danger.is-outlined.is-focused{background-color:#9e1b0d;border-color:#9e1b0d;color:#fff}html.theme--documenter-dark .button.is-danger.is-outlined.is-loading::after{border-color:transparent transparent #9e1b0d #9e1b0d !important}html.theme--documenter-dark .button.is-danger.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-danger.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-danger.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-danger.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}html.theme--documenter-dark .button.is-danger.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-outlined{background-color:transparent;border-color:#9e1b0d;box-shadow:none;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined:hover,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-hovered,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined:focus,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-focused{background-color:#fff;color:#9e1b0d}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading:hover::after,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading:focus::after,html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #9e1b0d #9e1b0d !important}html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined[disabled],fieldset[disabled] html.theme--documenter-dark .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}html.theme--documenter-dark .button.is-danger.is-light{background-color:#fdeeec;color:#ec311d}html.theme--documenter-dark .button.is-danger.is-light:hover,html.theme--documenter-dark .button.is-danger.is-light.is-hovered{background-color:#fce3e0;border-color:transparent;color:#ec311d}html.theme--documenter-dark .button.is-danger.is-light:active,html.theme--documenter-dark .button.is-danger.is-light.is-active{background-color:#fcd8d5;border-color:transparent;color:#ec311d}html.theme--documenter-dark .button.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.button{font-size:.75rem}html.theme--documenter-dark .button.is-small:not(.is-rounded),html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.button:not(.is-rounded){border-radius:3px}html.theme--documenter-dark .button.is-normal{font-size:1rem}html.theme--documenter-dark .button.is-medium{font-size:1.25rem}html.theme--documenter-dark .button.is-large{font-size:1.5rem}html.theme--documenter-dark .button[disabled],fieldset[disabled] html.theme--documenter-dark .button{background-color:#8c9b9d;border-color:#5e6d6f;box-shadow:none;opacity:.5}html.theme--documenter-dark .button.is-fullwidth{display:flex;width:100%}html.theme--documenter-dark .button.is-loading{color:transparent !important;pointer-events:none}html.theme--documenter-dark .button.is-loading::after{position:absolute;left:calc(50% - (1em * 0.5));top:calc(50% - (1em * 0.5));position:absolute !important}html.theme--documenter-dark .button.is-static{background-color:#282f2f;border-color:#5e6d6f;color:#dbdee0;box-shadow:none;pointer-events:none}html.theme--documenter-dark .button.is-rounded,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.button{border-radius:9999px;padding-left:calc(1em + 0.25em);padding-right:calc(1em + 0.25em)}html.theme--documenter-dark .buttons{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--documenter-dark .buttons .button{margin-bottom:0.5rem}html.theme--documenter-dark .buttons .button:not(:last-child):not(.is-fullwidth){margin-right:.5rem}html.theme--documenter-dark .buttons:last-child{margin-bottom:-0.5rem}html.theme--documenter-dark .buttons:not(:last-child){margin-bottom:1rem}html.theme--documenter-dark .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large){font-size:.75rem}html.theme--documenter-dark .buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large):not(.is-rounded){border-radius:3px}html.theme--documenter-dark .buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large){font-size:1.25rem}html.theme--documenter-dark .buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium){font-size:1.5rem}html.theme--documenter-dark .buttons.has-addons .button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}html.theme--documenter-dark .buttons.has-addons .button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}html.theme--documenter-dark .buttons.has-addons .button:last-child{margin-right:0}html.theme--documenter-dark .buttons.has-addons .button:hover,html.theme--documenter-dark .buttons.has-addons .button.is-hovered{z-index:2}html.theme--documenter-dark .buttons.has-addons .button:focus,html.theme--documenter-dark .buttons.has-addons .button.is-focused,html.theme--documenter-dark .buttons.has-addons .button:active,html.theme--documenter-dark .buttons.has-addons .button.is-active,html.theme--documenter-dark .buttons.has-addons .button.is-selected{z-index:3}html.theme--documenter-dark .buttons.has-addons .button:focus:hover,html.theme--documenter-dark .buttons.has-addons .button.is-focused:hover,html.theme--documenter-dark .buttons.has-addons .button:active:hover,html.theme--documenter-dark .buttons.has-addons .button.is-active:hover,html.theme--documenter-dark .buttons.has-addons .button.is-selected:hover{z-index:4}html.theme--documenter-dark .buttons.has-addons .button.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .buttons.is-centered{justify-content:center}html.theme--documenter-dark .buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}html.theme--documenter-dark .buttons.is-right{justify-content:flex-end}html.theme--documenter-dark .buttons.is-right:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}@media screen and (max-width: 768px){html.theme--documenter-dark .button.is-responsive.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.5625rem}html.theme--documenter-dark .button.is-responsive,html.theme--documenter-dark .button.is-responsive.is-normal{font-size:.65625rem}html.theme--documenter-dark .button.is-responsive.is-medium{font-size:.75rem}html.theme--documenter-dark .button.is-responsive.is-large{font-size:1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .button.is-responsive.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.65625rem}html.theme--documenter-dark .button.is-responsive,html.theme--documenter-dark .button.is-responsive.is-normal{font-size:.75rem}html.theme--documenter-dark .button.is-responsive.is-medium{font-size:1rem}html.theme--documenter-dark .button.is-responsive.is-large{font-size:1.25rem}}html.theme--documenter-dark .container{flex-grow:1;margin:0 auto;position:relative;width:auto}html.theme--documenter-dark .container.is-fluid{max-width:none !important;padding-left:32px;padding-right:32px;width:100%}@media screen and (min-width: 1056px){html.theme--documenter-dark .container{max-width:992px}}@media screen and (max-width: 1215px){html.theme--documenter-dark .container.is-widescreen:not(.is-max-desktop){max-width:1152px}}@media screen and (max-width: 1407px){html.theme--documenter-dark .container.is-fullhd:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}@media screen and (min-width: 1216px){html.theme--documenter-dark .container:not(.is-max-desktop){max-width:1152px}}@media screen and (min-width: 1408px){html.theme--documenter-dark .container:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}html.theme--documenter-dark .content li+li{margin-top:0.25em}html.theme--documenter-dark .content p:not(:last-child),html.theme--documenter-dark .content dl:not(:last-child),html.theme--documenter-dark .content ol:not(:last-child),html.theme--documenter-dark .content ul:not(:last-child),html.theme--documenter-dark .content blockquote:not(:last-child),html.theme--documenter-dark .content pre:not(:last-child),html.theme--documenter-dark .content table:not(:last-child){margin-bottom:1em}html.theme--documenter-dark .content h1,html.theme--documenter-dark .content h2,html.theme--documenter-dark .content h3,html.theme--documenter-dark .content h4,html.theme--documenter-dark .content h5,html.theme--documenter-dark .content h6{color:#f2f2f2;font-weight:600;line-height:1.125}html.theme--documenter-dark .content h1{font-size:2em;margin-bottom:0.5em}html.theme--documenter-dark .content h1:not(:first-child){margin-top:1em}html.theme--documenter-dark .content h2{font-size:1.75em;margin-bottom:0.5714em}html.theme--documenter-dark .content h2:not(:first-child){margin-top:1.1428em}html.theme--documenter-dark .content h3{font-size:1.5em;margin-bottom:0.6666em}html.theme--documenter-dark .content h3:not(:first-child){margin-top:1.3333em}html.theme--documenter-dark .content h4{font-size:1.25em;margin-bottom:0.8em}html.theme--documenter-dark .content h5{font-size:1.125em;margin-bottom:0.8888em}html.theme--documenter-dark .content h6{font-size:1em;margin-bottom:1em}html.theme--documenter-dark .content blockquote{background-color:#282f2f;border-left:5px solid #5e6d6f;padding:1.25em 1.5em}html.theme--documenter-dark .content ol{list-style-position:outside;margin-left:2em;margin-top:1em}html.theme--documenter-dark .content ol:not([type]){list-style-type:decimal}html.theme--documenter-dark .content ol.is-lower-alpha:not([type]){list-style-type:lower-alpha}html.theme--documenter-dark .content ol.is-lower-roman:not([type]){list-style-type:lower-roman}html.theme--documenter-dark .content ol.is-upper-alpha:not([type]){list-style-type:upper-alpha}html.theme--documenter-dark .content ol.is-upper-roman:not([type]){list-style-type:upper-roman}html.theme--documenter-dark .content ul{list-style:disc outside;margin-left:2em;margin-top:1em}html.theme--documenter-dark .content ul ul{list-style-type:circle;margin-top:0.5em}html.theme--documenter-dark .content ul ul ul{list-style-type:square}html.theme--documenter-dark .content dd{margin-left:2em}html.theme--documenter-dark .content figure{margin-left:2em;margin-right:2em;text-align:center}html.theme--documenter-dark .content figure:not(:first-child){margin-top:2em}html.theme--documenter-dark .content figure:not(:last-child){margin-bottom:2em}html.theme--documenter-dark .content figure img{display:inline-block}html.theme--documenter-dark .content figure figcaption{font-style:italic}html.theme--documenter-dark .content pre{-webkit-overflow-scrolling:touch;overflow-x:auto;padding:0;white-space:pre;word-wrap:normal}html.theme--documenter-dark .content sup,html.theme--documenter-dark .content sub{font-size:75%}html.theme--documenter-dark .content table{width:100%}html.theme--documenter-dark .content table td,html.theme--documenter-dark .content table th{border:1px solid #5e6d6f;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--documenter-dark .content table th{color:#f2f2f2}html.theme--documenter-dark .content table th:not([align]){text-align:inherit}html.theme--documenter-dark .content table thead td,html.theme--documenter-dark .content table thead th{border-width:0 0 2px;color:#f2f2f2}html.theme--documenter-dark .content table tfoot td,html.theme--documenter-dark .content table tfoot th{border-width:2px 0 0;color:#f2f2f2}html.theme--documenter-dark .content table tbody tr:last-child td,html.theme--documenter-dark .content table tbody tr:last-child th{border-bottom-width:0}html.theme--documenter-dark .content .tabs li+li{margin-top:0}html.theme--documenter-dark .content.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.content{font-size:.75rem}html.theme--documenter-dark .content.is-normal{font-size:1rem}html.theme--documenter-dark .content.is-medium{font-size:1.25rem}html.theme--documenter-dark .content.is-large{font-size:1.5rem}html.theme--documenter-dark .icon{align-items:center;display:inline-flex;justify-content:center;height:1.5rem;width:1.5rem}html.theme--documenter-dark .icon.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.icon{height:1rem;width:1rem}html.theme--documenter-dark .icon.is-medium{height:2rem;width:2rem}html.theme--documenter-dark .icon.is-large{height:3rem;width:3rem}html.theme--documenter-dark .icon-text{align-items:flex-start;color:inherit;display:inline-flex;flex-wrap:wrap;line-height:1.5rem;vertical-align:top}html.theme--documenter-dark .icon-text .icon{flex-grow:0;flex-shrink:0}html.theme--documenter-dark .icon-text .icon:not(:last-child){margin-right:.25em}html.theme--documenter-dark .icon-text .icon:not(:first-child){margin-left:.25em}html.theme--documenter-dark div.icon-text{display:flex}html.theme--documenter-dark .image,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img{display:block;position:relative}html.theme--documenter-dark .image img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img img{display:block;height:auto;width:100%}html.theme--documenter-dark .image img.is-rounded,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img img.is-rounded{border-radius:9999px}html.theme--documenter-dark .image.is-fullwidth,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-fullwidth{width:100%}html.theme--documenter-dark .image.is-square img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square img,html.theme--documenter-dark .image.is-square .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,html.theme--documenter-dark .image.is-1by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 img,html.theme--documenter-dark .image.is-1by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,html.theme--documenter-dark .image.is-5by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 img,html.theme--documenter-dark .image.is-5by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,html.theme--documenter-dark .image.is-4by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 img,html.theme--documenter-dark .image.is-4by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,html.theme--documenter-dark .image.is-3by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 img,html.theme--documenter-dark .image.is-3by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,html.theme--documenter-dark .image.is-5by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 img,html.theme--documenter-dark .image.is-5by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,html.theme--documenter-dark .image.is-16by9 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 img,html.theme--documenter-dark .image.is-16by9 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,html.theme--documenter-dark .image.is-2by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 img,html.theme--documenter-dark .image.is-2by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,html.theme--documenter-dark .image.is-3by1 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 img,html.theme--documenter-dark .image.is-3by1 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,html.theme--documenter-dark .image.is-4by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 img,html.theme--documenter-dark .image.is-4by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,html.theme--documenter-dark .image.is-3by4 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 img,html.theme--documenter-dark .image.is-3by4 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,html.theme--documenter-dark .image.is-2by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 img,html.theme--documenter-dark .image.is-2by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,html.theme--documenter-dark .image.is-3by5 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 img,html.theme--documenter-dark .image.is-3by5 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,html.theme--documenter-dark .image.is-9by16 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 img,html.theme--documenter-dark .image.is-9by16 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,html.theme--documenter-dark .image.is-1by2 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 img,html.theme--documenter-dark .image.is-1by2 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,html.theme--documenter-dark .image.is-1by3 img,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 img,html.theme--documenter-dark .image.is-1by3 .has-ratio,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio{height:100%;width:100%}html.theme--documenter-dark .image.is-square,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-square,html.theme--documenter-dark .image.is-1by1,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by1{padding-top:100%}html.theme--documenter-dark .image.is-5by4,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by4{padding-top:80%}html.theme--documenter-dark .image.is-4by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by3{padding-top:75%}html.theme--documenter-dark .image.is-3by2,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by2{padding-top:66.6666%}html.theme--documenter-dark .image.is-5by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-5by3{padding-top:60%}html.theme--documenter-dark .image.is-16by9,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16by9{padding-top:56.25%}html.theme--documenter-dark .image.is-2by1,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by1{padding-top:50%}html.theme--documenter-dark .image.is-3by1,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by1{padding-top:33.3333%}html.theme--documenter-dark .image.is-4by5,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-4by5{padding-top:125%}html.theme--documenter-dark .image.is-3by4,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by4{padding-top:133.3333%}html.theme--documenter-dark .image.is-2by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-2by3{padding-top:150%}html.theme--documenter-dark .image.is-3by5,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-3by5{padding-top:166.6666%}html.theme--documenter-dark .image.is-9by16,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-9by16{padding-top:177.7777%}html.theme--documenter-dark .image.is-1by2,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by2{padding-top:200%}html.theme--documenter-dark .image.is-1by3,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-1by3{padding-top:300%}html.theme--documenter-dark .image.is-16x16,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-16x16{height:16px;width:16px}html.theme--documenter-dark .image.is-24x24,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-24x24{height:24px;width:24px}html.theme--documenter-dark .image.is-32x32,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-32x32{height:32px;width:32px}html.theme--documenter-dark .image.is-48x48,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-48x48{height:48px;width:48px}html.theme--documenter-dark .image.is-64x64,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-64x64{height:64px;width:64px}html.theme--documenter-dark .image.is-96x96,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-96x96{height:96px;width:96px}html.theme--documenter-dark .image.is-128x128,html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img.is-128x128{height:128px;width:128px}html.theme--documenter-dark .notification{background-color:#282f2f;border-radius:.4em;position:relative;padding:1.25rem 2.5rem 1.25rem 1.5rem}html.theme--documenter-dark .notification a:not(.button):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--documenter-dark .notification strong{color:currentColor}html.theme--documenter-dark .notification code,html.theme--documenter-dark .notification pre{background:#fff}html.theme--documenter-dark .notification pre code{background:transparent}html.theme--documenter-dark .notification>.delete{right:.5rem;position:absolute;top:0.5rem}html.theme--documenter-dark .notification .title,html.theme--documenter-dark .notification .subtitle,html.theme--documenter-dark .notification .content{color:currentColor}html.theme--documenter-dark .notification.is-white{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .notification.is-black{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .notification.is-light{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .notification.is-dark,html.theme--documenter-dark .content kbd.notification{background-color:#282f2f;color:#fff}html.theme--documenter-dark .notification.is-primary,html.theme--documenter-dark .docstring>section>a.notification.docs-sourcelink{background-color:#375a7f;color:#fff}html.theme--documenter-dark .notification.is-primary.is-light,html.theme--documenter-dark .docstring>section>a.notification.is-light.docs-sourcelink{background-color:#f1f5f9;color:#4d7eb2}html.theme--documenter-dark .notification.is-link{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .notification.is-link.is-light{background-color:#edfdf9;color:#15987e}html.theme--documenter-dark .notification.is-info{background-color:#024c7d;color:#fff}html.theme--documenter-dark .notification.is-info.is-light{background-color:#ebf7ff;color:#0e9dfb}html.theme--documenter-dark .notification.is-success{background-color:#008438;color:#fff}html.theme--documenter-dark .notification.is-success.is-light{background-color:#ebfff3;color:#00eb64}html.theme--documenter-dark .notification.is-warning{background-color:#ad8100;color:#fff}html.theme--documenter-dark .notification.is-warning.is-light{background-color:#fffaeb;color:#d19c00}html.theme--documenter-dark .notification.is-danger{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .notification.is-danger.is-light{background-color:#fdeeec;color:#ec311d}html.theme--documenter-dark .progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:9999px;display:block;height:1rem;overflow:hidden;padding:0;width:100%}html.theme--documenter-dark .progress::-webkit-progress-bar{background-color:#343c3d}html.theme--documenter-dark .progress::-webkit-progress-value{background-color:#dbdee0}html.theme--documenter-dark .progress::-moz-progress-bar{background-color:#dbdee0}html.theme--documenter-dark .progress::-ms-fill{background-color:#dbdee0;border:none}html.theme--documenter-dark .progress.is-white::-webkit-progress-value{background-color:#fff}html.theme--documenter-dark .progress.is-white::-moz-progress-bar{background-color:#fff}html.theme--documenter-dark .progress.is-white::-ms-fill{background-color:#fff}html.theme--documenter-dark .progress.is-white:indeterminate{background-image:linear-gradient(to right, #fff 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-black::-webkit-progress-value{background-color:#0a0a0a}html.theme--documenter-dark .progress.is-black::-moz-progress-bar{background-color:#0a0a0a}html.theme--documenter-dark .progress.is-black::-ms-fill{background-color:#0a0a0a}html.theme--documenter-dark .progress.is-black:indeterminate{background-image:linear-gradient(to right, #0a0a0a 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-light::-webkit-progress-value{background-color:#ecf0f1}html.theme--documenter-dark .progress.is-light::-moz-progress-bar{background-color:#ecf0f1}html.theme--documenter-dark .progress.is-light::-ms-fill{background-color:#ecf0f1}html.theme--documenter-dark .progress.is-light:indeterminate{background-image:linear-gradient(to right, #ecf0f1 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-dark::-webkit-progress-value,html.theme--documenter-dark .content kbd.progress::-webkit-progress-value{background-color:#282f2f}html.theme--documenter-dark .progress.is-dark::-moz-progress-bar,html.theme--documenter-dark .content kbd.progress::-moz-progress-bar{background-color:#282f2f}html.theme--documenter-dark .progress.is-dark::-ms-fill,html.theme--documenter-dark .content kbd.progress::-ms-fill{background-color:#282f2f}html.theme--documenter-dark .progress.is-dark:indeterminate,html.theme--documenter-dark .content kbd.progress:indeterminate{background-image:linear-gradient(to right, #282f2f 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-primary::-webkit-progress-value,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink::-webkit-progress-value{background-color:#375a7f}html.theme--documenter-dark .progress.is-primary::-moz-progress-bar,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink::-moz-progress-bar{background-color:#375a7f}html.theme--documenter-dark .progress.is-primary::-ms-fill,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink::-ms-fill{background-color:#375a7f}html.theme--documenter-dark .progress.is-primary:indeterminate,html.theme--documenter-dark .docstring>section>a.progress.docs-sourcelink:indeterminate{background-image:linear-gradient(to right, #375a7f 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-link::-webkit-progress-value{background-color:#1abc9c}html.theme--documenter-dark .progress.is-link::-moz-progress-bar{background-color:#1abc9c}html.theme--documenter-dark .progress.is-link::-ms-fill{background-color:#1abc9c}html.theme--documenter-dark .progress.is-link:indeterminate{background-image:linear-gradient(to right, #1abc9c 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-info::-webkit-progress-value{background-color:#024c7d}html.theme--documenter-dark .progress.is-info::-moz-progress-bar{background-color:#024c7d}html.theme--documenter-dark .progress.is-info::-ms-fill{background-color:#024c7d}html.theme--documenter-dark .progress.is-info:indeterminate{background-image:linear-gradient(to right, #024c7d 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-success::-webkit-progress-value{background-color:#008438}html.theme--documenter-dark .progress.is-success::-moz-progress-bar{background-color:#008438}html.theme--documenter-dark .progress.is-success::-ms-fill{background-color:#008438}html.theme--documenter-dark .progress.is-success:indeterminate{background-image:linear-gradient(to right, #008438 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-warning::-webkit-progress-value{background-color:#ad8100}html.theme--documenter-dark .progress.is-warning::-moz-progress-bar{background-color:#ad8100}html.theme--documenter-dark .progress.is-warning::-ms-fill{background-color:#ad8100}html.theme--documenter-dark .progress.is-warning:indeterminate{background-image:linear-gradient(to right, #ad8100 30%, #343c3d 30%)}html.theme--documenter-dark .progress.is-danger::-webkit-progress-value{background-color:#9e1b0d}html.theme--documenter-dark .progress.is-danger::-moz-progress-bar{background-color:#9e1b0d}html.theme--documenter-dark .progress.is-danger::-ms-fill{background-color:#9e1b0d}html.theme--documenter-dark .progress.is-danger:indeterminate{background-image:linear-gradient(to right, #9e1b0d 30%, #343c3d 30%)}html.theme--documenter-dark .progress:indeterminate{animation-duration:1.5s;animation-iteration-count:infinite;animation-name:moveIndeterminate;animation-timing-function:linear;background-color:#343c3d;background-image:linear-gradient(to right, #fff 30%, #343c3d 30%);background-position:top left;background-repeat:no-repeat;background-size:150% 150%}html.theme--documenter-dark .progress:indeterminate::-webkit-progress-bar{background-color:transparent}html.theme--documenter-dark .progress:indeterminate::-moz-progress-bar{background-color:transparent}html.theme--documenter-dark .progress:indeterminate::-ms-fill{animation-name:none}html.theme--documenter-dark .progress.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.progress{height:.75rem}html.theme--documenter-dark .progress.is-medium{height:1.25rem}html.theme--documenter-dark .progress.is-large{height:1.5rem}@keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}html.theme--documenter-dark .table{background-color:#343c3d;color:#fff}html.theme--documenter-dark .table td,html.theme--documenter-dark .table th{border:1px solid #5e6d6f;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}html.theme--documenter-dark .table td.is-white,html.theme--documenter-dark .table th.is-white{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--documenter-dark .table td.is-black,html.theme--documenter-dark .table th.is-black{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--documenter-dark .table td.is-light,html.theme--documenter-dark .table th.is-light{background-color:#ecf0f1;border-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .table td.is-dark,html.theme--documenter-dark .table th.is-dark{background-color:#282f2f;border-color:#282f2f;color:#fff}html.theme--documenter-dark .table td.is-primary,html.theme--documenter-dark .table th.is-primary{background-color:#375a7f;border-color:#375a7f;color:#fff}html.theme--documenter-dark .table td.is-link,html.theme--documenter-dark .table th.is-link{background-color:#1abc9c;border-color:#1abc9c;color:#fff}html.theme--documenter-dark .table td.is-info,html.theme--documenter-dark .table th.is-info{background-color:#024c7d;border-color:#024c7d;color:#fff}html.theme--documenter-dark .table td.is-success,html.theme--documenter-dark .table th.is-success{background-color:#008438;border-color:#008438;color:#fff}html.theme--documenter-dark .table td.is-warning,html.theme--documenter-dark .table th.is-warning{background-color:#ad8100;border-color:#ad8100;color:#fff}html.theme--documenter-dark .table td.is-danger,html.theme--documenter-dark .table th.is-danger{background-color:#9e1b0d;border-color:#9e1b0d;color:#fff}html.theme--documenter-dark .table td.is-narrow,html.theme--documenter-dark .table th.is-narrow{white-space:nowrap;width:1%}html.theme--documenter-dark .table td.is-selected,html.theme--documenter-dark .table th.is-selected{background-color:#375a7f;color:#fff}html.theme--documenter-dark .table td.is-selected a,html.theme--documenter-dark .table td.is-selected strong,html.theme--documenter-dark .table th.is-selected a,html.theme--documenter-dark .table th.is-selected strong{color:currentColor}html.theme--documenter-dark .table td.is-vcentered,html.theme--documenter-dark .table th.is-vcentered{vertical-align:middle}html.theme--documenter-dark .table th{color:#f2f2f2}html.theme--documenter-dark .table th:not([align]){text-align:left}html.theme--documenter-dark .table tr.is-selected{background-color:#375a7f;color:#fff}html.theme--documenter-dark .table tr.is-selected a,html.theme--documenter-dark .table tr.is-selected strong{color:currentColor}html.theme--documenter-dark .table tr.is-selected td,html.theme--documenter-dark .table tr.is-selected th{border-color:#fff;color:currentColor}html.theme--documenter-dark .table thead{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .table thead td,html.theme--documenter-dark .table thead th{border-width:0 0 2px;color:#f2f2f2}html.theme--documenter-dark .table tfoot{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .table tfoot td,html.theme--documenter-dark .table tfoot th{border-width:2px 0 0;color:#f2f2f2}html.theme--documenter-dark .table tbody{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .table tbody tr:last-child td,html.theme--documenter-dark .table tbody tr:last-child th{border-bottom-width:0}html.theme--documenter-dark .table.is-bordered td,html.theme--documenter-dark .table.is-bordered th{border-width:1px}html.theme--documenter-dark .table.is-bordered tr:last-child td,html.theme--documenter-dark .table.is-bordered tr:last-child th{border-bottom-width:1px}html.theme--documenter-dark .table.is-fullwidth{width:100%}html.theme--documenter-dark .table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#282f2f}html.theme--documenter-dark .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover{background-color:#282f2f}html.theme--documenter-dark .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even){background-color:#2d3435}html.theme--documenter-dark .table.is-narrow td,html.theme--documenter-dark .table.is-narrow th{padding:0.25em 0.5em}html.theme--documenter-dark .table.is-striped tbody tr:not(.is-selected):nth-child(even){background-color:#282f2f}html.theme--documenter-dark .table-container{-webkit-overflow-scrolling:touch;overflow:auto;overflow-y:hidden;max-width:100%}html.theme--documenter-dark .tags{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--documenter-dark .tags .tag,html.theme--documenter-dark .tags .content kbd,html.theme--documenter-dark .content .tags kbd,html.theme--documenter-dark .tags .docstring>section>a.docs-sourcelink{margin-bottom:0.5rem}html.theme--documenter-dark .tags .tag:not(:last-child),html.theme--documenter-dark .tags .content kbd:not(:last-child),html.theme--documenter-dark .content .tags kbd:not(:last-child),html.theme--documenter-dark .tags .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:.5rem}html.theme--documenter-dark .tags:last-child{margin-bottom:-0.5rem}html.theme--documenter-dark .tags:not(:last-child){margin-bottom:1rem}html.theme--documenter-dark .tags.are-medium .tag:not(.is-normal):not(.is-large),html.theme--documenter-dark .tags.are-medium .content kbd:not(.is-normal):not(.is-large),html.theme--documenter-dark .content .tags.are-medium kbd:not(.is-normal):not(.is-large),html.theme--documenter-dark .tags.are-medium .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-large){font-size:1rem}html.theme--documenter-dark .tags.are-large .tag:not(.is-normal):not(.is-medium),html.theme--documenter-dark .tags.are-large .content kbd:not(.is-normal):not(.is-medium),html.theme--documenter-dark .content .tags.are-large kbd:not(.is-normal):not(.is-medium),html.theme--documenter-dark .tags.are-large .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-medium){font-size:1.25rem}html.theme--documenter-dark .tags.is-centered{justify-content:center}html.theme--documenter-dark .tags.is-centered .tag,html.theme--documenter-dark .tags.is-centered .content kbd,html.theme--documenter-dark .content .tags.is-centered kbd,html.theme--documenter-dark .tags.is-centered .docstring>section>a.docs-sourcelink{margin-right:0.25rem;margin-left:0.25rem}html.theme--documenter-dark .tags.is-right{justify-content:flex-end}html.theme--documenter-dark .tags.is-right .tag:not(:first-child),html.theme--documenter-dark .tags.is-right .content kbd:not(:first-child),html.theme--documenter-dark .content .tags.is-right kbd:not(:first-child),html.theme--documenter-dark .tags.is-right .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0.5rem}html.theme--documenter-dark .tags.is-right .tag:not(:last-child),html.theme--documenter-dark .tags.is-right .content kbd:not(:last-child),html.theme--documenter-dark .content .tags.is-right kbd:not(:last-child),html.theme--documenter-dark .tags.is-right .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:0}html.theme--documenter-dark .tags.has-addons .tag,html.theme--documenter-dark .tags.has-addons .content kbd,html.theme--documenter-dark .content .tags.has-addons kbd,html.theme--documenter-dark .tags.has-addons .docstring>section>a.docs-sourcelink{margin-right:0}html.theme--documenter-dark .tags.has-addons .tag:not(:first-child),html.theme--documenter-dark .tags.has-addons .content kbd:not(:first-child),html.theme--documenter-dark .content .tags.has-addons kbd:not(:first-child),html.theme--documenter-dark .tags.has-addons .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0;border-top-left-radius:0;border-bottom-left-radius:0}html.theme--documenter-dark .tags.has-addons .tag:not(:last-child),html.theme--documenter-dark .tags.has-addons .content kbd:not(:last-child),html.theme--documenter-dark .content .tags.has-addons kbd:not(:last-child),html.theme--documenter-dark .tags.has-addons .docstring>section>a.docs-sourcelink:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}html.theme--documenter-dark .tag:not(body),html.theme--documenter-dark .content kbd:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body){align-items:center;background-color:#282f2f;border-radius:.4em;color:#fff;display:inline-flex;font-size:.75rem;height:2em;justify-content:center;line-height:1.5;padding-left:0.75em;padding-right:0.75em;white-space:nowrap}html.theme--documenter-dark .tag:not(body) .delete,html.theme--documenter-dark .content kbd:not(body) .delete,html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .delete{margin-left:.25rem;margin-right:-.375rem}html.theme--documenter-dark .tag.is-white:not(body),html.theme--documenter-dark .content kbd.is-white:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-white:not(body){background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .tag.is-black:not(body),html.theme--documenter-dark .content kbd.is-black:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-black:not(body){background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .tag.is-light:not(body),html.theme--documenter-dark .content kbd.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .tag.is-dark:not(body),html.theme--documenter-dark .content kbd:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-dark:not(body),html.theme--documenter-dark .content .docstring>section>kbd:not(body){background-color:#282f2f;color:#fff}html.theme--documenter-dark .tag.is-primary:not(body),html.theme--documenter-dark .content kbd.is-primary:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body){background-color:#375a7f;color:#fff}html.theme--documenter-dark .tag.is-primary.is-light:not(body),html.theme--documenter-dark .content kbd.is-primary.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#f1f5f9;color:#4d7eb2}html.theme--documenter-dark .tag.is-link:not(body),html.theme--documenter-dark .content kbd.is-link:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-link:not(body){background-color:#1abc9c;color:#fff}html.theme--documenter-dark .tag.is-link.is-light:not(body),html.theme--documenter-dark .content kbd.is-link.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-link.is-light:not(body){background-color:#edfdf9;color:#15987e}html.theme--documenter-dark .tag.is-info:not(body),html.theme--documenter-dark .content kbd.is-info:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-info:not(body){background-color:#024c7d;color:#fff}html.theme--documenter-dark .tag.is-info.is-light:not(body),html.theme--documenter-dark .content kbd.is-info.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-info.is-light:not(body){background-color:#ebf7ff;color:#0e9dfb}html.theme--documenter-dark .tag.is-success:not(body),html.theme--documenter-dark .content kbd.is-success:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-success:not(body){background-color:#008438;color:#fff}html.theme--documenter-dark .tag.is-success.is-light:not(body),html.theme--documenter-dark .content kbd.is-success.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-success.is-light:not(body){background-color:#ebfff3;color:#00eb64}html.theme--documenter-dark .tag.is-warning:not(body),html.theme--documenter-dark .content kbd.is-warning:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-warning:not(body){background-color:#ad8100;color:#fff}html.theme--documenter-dark .tag.is-warning.is-light:not(body),html.theme--documenter-dark .content kbd.is-warning.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-warning.is-light:not(body){background-color:#fffaeb;color:#d19c00}html.theme--documenter-dark .tag.is-danger:not(body),html.theme--documenter-dark .content kbd.is-danger:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-danger:not(body){background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .tag.is-danger.is-light:not(body),html.theme--documenter-dark .content kbd.is-danger.is-light:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-danger.is-light:not(body){background-color:#fdeeec;color:#ec311d}html.theme--documenter-dark .tag.is-normal:not(body),html.theme--documenter-dark .content kbd.is-normal:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-normal:not(body){font-size:.75rem}html.theme--documenter-dark .tag.is-medium:not(body),html.theme--documenter-dark .content kbd.is-medium:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-medium:not(body){font-size:1rem}html.theme--documenter-dark .tag.is-large:not(body),html.theme--documenter-dark .content kbd.is-large:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-large:not(body){font-size:1.25rem}html.theme--documenter-dark .tag:not(body) .icon:first-child:not(:last-child),html.theme--documenter-dark .content kbd:not(body) .icon:first-child:not(:last-child),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:not(:last-child){margin-left:-.375em;margin-right:.1875em}html.theme--documenter-dark .tag:not(body) .icon:last-child:not(:first-child),html.theme--documenter-dark .content kbd:not(body) .icon:last-child:not(:first-child),html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .icon:last-child:not(:first-child){margin-left:.1875em;margin-right:-.375em}html.theme--documenter-dark .tag:not(body) .icon:first-child:last-child,html.theme--documenter-dark .content kbd:not(body) .icon:first-child:last-child,html.theme--documenter-dark .docstring>section>a.docs-sourcelink:not(body) .icon:first-child:last-child{margin-left:-.375em;margin-right:-.375em}html.theme--documenter-dark .tag.is-delete:not(body),html.theme--documenter-dark .content kbd.is-delete:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body){margin-left:1px;padding:0;position:relative;width:2em}html.theme--documenter-dark .tag.is-delete:not(body)::before,html.theme--documenter-dark .content kbd.is-delete:not(body)::before,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::before,html.theme--documenter-dark .tag.is-delete:not(body)::after,html.theme--documenter-dark .content kbd.is-delete:not(body)::after,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{background-color:currentColor;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}html.theme--documenter-dark .tag.is-delete:not(body)::before,html.theme--documenter-dark .content kbd.is-delete:not(body)::before,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::before{height:1px;width:50%}html.theme--documenter-dark .tag.is-delete:not(body)::after,html.theme--documenter-dark .content kbd.is-delete:not(body)::after,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body)::after{height:50%;width:1px}html.theme--documenter-dark .tag.is-delete:not(body):hover,html.theme--documenter-dark .content kbd.is-delete:not(body):hover,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body):hover,html.theme--documenter-dark .tag.is-delete:not(body):focus,html.theme--documenter-dark .content kbd.is-delete:not(body):focus,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body):focus{background-color:#1d2122}html.theme--documenter-dark .tag.is-delete:not(body):active,html.theme--documenter-dark .content kbd.is-delete:not(body):active,html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-delete:not(body):active{background-color:#111414}html.theme--documenter-dark .tag.is-rounded:not(body),html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:not(body),html.theme--documenter-dark .content kbd.is-rounded:not(body),html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search>input:not(body),html.theme--documenter-dark .docstring>section>a.docs-sourcelink.is-rounded:not(body){border-radius:9999px}html.theme--documenter-dark a.tag:hover,html.theme--documenter-dark .docstring>section>a.docs-sourcelink:hover{text-decoration:underline}html.theme--documenter-dark .title,html.theme--documenter-dark .subtitle{word-break:break-word}html.theme--documenter-dark .title em,html.theme--documenter-dark .title span,html.theme--documenter-dark .subtitle em,html.theme--documenter-dark .subtitle span{font-weight:inherit}html.theme--documenter-dark .title sub,html.theme--documenter-dark .subtitle sub{font-size:.75em}html.theme--documenter-dark .title sup,html.theme--documenter-dark .subtitle sup{font-size:.75em}html.theme--documenter-dark .title .tag,html.theme--documenter-dark .title .content kbd,html.theme--documenter-dark .content .title kbd,html.theme--documenter-dark .title .docstring>section>a.docs-sourcelink,html.theme--documenter-dark .subtitle .tag,html.theme--documenter-dark .subtitle .content kbd,html.theme--documenter-dark .content .subtitle kbd,html.theme--documenter-dark .subtitle .docstring>section>a.docs-sourcelink{vertical-align:middle}html.theme--documenter-dark .title{color:#fff;font-size:2rem;font-weight:500;line-height:1.125}html.theme--documenter-dark .title strong{color:inherit;font-weight:inherit}html.theme--documenter-dark .title:not(.is-spaced)+.subtitle{margin-top:-1.25rem}html.theme--documenter-dark .title.is-1{font-size:3rem}html.theme--documenter-dark .title.is-2{font-size:2.5rem}html.theme--documenter-dark .title.is-3{font-size:2rem}html.theme--documenter-dark .title.is-4{font-size:1.5rem}html.theme--documenter-dark .title.is-5{font-size:1.25rem}html.theme--documenter-dark .title.is-6{font-size:1rem}html.theme--documenter-dark .title.is-7{font-size:.75rem}html.theme--documenter-dark .subtitle{color:#8c9b9d;font-size:1.25rem;font-weight:400;line-height:1.25}html.theme--documenter-dark .subtitle strong{color:#8c9b9d;font-weight:600}html.theme--documenter-dark .subtitle:not(.is-spaced)+.title{margin-top:-1.25rem}html.theme--documenter-dark .subtitle.is-1{font-size:3rem}html.theme--documenter-dark .subtitle.is-2{font-size:2.5rem}html.theme--documenter-dark .subtitle.is-3{font-size:2rem}html.theme--documenter-dark .subtitle.is-4{font-size:1.5rem}html.theme--documenter-dark .subtitle.is-5{font-size:1.25rem}html.theme--documenter-dark .subtitle.is-6{font-size:1rem}html.theme--documenter-dark .subtitle.is-7{font-size:.75rem}html.theme--documenter-dark .heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}html.theme--documenter-dark .number{align-items:center;background-color:#282f2f;border-radius:9999px;display:inline-flex;font-size:1.25rem;height:2em;justify-content:center;margin-right:1.5rem;min-width:2.5em;padding:0.25rem 0.5rem;text-align:center;vertical-align:top}html.theme--documenter-dark .select select,html.theme--documenter-dark .textarea,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{background-color:#1f2424;border-color:#5e6d6f;border-radius:.4em;color:#dbdee0}html.theme--documenter-dark .select select::-moz-placeholder,html.theme--documenter-dark .textarea::-moz-placeholder,html.theme--documenter-dark .input::-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:#868c98}html.theme--documenter-dark .select select::-webkit-input-placeholder,html.theme--documenter-dark .textarea::-webkit-input-placeholder,html.theme--documenter-dark .input::-webkit-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:#868c98}html.theme--documenter-dark .select select:-moz-placeholder,html.theme--documenter-dark .textarea:-moz-placeholder,html.theme--documenter-dark .input:-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:#868c98}html.theme--documenter-dark .select select:-ms-input-placeholder,html.theme--documenter-dark .textarea:-ms-input-placeholder,html.theme--documenter-dark .input:-ms-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:#868c98}html.theme--documenter-dark .select select:hover,html.theme--documenter-dark .textarea:hover,html.theme--documenter-dark .input:hover,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:hover,html.theme--documenter-dark .select select.is-hovered,html.theme--documenter-dark .is-hovered.textarea,html.theme--documenter-dark .is-hovered.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-hovered{border-color:#8c9b9d}html.theme--documenter-dark .select select:focus,html.theme--documenter-dark .textarea:focus,html.theme--documenter-dark .input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:focus,html.theme--documenter-dark .select select.is-focused,html.theme--documenter-dark .is-focused.textarea,html.theme--documenter-dark .is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .select select:active,html.theme--documenter-dark .textarea:active,html.theme--documenter-dark .input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:active,html.theme--documenter-dark .select select.is-active,html.theme--documenter-dark .is-active.textarea,html.theme--documenter-dark .is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{border-color:#1abc9c;box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .select select[disabled],html.theme--documenter-dark .textarea[disabled],html.theme--documenter-dark .input[disabled],html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled],fieldset[disabled] html.theme--documenter-dark .select select,fieldset[disabled] html.theme--documenter-dark .textarea,fieldset[disabled] html.theme--documenter-dark .input,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{background-color:#8c9b9d;border-color:#282f2f;box-shadow:none;color:#fff}html.theme--documenter-dark .select select[disabled]::-moz-placeholder,html.theme--documenter-dark .textarea[disabled]::-moz-placeholder,html.theme--documenter-dark .input[disabled]::-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .select select::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .input::-moz-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .select select[disabled]::-webkit-input-placeholder,html.theme--documenter-dark .textarea[disabled]::-webkit-input-placeholder,html.theme--documenter-dark .input[disabled]::-webkit-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark .select select::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark .input::-webkit-input-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .select select[disabled]:-moz-placeholder,html.theme--documenter-dark .textarea[disabled]:-moz-placeholder,html.theme--documenter-dark .input[disabled]:-moz-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .select select:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark .input:-moz-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .select select[disabled]:-ms-input-placeholder,html.theme--documenter-dark .textarea[disabled]:-ms-input-placeholder,html.theme--documenter-dark .input[disabled]:-ms-input-placeholder,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[disabled]:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark .select select:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark .textarea:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark .input:-ms-input-placeholder,fieldset[disabled] html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:rgba(255,255,255,0.3)}html.theme--documenter-dark .textarea,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{box-shadow:inset 0 0.0625em 0.125em rgba(10,10,10,0.05);max-width:100%;width:100%}html.theme--documenter-dark .textarea[readonly],html.theme--documenter-dark .input[readonly],html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input[readonly]{box-shadow:none}html.theme--documenter-dark .is-white.textarea,html.theme--documenter-dark .is-white.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-white{border-color:#fff}html.theme--documenter-dark .is-white.textarea:focus,html.theme--documenter-dark .is-white.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-white:focus,html.theme--documenter-dark .is-white.is-focused.textarea,html.theme--documenter-dark .is-white.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-white.textarea:active,html.theme--documenter-dark .is-white.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-white:active,html.theme--documenter-dark .is-white.is-active.textarea,html.theme--documenter-dark .is-white.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--documenter-dark .is-black.textarea,html.theme--documenter-dark .is-black.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-black{border-color:#0a0a0a}html.theme--documenter-dark .is-black.textarea:focus,html.theme--documenter-dark .is-black.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-black:focus,html.theme--documenter-dark .is-black.is-focused.textarea,html.theme--documenter-dark .is-black.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-black.textarea:active,html.theme--documenter-dark .is-black.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-black:active,html.theme--documenter-dark .is-black.is-active.textarea,html.theme--documenter-dark .is-black.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--documenter-dark .is-light.textarea,html.theme--documenter-dark .is-light.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-light{border-color:#ecf0f1}html.theme--documenter-dark .is-light.textarea:focus,html.theme--documenter-dark .is-light.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-light:focus,html.theme--documenter-dark .is-light.is-focused.textarea,html.theme--documenter-dark .is-light.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-light.textarea:active,html.theme--documenter-dark .is-light.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-light:active,html.theme--documenter-dark .is-light.is-active.textarea,html.theme--documenter-dark .is-light.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(236,240,241,0.25)}html.theme--documenter-dark .is-dark.textarea,html.theme--documenter-dark .content kbd.textarea,html.theme--documenter-dark .is-dark.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-dark,html.theme--documenter-dark .content kbd.input{border-color:#282f2f}html.theme--documenter-dark .is-dark.textarea:focus,html.theme--documenter-dark .content kbd.textarea:focus,html.theme--documenter-dark .is-dark.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-dark:focus,html.theme--documenter-dark .content kbd.input:focus,html.theme--documenter-dark .is-dark.is-focused.textarea,html.theme--documenter-dark .content kbd.is-focused.textarea,html.theme--documenter-dark .is-dark.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .content kbd.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search>input.is-focused,html.theme--documenter-dark .is-dark.textarea:active,html.theme--documenter-dark .content kbd.textarea:active,html.theme--documenter-dark .is-dark.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-dark:active,html.theme--documenter-dark .content kbd.input:active,html.theme--documenter-dark .is-dark.is-active.textarea,html.theme--documenter-dark .content kbd.is-active.textarea,html.theme--documenter-dark .is-dark.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--documenter-dark .content kbd.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar .content form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(40,47,47,0.25)}html.theme--documenter-dark .is-primary.textarea,html.theme--documenter-dark .docstring>section>a.textarea.docs-sourcelink,html.theme--documenter-dark .is-primary.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-primary,html.theme--documenter-dark .docstring>section>a.input.docs-sourcelink{border-color:#375a7f}html.theme--documenter-dark .is-primary.textarea:focus,html.theme--documenter-dark .docstring>section>a.textarea.docs-sourcelink:focus,html.theme--documenter-dark .is-primary.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-primary:focus,html.theme--documenter-dark .docstring>section>a.input.docs-sourcelink:focus,html.theme--documenter-dark .is-primary.is-focused.textarea,html.theme--documenter-dark .docstring>section>a.is-focused.textarea.docs-sourcelink,html.theme--documenter-dark .is-primary.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .docstring>section>a.is-focused.input.docs-sourcelink,html.theme--documenter-dark .is-primary.textarea:active,html.theme--documenter-dark .docstring>section>a.textarea.docs-sourcelink:active,html.theme--documenter-dark .is-primary.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-primary:active,html.theme--documenter-dark .docstring>section>a.input.docs-sourcelink:active,html.theme--documenter-dark .is-primary.is-active.textarea,html.theme--documenter-dark .docstring>section>a.is-active.textarea.docs-sourcelink,html.theme--documenter-dark .is-primary.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active,html.theme--documenter-dark .docstring>section>a.is-active.input.docs-sourcelink{box-shadow:0 0 0 0.125em rgba(55,90,127,0.25)}html.theme--documenter-dark .is-link.textarea,html.theme--documenter-dark .is-link.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-link{border-color:#1abc9c}html.theme--documenter-dark .is-link.textarea:focus,html.theme--documenter-dark .is-link.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-link:focus,html.theme--documenter-dark .is-link.is-focused.textarea,html.theme--documenter-dark .is-link.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-link.textarea:active,html.theme--documenter-dark .is-link.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-link:active,html.theme--documenter-dark .is-link.is-active.textarea,html.theme--documenter-dark .is-link.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .is-info.textarea,html.theme--documenter-dark .is-info.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-info{border-color:#024c7d}html.theme--documenter-dark .is-info.textarea:focus,html.theme--documenter-dark .is-info.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-info:focus,html.theme--documenter-dark .is-info.is-focused.textarea,html.theme--documenter-dark .is-info.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-info.textarea:active,html.theme--documenter-dark .is-info.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-info:active,html.theme--documenter-dark .is-info.is-active.textarea,html.theme--documenter-dark .is-info.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(2,76,125,0.25)}html.theme--documenter-dark .is-success.textarea,html.theme--documenter-dark .is-success.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-success{border-color:#008438}html.theme--documenter-dark .is-success.textarea:focus,html.theme--documenter-dark .is-success.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-success:focus,html.theme--documenter-dark .is-success.is-focused.textarea,html.theme--documenter-dark .is-success.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-success.textarea:active,html.theme--documenter-dark .is-success.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-success:active,html.theme--documenter-dark .is-success.is-active.textarea,html.theme--documenter-dark .is-success.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(0,132,56,0.25)}html.theme--documenter-dark .is-warning.textarea,html.theme--documenter-dark .is-warning.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-warning{border-color:#ad8100}html.theme--documenter-dark .is-warning.textarea:focus,html.theme--documenter-dark .is-warning.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-warning:focus,html.theme--documenter-dark .is-warning.is-focused.textarea,html.theme--documenter-dark .is-warning.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-warning.textarea:active,html.theme--documenter-dark .is-warning.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-warning:active,html.theme--documenter-dark .is-warning.is-active.textarea,html.theme--documenter-dark .is-warning.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(173,129,0,0.25)}html.theme--documenter-dark .is-danger.textarea,html.theme--documenter-dark .is-danger.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-danger{border-color:#9e1b0d}html.theme--documenter-dark .is-danger.textarea:focus,html.theme--documenter-dark .is-danger.input:focus,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-danger:focus,html.theme--documenter-dark .is-danger.is-focused.textarea,html.theme--documenter-dark .is-danger.is-focused.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-focused,html.theme--documenter-dark .is-danger.textarea:active,html.theme--documenter-dark .is-danger.input:active,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-danger:active,html.theme--documenter-dark .is-danger.is-active.textarea,html.theme--documenter-dark .is-danger.is-active.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(158,27,13,0.25)}html.theme--documenter-dark .is-small.textarea,html.theme--documenter-dark .is-small.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{border-radius:3px;font-size:.75rem}html.theme--documenter-dark .is-medium.textarea,html.theme--documenter-dark .is-medium.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-medium{font-size:1.25rem}html.theme--documenter-dark .is-large.textarea,html.theme--documenter-dark .is-large.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-large{font-size:1.5rem}html.theme--documenter-dark .is-fullwidth.textarea,html.theme--documenter-dark .is-fullwidth.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-fullwidth{display:block;width:100%}html.theme--documenter-dark .is-inline.textarea,html.theme--documenter-dark .is-inline.input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-inline{display:inline;width:auto}html.theme--documenter-dark .input.is-rounded,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{border-radius:9999px;padding-left:calc(calc(0.75em - 1px) + 0.375em);padding-right:calc(calc(0.75em - 1px) + 0.375em)}html.theme--documenter-dark .input.is-static,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-static{background-color:transparent;border-color:transparent;box-shadow:none;padding-left:0;padding-right:0}html.theme--documenter-dark .textarea{display:block;max-width:100%;min-width:100%;padding:calc(0.75em - 1px);resize:vertical}html.theme--documenter-dark .textarea:not([rows]){max-height:40em;min-height:8em}html.theme--documenter-dark .textarea[rows]{height:initial}html.theme--documenter-dark .textarea.has-fixed-size{resize:none}html.theme--documenter-dark .radio,html.theme--documenter-dark .checkbox{cursor:pointer;display:inline-block;line-height:1.25;position:relative}html.theme--documenter-dark .radio input,html.theme--documenter-dark .checkbox input{cursor:pointer}html.theme--documenter-dark .radio:hover,html.theme--documenter-dark .checkbox:hover{color:#8c9b9d}html.theme--documenter-dark .radio[disabled],html.theme--documenter-dark .checkbox[disabled],fieldset[disabled] html.theme--documenter-dark .radio,fieldset[disabled] html.theme--documenter-dark .checkbox,html.theme--documenter-dark .radio input[disabled],html.theme--documenter-dark .checkbox input[disabled]{color:#fff;cursor:not-allowed}html.theme--documenter-dark .radio+.radio{margin-left:.5em}html.theme--documenter-dark .select{display:inline-block;max-width:100%;position:relative;vertical-align:top}html.theme--documenter-dark .select:not(.is-multiple){height:2.5em}html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading)::after{border-color:#1abc9c;right:1.125em;z-index:4}html.theme--documenter-dark .select.is-rounded select,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.select select{border-radius:9999px;padding-left:1em}html.theme--documenter-dark .select select{cursor:pointer;display:block;font-size:1em;max-width:100%;outline:none}html.theme--documenter-dark .select select::-ms-expand{display:none}html.theme--documenter-dark .select select[disabled]:hover,fieldset[disabled] html.theme--documenter-dark .select select:hover{border-color:#282f2f}html.theme--documenter-dark .select select:not([multiple]){padding-right:2.5em}html.theme--documenter-dark .select select[multiple]{height:auto;padding:0}html.theme--documenter-dark .select select[multiple] option{padding:0.5em 1em}html.theme--documenter-dark .select:not(.is-multiple):not(.is-loading):hover::after{border-color:#8c9b9d}html.theme--documenter-dark .select.is-white:not(:hover)::after{border-color:#fff}html.theme--documenter-dark .select.is-white select{border-color:#fff}html.theme--documenter-dark .select.is-white select:hover,html.theme--documenter-dark .select.is-white select.is-hovered{border-color:#f2f2f2}html.theme--documenter-dark .select.is-white select:focus,html.theme--documenter-dark .select.is-white select.is-focused,html.theme--documenter-dark .select.is-white select:active,html.theme--documenter-dark .select.is-white select.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}html.theme--documenter-dark .select.is-black:not(:hover)::after{border-color:#0a0a0a}html.theme--documenter-dark .select.is-black select{border-color:#0a0a0a}html.theme--documenter-dark .select.is-black select:hover,html.theme--documenter-dark .select.is-black select.is-hovered{border-color:#000}html.theme--documenter-dark .select.is-black select:focus,html.theme--documenter-dark .select.is-black select.is-focused,html.theme--documenter-dark .select.is-black select:active,html.theme--documenter-dark .select.is-black select.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}html.theme--documenter-dark .select.is-light:not(:hover)::after{border-color:#ecf0f1}html.theme--documenter-dark .select.is-light select{border-color:#ecf0f1}html.theme--documenter-dark .select.is-light select:hover,html.theme--documenter-dark .select.is-light select.is-hovered{border-color:#dde4e6}html.theme--documenter-dark .select.is-light select:focus,html.theme--documenter-dark .select.is-light select.is-focused,html.theme--documenter-dark .select.is-light select:active,html.theme--documenter-dark .select.is-light select.is-active{box-shadow:0 0 0 0.125em rgba(236,240,241,0.25)}html.theme--documenter-dark .select.is-dark:not(:hover)::after,html.theme--documenter-dark .content kbd.select:not(:hover)::after{border-color:#282f2f}html.theme--documenter-dark .select.is-dark select,html.theme--documenter-dark .content kbd.select select{border-color:#282f2f}html.theme--documenter-dark .select.is-dark select:hover,html.theme--documenter-dark .content kbd.select select:hover,html.theme--documenter-dark .select.is-dark select.is-hovered,html.theme--documenter-dark .content kbd.select select.is-hovered{border-color:#1d2122}html.theme--documenter-dark .select.is-dark select:focus,html.theme--documenter-dark .content kbd.select select:focus,html.theme--documenter-dark .select.is-dark select.is-focused,html.theme--documenter-dark .content kbd.select select.is-focused,html.theme--documenter-dark .select.is-dark select:active,html.theme--documenter-dark .content kbd.select select:active,html.theme--documenter-dark .select.is-dark select.is-active,html.theme--documenter-dark .content kbd.select select.is-active{box-shadow:0 0 0 0.125em rgba(40,47,47,0.25)}html.theme--documenter-dark .select.is-primary:not(:hover)::after,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink:not(:hover)::after{border-color:#375a7f}html.theme--documenter-dark .select.is-primary select,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select{border-color:#375a7f}html.theme--documenter-dark .select.is-primary select:hover,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select:hover,html.theme--documenter-dark .select.is-primary select.is-hovered,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select.is-hovered{border-color:#2f4d6d}html.theme--documenter-dark .select.is-primary select:focus,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select:focus,html.theme--documenter-dark .select.is-primary select.is-focused,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select.is-focused,html.theme--documenter-dark .select.is-primary select:active,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select:active,html.theme--documenter-dark .select.is-primary select.is-active,html.theme--documenter-dark .docstring>section>a.select.docs-sourcelink select.is-active{box-shadow:0 0 0 0.125em rgba(55,90,127,0.25)}html.theme--documenter-dark .select.is-link:not(:hover)::after{border-color:#1abc9c}html.theme--documenter-dark .select.is-link select{border-color:#1abc9c}html.theme--documenter-dark .select.is-link select:hover,html.theme--documenter-dark .select.is-link select.is-hovered{border-color:#17a689}html.theme--documenter-dark .select.is-link select:focus,html.theme--documenter-dark .select.is-link select.is-focused,html.theme--documenter-dark .select.is-link select:active,html.theme--documenter-dark .select.is-link select.is-active{box-shadow:0 0 0 0.125em rgba(26,188,156,0.25)}html.theme--documenter-dark .select.is-info:not(:hover)::after{border-color:#024c7d}html.theme--documenter-dark .select.is-info select{border-color:#024c7d}html.theme--documenter-dark .select.is-info select:hover,html.theme--documenter-dark .select.is-info select.is-hovered{border-color:#023d64}html.theme--documenter-dark .select.is-info select:focus,html.theme--documenter-dark .select.is-info select.is-focused,html.theme--documenter-dark .select.is-info select:active,html.theme--documenter-dark .select.is-info select.is-active{box-shadow:0 0 0 0.125em rgba(2,76,125,0.25)}html.theme--documenter-dark .select.is-success:not(:hover)::after{border-color:#008438}html.theme--documenter-dark .select.is-success select{border-color:#008438}html.theme--documenter-dark .select.is-success select:hover,html.theme--documenter-dark .select.is-success select.is-hovered{border-color:#006b2d}html.theme--documenter-dark .select.is-success select:focus,html.theme--documenter-dark .select.is-success select.is-focused,html.theme--documenter-dark .select.is-success select:active,html.theme--documenter-dark .select.is-success select.is-active{box-shadow:0 0 0 0.125em rgba(0,132,56,0.25)}html.theme--documenter-dark .select.is-warning:not(:hover)::after{border-color:#ad8100}html.theme--documenter-dark .select.is-warning select{border-color:#ad8100}html.theme--documenter-dark .select.is-warning select:hover,html.theme--documenter-dark .select.is-warning select.is-hovered{border-color:#946e00}html.theme--documenter-dark .select.is-warning select:focus,html.theme--documenter-dark .select.is-warning select.is-focused,html.theme--documenter-dark .select.is-warning select:active,html.theme--documenter-dark .select.is-warning select.is-active{box-shadow:0 0 0 0.125em rgba(173,129,0,0.25)}html.theme--documenter-dark .select.is-danger:not(:hover)::after{border-color:#9e1b0d}html.theme--documenter-dark .select.is-danger select{border-color:#9e1b0d}html.theme--documenter-dark .select.is-danger select:hover,html.theme--documenter-dark .select.is-danger select.is-hovered{border-color:#86170b}html.theme--documenter-dark .select.is-danger select:focus,html.theme--documenter-dark .select.is-danger select.is-focused,html.theme--documenter-dark .select.is-danger select:active,html.theme--documenter-dark .select.is-danger select.is-active{box-shadow:0 0 0 0.125em rgba(158,27,13,0.25)}html.theme--documenter-dark .select.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.select{border-radius:3px;font-size:.75rem}html.theme--documenter-dark .select.is-medium{font-size:1.25rem}html.theme--documenter-dark .select.is-large{font-size:1.5rem}html.theme--documenter-dark .select.is-disabled::after{border-color:#fff !important;opacity:0.5}html.theme--documenter-dark .select.is-fullwidth{width:100%}html.theme--documenter-dark .select.is-fullwidth select{width:100%}html.theme--documenter-dark .select.is-loading::after{margin-top:0;position:absolute;right:.625em;top:0.625em;transform:none}html.theme--documenter-dark .select.is-loading.is-small:after,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}html.theme--documenter-dark .select.is-loading.is-medium:after{font-size:1.25rem}html.theme--documenter-dark .select.is-loading.is-large:after{font-size:1.5rem}html.theme--documenter-dark .file{align-items:stretch;display:flex;justify-content:flex-start;position:relative}html.theme--documenter-dark .file.is-white .file-cta{background-color:#fff;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .file.is-white:hover .file-cta,html.theme--documenter-dark .file.is-white.is-hovered .file-cta{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .file.is-white:focus .file-cta,html.theme--documenter-dark .file.is-white.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,255,255,0.25);color:#0a0a0a}html.theme--documenter-dark .file.is-white:active .file-cta,html.theme--documenter-dark .file.is-white.is-active .file-cta{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}html.theme--documenter-dark .file.is-black .file-cta{background-color:#0a0a0a;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-black:hover .file-cta,html.theme--documenter-dark .file.is-black.is-hovered .file-cta{background-color:#040404;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-black:focus .file-cta,html.theme--documenter-dark .file.is-black.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(10,10,10,0.25);color:#fff}html.theme--documenter-dark .file.is-black:active .file-cta,html.theme--documenter-dark .file.is-black.is-active .file-cta{background-color:#000;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-light .file-cta{background-color:#ecf0f1;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-light:hover .file-cta,html.theme--documenter-dark .file.is-light.is-hovered .file-cta{background-color:#e5eaec;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-light:focus .file-cta,html.theme--documenter-dark .file.is-light.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(236,240,241,0.25);color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-light:active .file-cta,html.theme--documenter-dark .file.is-light.is-active .file-cta{background-color:#dde4e6;border-color:transparent;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .file.is-dark .file-cta,html.theme--documenter-dark .content kbd.file .file-cta{background-color:#282f2f;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-dark:hover .file-cta,html.theme--documenter-dark .content kbd.file:hover .file-cta,html.theme--documenter-dark .file.is-dark.is-hovered .file-cta,html.theme--documenter-dark .content kbd.file.is-hovered .file-cta{background-color:#232829;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-dark:focus .file-cta,html.theme--documenter-dark .content kbd.file:focus .file-cta,html.theme--documenter-dark .file.is-dark.is-focused .file-cta,html.theme--documenter-dark .content kbd.file.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(40,47,47,0.25);color:#fff}html.theme--documenter-dark .file.is-dark:active .file-cta,html.theme--documenter-dark .content kbd.file:active .file-cta,html.theme--documenter-dark .file.is-dark.is-active .file-cta,html.theme--documenter-dark .content kbd.file.is-active .file-cta{background-color:#1d2122;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-primary .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink .file-cta{background-color:#375a7f;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-primary:hover .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink:hover .file-cta,html.theme--documenter-dark .file.is-primary.is-hovered .file-cta,html.theme--documenter-dark .docstring>section>a.file.is-hovered.docs-sourcelink .file-cta{background-color:#335476;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-primary:focus .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink:focus .file-cta,html.theme--documenter-dark .file.is-primary.is-focused .file-cta,html.theme--documenter-dark .docstring>section>a.file.is-focused.docs-sourcelink .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(55,90,127,0.25);color:#fff}html.theme--documenter-dark .file.is-primary:active .file-cta,html.theme--documenter-dark .docstring>section>a.file.docs-sourcelink:active .file-cta,html.theme--documenter-dark .file.is-primary.is-active .file-cta,html.theme--documenter-dark .docstring>section>a.file.is-active.docs-sourcelink .file-cta{background-color:#2f4d6d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-link .file-cta{background-color:#1abc9c;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-link:hover .file-cta,html.theme--documenter-dark .file.is-link.is-hovered .file-cta{background-color:#18b193;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-link:focus .file-cta,html.theme--documenter-dark .file.is-link.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(26,188,156,0.25);color:#fff}html.theme--documenter-dark .file.is-link:active .file-cta,html.theme--documenter-dark .file.is-link.is-active .file-cta{background-color:#17a689;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-info .file-cta{background-color:#024c7d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-info:hover .file-cta,html.theme--documenter-dark .file.is-info.is-hovered .file-cta{background-color:#024470;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-info:focus .file-cta,html.theme--documenter-dark .file.is-info.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(2,76,125,0.25);color:#fff}html.theme--documenter-dark .file.is-info:active .file-cta,html.theme--documenter-dark .file.is-info.is-active .file-cta{background-color:#023d64;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-success .file-cta{background-color:#008438;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-success:hover .file-cta,html.theme--documenter-dark .file.is-success.is-hovered .file-cta{background-color:#073;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-success:focus .file-cta,html.theme--documenter-dark .file.is-success.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(0,132,56,0.25);color:#fff}html.theme--documenter-dark .file.is-success:active .file-cta,html.theme--documenter-dark .file.is-success.is-active .file-cta{background-color:#006b2d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-warning .file-cta{background-color:#ad8100;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-warning:hover .file-cta,html.theme--documenter-dark .file.is-warning.is-hovered .file-cta{background-color:#a07700;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-warning:focus .file-cta,html.theme--documenter-dark .file.is-warning.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(173,129,0,0.25);color:#fff}html.theme--documenter-dark .file.is-warning:active .file-cta,html.theme--documenter-dark .file.is-warning.is-active .file-cta{background-color:#946e00;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-danger .file-cta{background-color:#9e1b0d;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-danger:hover .file-cta,html.theme--documenter-dark .file.is-danger.is-hovered .file-cta{background-color:#92190c;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-danger:focus .file-cta,html.theme--documenter-dark .file.is-danger.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(158,27,13,0.25);color:#fff}html.theme--documenter-dark .file.is-danger:active .file-cta,html.theme--documenter-dark .file.is-danger.is-active .file-cta{background-color:#86170b;border-color:transparent;color:#fff}html.theme--documenter-dark .file.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.file{font-size:.75rem}html.theme--documenter-dark .file.is-normal{font-size:1rem}html.theme--documenter-dark .file.is-medium{font-size:1.25rem}html.theme--documenter-dark .file.is-medium .file-icon .fa{font-size:21px}html.theme--documenter-dark .file.is-large{font-size:1.5rem}html.theme--documenter-dark .file.is-large .file-icon .fa{font-size:28px}html.theme--documenter-dark .file.has-name .file-cta{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--documenter-dark .file.has-name .file-name{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--documenter-dark .file.has-name.is-empty .file-cta{border-radius:.4em}html.theme--documenter-dark .file.has-name.is-empty .file-name{display:none}html.theme--documenter-dark .file.is-boxed .file-label{flex-direction:column}html.theme--documenter-dark .file.is-boxed .file-cta{flex-direction:column;height:auto;padding:1em 3em}html.theme--documenter-dark .file.is-boxed .file-name{border-width:0 1px 1px}html.theme--documenter-dark .file.is-boxed .file-icon{height:1.5em;width:1.5em}html.theme--documenter-dark .file.is-boxed .file-icon .fa{font-size:21px}html.theme--documenter-dark .file.is-boxed.is-small .file-icon .fa,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-boxed .file-icon .fa{font-size:14px}html.theme--documenter-dark .file.is-boxed.is-medium .file-icon .fa{font-size:28px}html.theme--documenter-dark .file.is-boxed.is-large .file-icon .fa{font-size:35px}html.theme--documenter-dark .file.is-boxed.has-name .file-cta{border-radius:.4em .4em 0 0}html.theme--documenter-dark .file.is-boxed.has-name .file-name{border-radius:0 0 .4em .4em;border-width:0 1px 1px}html.theme--documenter-dark .file.is-centered{justify-content:center}html.theme--documenter-dark .file.is-fullwidth .file-label{width:100%}html.theme--documenter-dark .file.is-fullwidth .file-name{flex-grow:1;max-width:none}html.theme--documenter-dark .file.is-right{justify-content:flex-end}html.theme--documenter-dark .file.is-right .file-cta{border-radius:0 .4em .4em 0}html.theme--documenter-dark .file.is-right .file-name{border-radius:.4em 0 0 .4em;border-width:1px 0 1px 1px;order:-1}html.theme--documenter-dark .file-label{align-items:stretch;display:flex;cursor:pointer;justify-content:flex-start;overflow:hidden;position:relative}html.theme--documenter-dark .file-label:hover .file-cta{background-color:#232829;color:#f2f2f2}html.theme--documenter-dark .file-label:hover .file-name{border-color:#596668}html.theme--documenter-dark .file-label:active .file-cta{background-color:#1d2122;color:#f2f2f2}html.theme--documenter-dark .file-label:active .file-name{border-color:#535f61}html.theme--documenter-dark .file-input{height:100%;left:0;opacity:0;outline:none;position:absolute;top:0;width:100%}html.theme--documenter-dark .file-cta,html.theme--documenter-dark .file-name{border-color:#5e6d6f;border-radius:.4em;font-size:1em;padding-left:1em;padding-right:1em;white-space:nowrap}html.theme--documenter-dark .file-cta{background-color:#282f2f;color:#fff}html.theme--documenter-dark .file-name{border-color:#5e6d6f;border-style:solid;border-width:1px 1px 1px 0;display:block;max-width:16em;overflow:hidden;text-align:inherit;text-overflow:ellipsis}html.theme--documenter-dark .file-icon{align-items:center;display:flex;height:1em;justify-content:center;margin-right:.5em;width:1em}html.theme--documenter-dark .file-icon .fa{font-size:14px}html.theme--documenter-dark .label{color:#f2f2f2;display:block;font-size:1rem;font-weight:700}html.theme--documenter-dark .label:not(:last-child){margin-bottom:0.5em}html.theme--documenter-dark .label.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.label{font-size:.75rem}html.theme--documenter-dark .label.is-medium{font-size:1.25rem}html.theme--documenter-dark .label.is-large{font-size:1.5rem}html.theme--documenter-dark .help{display:block;font-size:.75rem;margin-top:0.25rem}html.theme--documenter-dark .help.is-white{color:#fff}html.theme--documenter-dark .help.is-black{color:#0a0a0a}html.theme--documenter-dark .help.is-light{color:#ecf0f1}html.theme--documenter-dark .help.is-dark,html.theme--documenter-dark .content kbd.help{color:#282f2f}html.theme--documenter-dark .help.is-primary,html.theme--documenter-dark .docstring>section>a.help.docs-sourcelink{color:#375a7f}html.theme--documenter-dark .help.is-link{color:#1abc9c}html.theme--documenter-dark .help.is-info{color:#024c7d}html.theme--documenter-dark .help.is-success{color:#008438}html.theme--documenter-dark .help.is-warning{color:#ad8100}html.theme--documenter-dark .help.is-danger{color:#9e1b0d}html.theme--documenter-dark .field:not(:last-child){margin-bottom:0.75rem}html.theme--documenter-dark .field.has-addons{display:flex;justify-content:flex-start}html.theme--documenter-dark .field.has-addons .control:not(:last-child){margin-right:-1px}html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .button,html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .input,html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:not(:first-child):not(:last-child) form.docs-search>input,html.theme--documenter-dark .field.has-addons .control:not(:first-child):not(:last-child) .select select{border-radius:0}html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .button,html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .input,html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:first-child:not(:only-child) form.docs-search>input,html.theme--documenter-dark .field.has-addons .control:first-child:not(:only-child) .select select{border-bottom-right-radius:0;border-top-right-radius:0}html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .button,html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .input,html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control:last-child:not(:only-child) form.docs-search>input,html.theme--documenter-dark .field.has-addons .control:last-child:not(:only-child) .select select{border-bottom-left-radius:0;border-top-left-radius:0}html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .button.is-hovered:not([disabled]),html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .input.is-hovered:not([disabled]),html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-hovered:not([disabled]),html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-hovered:not([disabled]),html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .select select.is-hovered:not([disabled]){z-index:2}html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control .button.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control .button.is-active:not([disabled]),html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control .input.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]),html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control .input.is-active:not([disabled]),html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]),html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]),html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):focus,html.theme--documenter-dark .field.has-addons .control .select select.is-focused:not([disabled]),html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):active,html.theme--documenter-dark .field.has-addons .control .select select.is-active:not([disabled]){z-index:3}html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control .button.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .button:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control .button.is-active:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus:hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control .input.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]):hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .input:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active:hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control .input.is-active:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]):hover,html.theme--documenter-dark #documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):focus:hover,html.theme--documenter-dark .field.has-addons .control .select select.is-focused:not([disabled]):hover,html.theme--documenter-dark .field.has-addons .control .select select:not([disabled]):active:hover,html.theme--documenter-dark .field.has-addons .control .select select.is-active:not([disabled]):hover{z-index:4}html.theme--documenter-dark .field.has-addons .control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .field.has-addons.has-addons-centered{justify-content:center}html.theme--documenter-dark .field.has-addons.has-addons-right{justify-content:flex-end}html.theme--documenter-dark .field.has-addons.has-addons-fullwidth .control{flex-grow:1;flex-shrink:0}html.theme--documenter-dark .field.is-grouped{display:flex;justify-content:flex-start}html.theme--documenter-dark .field.is-grouped>.control{flex-shrink:0}html.theme--documenter-dark .field.is-grouped>.control:not(:last-child){margin-bottom:0;margin-right:.75rem}html.theme--documenter-dark .field.is-grouped>.control.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .field.is-grouped.is-grouped-centered{justify-content:center}html.theme--documenter-dark .field.is-grouped.is-grouped-right{justify-content:flex-end}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline{flex-wrap:wrap}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline>.control:last-child,html.theme--documenter-dark .field.is-grouped.is-grouped-multiline>.control:not(:last-child){margin-bottom:0.75rem}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline:last-child{margin-bottom:-0.75rem}html.theme--documenter-dark .field.is-grouped.is-grouped-multiline:not(:last-child){margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--documenter-dark .field.is-horizontal{display:flex}}html.theme--documenter-dark .field-label .label{font-size:inherit}@media screen and (max-width: 768px){html.theme--documenter-dark .field-label{margin-bottom:0.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .field-label{flex-basis:0;flex-grow:1;flex-shrink:0;margin-right:1.5rem;text-align:right}html.theme--documenter-dark .field-label.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.field-label{font-size:.75rem;padding-top:0.375em}html.theme--documenter-dark .field-label.is-normal{padding-top:0.375em}html.theme--documenter-dark .field-label.is-medium{font-size:1.25rem;padding-top:0.375em}html.theme--documenter-dark .field-label.is-large{font-size:1.5rem;padding-top:0.375em}}html.theme--documenter-dark .field-body .field .field{margin-bottom:0}@media screen and (min-width: 769px),print{html.theme--documenter-dark .field-body{display:flex;flex-basis:0;flex-grow:5;flex-shrink:1}html.theme--documenter-dark .field-body .field{margin-bottom:0}html.theme--documenter-dark .field-body>.field{flex-shrink:1}html.theme--documenter-dark .field-body>.field:not(.is-narrow){flex-grow:1}html.theme--documenter-dark .field-body>.field:not(:last-child){margin-right:.75rem}}html.theme--documenter-dark .control{box-sizing:border-box;clear:both;font-size:1rem;position:relative;text-align:inherit}html.theme--documenter-dark .control.has-icons-left .input:focus~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input:focus~.icon,html.theme--documenter-dark .control.has-icons-left .select:focus~.icon,html.theme--documenter-dark .control.has-icons-right .input:focus~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input:focus~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input:focus~.icon,html.theme--documenter-dark .control.has-icons-right .select:focus~.icon{color:#282f2f}html.theme--documenter-dark .control.has-icons-left .input.is-small~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input~.icon,html.theme--documenter-dark .control.has-icons-left .select.is-small~.icon,html.theme--documenter-dark .control.has-icons-right .input.is-small~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input~.icon,html.theme--documenter-dark .control.has-icons-right .select.is-small~.icon{font-size:.75rem}html.theme--documenter-dark .control.has-icons-left .input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-left .select.is-medium~.icon,html.theme--documenter-dark .control.has-icons-right .input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-medium~.icon,html.theme--documenter-dark .control.has-icons-right .select.is-medium~.icon{font-size:1.25rem}html.theme--documenter-dark .control.has-icons-left .input.is-large~.icon,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-large~.icon,html.theme--documenter-dark .control.has-icons-left .select.is-large~.icon,html.theme--documenter-dark .control.has-icons-right .input.is-large~.icon,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-large~.icon,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-large~.icon,html.theme--documenter-dark .control.has-icons-right .select.is-large~.icon{font-size:1.5rem}html.theme--documenter-dark .control.has-icons-left .icon,html.theme--documenter-dark .control.has-icons-right .icon{color:#5e6d6f;height:2.5em;pointer-events:none;position:absolute;top:0;width:2.5em;z-index:4}html.theme--documenter-dark .control.has-icons-left .input,html.theme--documenter-dark .control.has-icons-left #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-left form.docs-search>input,html.theme--documenter-dark .control.has-icons-left .select select{padding-left:2.5em}html.theme--documenter-dark .control.has-icons-left .icon.is-left{left:0}html.theme--documenter-dark .control.has-icons-right .input,html.theme--documenter-dark .control.has-icons-right #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .control.has-icons-right form.docs-search>input,html.theme--documenter-dark .control.has-icons-right .select select{padding-right:2.5em}html.theme--documenter-dark .control.has-icons-right .icon.is-right{right:0}html.theme--documenter-dark .control.is-loading::after{position:absolute !important;right:.625em;top:0.625em;z-index:4}html.theme--documenter-dark .control.is-loading.is-small:after,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}html.theme--documenter-dark .control.is-loading.is-medium:after{font-size:1.25rem}html.theme--documenter-dark .control.is-loading.is-large:after{font-size:1.5rem}html.theme--documenter-dark .breadcrumb{font-size:1rem;white-space:nowrap}html.theme--documenter-dark .breadcrumb a{align-items:center;color:#1abc9c;display:flex;justify-content:center;padding:0 .75em}html.theme--documenter-dark .breadcrumb a:hover{color:#1dd2af}html.theme--documenter-dark .breadcrumb li{align-items:center;display:flex}html.theme--documenter-dark .breadcrumb li:first-child a{padding-left:0}html.theme--documenter-dark .breadcrumb li.is-active a{color:#f2f2f2;cursor:default;pointer-events:none}html.theme--documenter-dark .breadcrumb li+li::before{color:#8c9b9d;content:"\0002f"}html.theme--documenter-dark .breadcrumb ul,html.theme--documenter-dark .breadcrumb ol{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:flex-start}html.theme--documenter-dark .breadcrumb .icon:first-child{margin-right:.5em}html.theme--documenter-dark .breadcrumb .icon:last-child{margin-left:.5em}html.theme--documenter-dark .breadcrumb.is-centered ol,html.theme--documenter-dark .breadcrumb.is-centered ul{justify-content:center}html.theme--documenter-dark .breadcrumb.is-right ol,html.theme--documenter-dark .breadcrumb.is-right ul{justify-content:flex-end}html.theme--documenter-dark .breadcrumb.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.breadcrumb{font-size:.75rem}html.theme--documenter-dark .breadcrumb.is-medium{font-size:1.25rem}html.theme--documenter-dark .breadcrumb.is-large{font-size:1.5rem}html.theme--documenter-dark .breadcrumb.has-arrow-separator li+li::before{content:"\02192"}html.theme--documenter-dark .breadcrumb.has-bullet-separator li+li::before{content:"\02022"}html.theme--documenter-dark .breadcrumb.has-dot-separator li+li::before{content:"\000b7"}html.theme--documenter-dark .breadcrumb.has-succeeds-separator li+li::before{content:"\0227B"}html.theme--documenter-dark .card{background-color:#fff;border-radius:.25rem;box-shadow:#171717;color:#fff;max-width:100%;position:relative}html.theme--documenter-dark .card-footer:first-child,html.theme--documenter-dark .card-content:first-child,html.theme--documenter-dark .card-header:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}html.theme--documenter-dark .card-footer:last-child,html.theme--documenter-dark .card-content:last-child,html.theme--documenter-dark .card-header:last-child{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}html.theme--documenter-dark .card-header{background-color:rgba(0,0,0,0);align-items:stretch;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);display:flex}html.theme--documenter-dark .card-header-title{align-items:center;color:#f2f2f2;display:flex;flex-grow:1;font-weight:700;padding:0.75rem 1rem}html.theme--documenter-dark .card-header-title.is-centered{justify-content:center}html.theme--documenter-dark .card-header-icon{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0;align-items:center;cursor:pointer;display:flex;justify-content:center;padding:0.75rem 1rem}html.theme--documenter-dark .card-image{display:block;position:relative}html.theme--documenter-dark .card-image:first-child img{border-top-left-radius:.25rem;border-top-right-radius:.25rem}html.theme--documenter-dark .card-image:last-child img{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}html.theme--documenter-dark .card-content{background-color:rgba(0,0,0,0);padding:1.5rem}html.theme--documenter-dark .card-footer{background-color:rgba(0,0,0,0);border-top:1px solid #ededed;align-items:stretch;display:flex}html.theme--documenter-dark .card-footer-item{align-items:center;display:flex;flex-basis:0;flex-grow:1;flex-shrink:0;justify-content:center;padding:.75rem}html.theme--documenter-dark .card-footer-item:not(:last-child){border-right:1px solid #ededed}html.theme--documenter-dark .card .media:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .dropdown{display:inline-flex;position:relative;vertical-align:top}html.theme--documenter-dark .dropdown.is-active .dropdown-menu,html.theme--documenter-dark .dropdown.is-hoverable:hover .dropdown-menu{display:block}html.theme--documenter-dark .dropdown.is-right .dropdown-menu{left:auto;right:0}html.theme--documenter-dark .dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:initial;top:auto}html.theme--documenter-dark .dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:20}html.theme--documenter-dark .dropdown-content{background-color:#282f2f;border-radius:.4em;box-shadow:#171717;padding-bottom:.5rem;padding-top:.5rem}html.theme--documenter-dark .dropdown-item{color:#fff;display:block;font-size:0.875rem;line-height:1.5;padding:0.375rem 1rem;position:relative}html.theme--documenter-dark a.dropdown-item,html.theme--documenter-dark button.dropdown-item{padding-right:3rem;text-align:inherit;white-space:nowrap;width:100%}html.theme--documenter-dark a.dropdown-item:hover,html.theme--documenter-dark button.dropdown-item:hover{background-color:#282f2f;color:#0a0a0a}html.theme--documenter-dark a.dropdown-item.is-active,html.theme--documenter-dark button.dropdown-item.is-active{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .dropdown-divider{background-color:#ededed;border:none;display:block;height:1px;margin:0.5rem 0}html.theme--documenter-dark .level{align-items:center;justify-content:space-between}html.theme--documenter-dark .level code{border-radius:.4em}html.theme--documenter-dark .level img{display:inline-block;vertical-align:top}html.theme--documenter-dark .level.is-mobile{display:flex}html.theme--documenter-dark .level.is-mobile .level-left,html.theme--documenter-dark .level.is-mobile .level-right{display:flex}html.theme--documenter-dark .level.is-mobile .level-left+.level-right{margin-top:0}html.theme--documenter-dark .level.is-mobile .level-item:not(:last-child){margin-bottom:0;margin-right:.75rem}html.theme--documenter-dark .level.is-mobile .level-item:not(.is-narrow){flex-grow:1}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level{display:flex}html.theme--documenter-dark .level>.level-item:not(.is-narrow){flex-grow:1}}html.theme--documenter-dark .level-item{align-items:center;display:flex;flex-basis:auto;flex-grow:0;flex-shrink:0;justify-content:center}html.theme--documenter-dark .level-item .title,html.theme--documenter-dark .level-item .subtitle{margin-bottom:0}@media screen and (max-width: 768px){html.theme--documenter-dark .level-item:not(:last-child){margin-bottom:.75rem}}html.theme--documenter-dark .level-left,html.theme--documenter-dark .level-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--documenter-dark .level-left .level-item.is-flexible,html.theme--documenter-dark .level-right .level-item.is-flexible{flex-grow:1}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level-left .level-item:not(:last-child),html.theme--documenter-dark .level-right .level-item:not(:last-child){margin-right:.75rem}}html.theme--documenter-dark .level-left{align-items:center;justify-content:flex-start}@media screen and (max-width: 768px){html.theme--documenter-dark .level-left+.level-right{margin-top:1.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level-left{display:flex}}html.theme--documenter-dark .level-right{align-items:center;justify-content:flex-end}@media screen and (min-width: 769px),print{html.theme--documenter-dark .level-right{display:flex}}html.theme--documenter-dark .media{align-items:flex-start;display:flex;text-align:inherit}html.theme--documenter-dark .media .content:not(:last-child){margin-bottom:.75rem}html.theme--documenter-dark .media .media{border-top:1px solid rgba(94,109,111,0.5);display:flex;padding-top:.75rem}html.theme--documenter-dark .media .media .content:not(:last-child),html.theme--documenter-dark .media .media .control:not(:last-child){margin-bottom:.5rem}html.theme--documenter-dark .media .media .media{padding-top:.5rem}html.theme--documenter-dark .media .media .media+.media{margin-top:.5rem}html.theme--documenter-dark .media+.media{border-top:1px solid rgba(94,109,111,0.5);margin-top:1rem;padding-top:1rem}html.theme--documenter-dark .media.is-large+.media{margin-top:1.5rem;padding-top:1.5rem}html.theme--documenter-dark .media-left,html.theme--documenter-dark .media-right{flex-basis:auto;flex-grow:0;flex-shrink:0}html.theme--documenter-dark .media-left{margin-right:1rem}html.theme--documenter-dark .media-right{margin-left:1rem}html.theme--documenter-dark .media-content{flex-basis:auto;flex-grow:1;flex-shrink:1;text-align:inherit}@media screen and (max-width: 768px){html.theme--documenter-dark .media-content{overflow-x:auto}}html.theme--documenter-dark .menu{font-size:1rem}html.theme--documenter-dark .menu.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.menu{font-size:.75rem}html.theme--documenter-dark .menu.is-medium{font-size:1.25rem}html.theme--documenter-dark .menu.is-large{font-size:1.5rem}html.theme--documenter-dark .menu-list{line-height:1.25}html.theme--documenter-dark .menu-list a{border-radius:3px;color:#fff;display:block;padding:0.5em 0.75em}html.theme--documenter-dark .menu-list a:hover{background-color:#282f2f;color:#f2f2f2}html.theme--documenter-dark .menu-list a.is-active{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .menu-list li ul{border-left:1px solid #5e6d6f;margin:.75em;padding-left:.75em}html.theme--documenter-dark .menu-label{color:#fff;font-size:.75em;letter-spacing:.1em;text-transform:uppercase}html.theme--documenter-dark .menu-label:not(:first-child){margin-top:1em}html.theme--documenter-dark .menu-label:not(:last-child){margin-bottom:1em}html.theme--documenter-dark .message{background-color:#282f2f;border-radius:.4em;font-size:1rem}html.theme--documenter-dark .message strong{color:currentColor}html.theme--documenter-dark .message a:not(.button):not(.tag):not(.dropdown-item){color:currentColor;text-decoration:underline}html.theme--documenter-dark .message.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.message{font-size:.75rem}html.theme--documenter-dark .message.is-medium{font-size:1.25rem}html.theme--documenter-dark .message.is-large{font-size:1.5rem}html.theme--documenter-dark .message.is-white{background-color:#fff}html.theme--documenter-dark .message.is-white .message-header{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .message.is-white .message-body{border-color:#fff}html.theme--documenter-dark .message.is-black{background-color:#fafafa}html.theme--documenter-dark .message.is-black .message-header{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .message.is-black .message-body{border-color:#0a0a0a}html.theme--documenter-dark .message.is-light{background-color:#f9fafb}html.theme--documenter-dark .message.is-light .message-header{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .message.is-light .message-body{border-color:#ecf0f1}html.theme--documenter-dark .message.is-dark,html.theme--documenter-dark .content kbd.message{background-color:#f9fafa}html.theme--documenter-dark .message.is-dark .message-header,html.theme--documenter-dark .content kbd.message .message-header{background-color:#282f2f;color:#fff}html.theme--documenter-dark .message.is-dark .message-body,html.theme--documenter-dark .content kbd.message .message-body{border-color:#282f2f}html.theme--documenter-dark .message.is-primary,html.theme--documenter-dark .docstring>section>a.message.docs-sourcelink{background-color:#f1f5f9}html.theme--documenter-dark .message.is-primary .message-header,html.theme--documenter-dark .docstring>section>a.message.docs-sourcelink .message-header{background-color:#375a7f;color:#fff}html.theme--documenter-dark .message.is-primary .message-body,html.theme--documenter-dark .docstring>section>a.message.docs-sourcelink .message-body{border-color:#375a7f;color:#4d7eb2}html.theme--documenter-dark .message.is-link{background-color:#edfdf9}html.theme--documenter-dark .message.is-link .message-header{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .message.is-link .message-body{border-color:#1abc9c;color:#15987e}html.theme--documenter-dark .message.is-info{background-color:#ebf7ff}html.theme--documenter-dark .message.is-info .message-header{background-color:#024c7d;color:#fff}html.theme--documenter-dark .message.is-info .message-body{border-color:#024c7d;color:#0e9dfb}html.theme--documenter-dark .message.is-success{background-color:#ebfff3}html.theme--documenter-dark .message.is-success .message-header{background-color:#008438;color:#fff}html.theme--documenter-dark .message.is-success .message-body{border-color:#008438;color:#00eb64}html.theme--documenter-dark .message.is-warning{background-color:#fffaeb}html.theme--documenter-dark .message.is-warning .message-header{background-color:#ad8100;color:#fff}html.theme--documenter-dark .message.is-warning .message-body{border-color:#ad8100;color:#d19c00}html.theme--documenter-dark .message.is-danger{background-color:#fdeeec}html.theme--documenter-dark .message.is-danger .message-header{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .message.is-danger .message-body{border-color:#9e1b0d;color:#ec311d}html.theme--documenter-dark .message-header{align-items:center;background-color:#fff;border-radius:.4em .4em 0 0;color:rgba(0,0,0,0.7);display:flex;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.75em 1em;position:relative}html.theme--documenter-dark .message-header .delete{flex-grow:0;flex-shrink:0;margin-left:.75em}html.theme--documenter-dark .message-header+.message-body{border-width:0;border-top-left-radius:0;border-top-right-radius:0}html.theme--documenter-dark .message-body{border-color:#5e6d6f;border-radius:.4em;border-style:solid;border-width:0 0 0 4px;color:#fff;padding:1.25em 1.5em}html.theme--documenter-dark .message-body code,html.theme--documenter-dark .message-body pre{background-color:#fff}html.theme--documenter-dark .message-body pre code{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .modal{align-items:center;display:none;flex-direction:column;justify-content:center;overflow:hidden;position:fixed;z-index:40}html.theme--documenter-dark .modal.is-active{display:flex}html.theme--documenter-dark .modal-background{background-color:rgba(10,10,10,0.86)}html.theme--documenter-dark .modal-content,html.theme--documenter-dark .modal-card{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width: 769px){html.theme--documenter-dark .modal-content,html.theme--documenter-dark .modal-card{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}html.theme--documenter-dark .modal-close{background:none;height:40px;position:fixed;right:20px;top:20px;width:40px}html.theme--documenter-dark .modal-card{display:flex;flex-direction:column;max-height:calc(100vh - 40px);overflow:hidden;-ms-overflow-y:visible}html.theme--documenter-dark .modal-card-head,html.theme--documenter-dark .modal-card-foot{align-items:center;background-color:#282f2f;display:flex;flex-shrink:0;justify-content:flex-start;padding:20px;position:relative}html.theme--documenter-dark .modal-card-head{border-bottom:1px solid #5e6d6f;border-top-left-radius:8px;border-top-right-radius:8px}html.theme--documenter-dark .modal-card-title{color:#f2f2f2;flex-grow:1;flex-shrink:0;font-size:1.5rem;line-height:1}html.theme--documenter-dark .modal-card-foot{border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid #5e6d6f}html.theme--documenter-dark .modal-card-foot .button:not(:last-child){margin-right:.5em}html.theme--documenter-dark .modal-card-body{-webkit-overflow-scrolling:touch;background-color:#fff;flex-grow:1;flex-shrink:1;overflow:auto;padding:20px}html.theme--documenter-dark .navbar{background-color:#375a7f;min-height:4rem;position:relative;z-index:30}html.theme--documenter-dark .navbar.is-white{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link{color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-white .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-white .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-brand .navbar-link::after{border-color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-burger{color:#0a0a0a}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-white .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-white .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link{color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-white .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-white .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-white .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-white .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-white .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-white .navbar-end .navbar-link::after{border-color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .navbar.is-white .navbar-dropdown a.navbar-item.is-active{background-color:#fff;color:#0a0a0a}}html.theme--documenter-dark .navbar.is-black{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-black .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-black .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link.is-active{background-color:#000;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-black .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-black .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-black .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-black .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-black .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-black .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-black .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link.is-active{background-color:#000;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-black .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link{background-color:#000;color:#fff}html.theme--documenter-dark .navbar.is-black .navbar-dropdown a.navbar-item.is-active{background-color:#0a0a0a;color:#fff}}html.theme--documenter-dark .navbar.is-light{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-light .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-light .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link.is-active{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-light .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-light .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-light .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-light .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-light .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-light .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-light .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link.is-active{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-light .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .navbar.is-light .navbar-dropdown a.navbar-item.is-active{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}}html.theme--documenter-dark .navbar.is-dark,html.theme--documenter-dark .content kbd.navbar{background-color:#282f2f;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-brand>.navbar-item,html.theme--documenter-dark .content kbd.navbar .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .content kbd.navbar .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-dark .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .content kbd.navbar .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-dark .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link:focus,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link:hover,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link.is-active{background-color:#1d2122;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-brand .navbar-link::after,html.theme--documenter-dark .content kbd.navbar .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-burger,html.theme--documenter-dark .content kbd.navbar .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-dark .navbar-start>.navbar-item,html.theme--documenter-dark .content kbd.navbar .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-dark .navbar-end>.navbar-item,html.theme--documenter-dark .content kbd.navbar .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .content kbd.navbar .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-dark .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .content kbd.navbar .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-dark .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link:focus,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link:hover,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .content kbd.navbar .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-dark .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .content kbd.navbar .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-dark .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link:focus,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link:hover,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link.is-active{background-color:#1d2122;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-start .navbar-link::after,html.theme--documenter-dark .content kbd.navbar .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-dark .navbar-end .navbar-link::after,html.theme--documenter-dark .content kbd.navbar .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link,html.theme--documenter-dark .content kbd.navbar .navbar-item.has-dropdown.is-active .navbar-link{background-color:#1d2122;color:#fff}html.theme--documenter-dark .navbar.is-dark .navbar-dropdown a.navbar-item.is-active,html.theme--documenter-dark .content kbd.navbar .navbar-dropdown a.navbar-item.is-active{background-color:#282f2f;color:#fff}}html.theme--documenter-dark .navbar.is-primary,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink{background-color:#375a7f;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-brand>.navbar-item,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-primary .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-primary .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link.is-active{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-brand .navbar-link::after,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-burger,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-primary .navbar-start>.navbar-item,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-primary .navbar-end>.navbar-item,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-primary .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-primary .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-primary .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-primary .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link:focus,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link.is-active{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-start .navbar-link::after,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-primary .navbar-end .navbar-link::after,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown.is-active .navbar-link{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#375a7f;color:#fff}}html.theme--documenter-dark .navbar.is-link{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-link .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-link .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link.is-active{background-color:#17a689;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-link .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-link .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-link .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-link .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-link .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-link .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-link .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link.is-active{background-color:#17a689;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-link .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link{background-color:#17a689;color:#fff}html.theme--documenter-dark .navbar.is-link .navbar-dropdown a.navbar-item.is-active{background-color:#1abc9c;color:#fff}}html.theme--documenter-dark .navbar.is-info{background-color:#024c7d;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-info .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-info .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link.is-active{background-color:#023d64;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-info .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-info .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-info .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-info .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-info .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-info .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-info .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link.is-active{background-color:#023d64;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-info .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link{background-color:#023d64;color:#fff}html.theme--documenter-dark .navbar.is-info .navbar-dropdown a.navbar-item.is-active{background-color:#024c7d;color:#fff}}html.theme--documenter-dark .navbar.is-success{background-color:#008438;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-success .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-success .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link.is-active{background-color:#006b2d;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-success .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-success .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-success .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-success .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-success .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-success .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-success .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link.is-active{background-color:#006b2d;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-success .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link{background-color:#006b2d;color:#fff}html.theme--documenter-dark .navbar.is-success .navbar-dropdown a.navbar-item.is-active{background-color:#008438;color:#fff}}html.theme--documenter-dark .navbar.is-warning{background-color:#ad8100;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-warning .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-warning .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link.is-active{background-color:#946e00;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-warning .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-warning .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-warning .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-warning .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-warning .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-warning .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link.is-active{background-color:#946e00;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-warning .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link{background-color:#946e00;color:#fff}html.theme--documenter-dark .navbar.is-warning .navbar-dropdown a.navbar-item.is-active{background-color:#ad8100;color:#fff}}html.theme--documenter-dark .navbar.is-danger{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-brand>.navbar-item,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-brand>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-danger .navbar-brand>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-danger .navbar-brand>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link:focus,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link:hover,html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link.is-active{background-color:#86170b;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-brand .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-burger{color:#fff}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar.is-danger .navbar-start>.navbar-item,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link,html.theme--documenter-dark .navbar.is-danger .navbar-end>.navbar-item,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link{color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-start>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-danger .navbar-start>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-danger .navbar-start>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link:focus,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link:hover,html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-end>a.navbar-item:focus,html.theme--documenter-dark .navbar.is-danger .navbar-end>a.navbar-item:hover,html.theme--documenter-dark .navbar.is-danger .navbar-end>a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link:focus,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link:hover,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link.is-active{background-color:#86170b;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-start .navbar-link::after,html.theme--documenter-dark .navbar.is-danger .navbar-end .navbar-link::after{border-color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link{background-color:#86170b;color:#fff}html.theme--documenter-dark .navbar.is-danger .navbar-dropdown a.navbar-item.is-active{background-color:#9e1b0d;color:#fff}}html.theme--documenter-dark .navbar>.container{align-items:stretch;display:flex;min-height:4rem;width:100%}html.theme--documenter-dark .navbar.has-shadow{box-shadow:0 2px 0 0 #282f2f}html.theme--documenter-dark .navbar.is-fixed-bottom,html.theme--documenter-dark .navbar.is-fixed-top{left:0;position:fixed;right:0;z-index:30}html.theme--documenter-dark .navbar.is-fixed-bottom{bottom:0}html.theme--documenter-dark .navbar.is-fixed-bottom.has-shadow{box-shadow:0 -2px 0 0 #282f2f}html.theme--documenter-dark .navbar.is-fixed-top{top:0}html.theme--documenter-dark html.has-navbar-fixed-top,html.theme--documenter-dark body.has-navbar-fixed-top{padding-top:4rem}html.theme--documenter-dark html.has-navbar-fixed-bottom,html.theme--documenter-dark body.has-navbar-fixed-bottom{padding-bottom:4rem}html.theme--documenter-dark .navbar-brand,html.theme--documenter-dark .navbar-tabs{align-items:stretch;display:flex;flex-shrink:0;min-height:4rem}html.theme--documenter-dark .navbar-brand a.navbar-item:focus,html.theme--documenter-dark .navbar-brand a.navbar-item:hover{background-color:transparent}html.theme--documenter-dark .navbar-tabs{-webkit-overflow-scrolling:touch;max-width:100vw;overflow-x:auto;overflow-y:hidden}html.theme--documenter-dark .navbar-burger{color:#fff;-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;cursor:pointer;display:block;height:4rem;position:relative;width:4rem;margin-left:auto}html.theme--documenter-dark .navbar-burger span{background-color:currentColor;display:block;height:1px;left:calc(50% - 8px);position:absolute;transform-origin:center;transition-duration:86ms;transition-property:background-color, opacity, transform;transition-timing-function:ease-out;width:16px}html.theme--documenter-dark .navbar-burger span:nth-child(1){top:calc(50% - 6px)}html.theme--documenter-dark .navbar-burger span:nth-child(2){top:calc(50% - 1px)}html.theme--documenter-dark .navbar-burger span:nth-child(3){top:calc(50% + 4px)}html.theme--documenter-dark .navbar-burger:hover{background-color:rgba(0,0,0,0.05)}html.theme--documenter-dark .navbar-burger.is-active span:nth-child(1){transform:translateY(5px) rotate(45deg)}html.theme--documenter-dark .navbar-burger.is-active span:nth-child(2){opacity:0}html.theme--documenter-dark .navbar-burger.is-active span:nth-child(3){transform:translateY(-5px) rotate(-45deg)}html.theme--documenter-dark .navbar-menu{display:none}html.theme--documenter-dark .navbar-item,html.theme--documenter-dark .navbar-link{color:#fff;display:block;line-height:1.5;padding:0.5rem 0.75rem;position:relative}html.theme--documenter-dark .navbar-item .icon:only-child,html.theme--documenter-dark .navbar-link .icon:only-child{margin-left:-0.25rem;margin-right:-0.25rem}html.theme--documenter-dark a.navbar-item,html.theme--documenter-dark .navbar-link{cursor:pointer}html.theme--documenter-dark a.navbar-item:focus,html.theme--documenter-dark a.navbar-item:focus-within,html.theme--documenter-dark a.navbar-item:hover,html.theme--documenter-dark a.navbar-item.is-active,html.theme--documenter-dark .navbar-link:focus,html.theme--documenter-dark .navbar-link:focus-within,html.theme--documenter-dark .navbar-link:hover,html.theme--documenter-dark .navbar-link.is-active{background-color:rgba(0,0,0,0);color:#1abc9c}html.theme--documenter-dark .navbar-item{flex-grow:0;flex-shrink:0}html.theme--documenter-dark .navbar-item img{max-height:1.75rem}html.theme--documenter-dark .navbar-item.has-dropdown{padding:0}html.theme--documenter-dark .navbar-item.is-expanded{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .navbar-item.is-tab{border-bottom:1px solid transparent;min-height:4rem;padding-bottom:calc(0.5rem - 1px)}html.theme--documenter-dark .navbar-item.is-tab:focus,html.theme--documenter-dark .navbar-item.is-tab:hover{background-color:rgba(0,0,0,0);border-bottom-color:#1abc9c}html.theme--documenter-dark .navbar-item.is-tab.is-active{background-color:rgba(0,0,0,0);border-bottom-color:#1abc9c;border-bottom-style:solid;border-bottom-width:3px;color:#1abc9c;padding-bottom:calc(0.5rem - 3px)}html.theme--documenter-dark .navbar-content{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .navbar-link:not(.is-arrowless){padding-right:2.5em}html.theme--documenter-dark .navbar-link:not(.is-arrowless)::after{border-color:#fff;margin-top:-0.375em;right:1.125em}html.theme--documenter-dark .navbar-dropdown{font-size:0.875rem;padding-bottom:0.5rem;padding-top:0.5rem}html.theme--documenter-dark .navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}html.theme--documenter-dark .navbar-divider{background-color:rgba(0,0,0,0.2);border:none;display:none;height:2px;margin:0.5rem 0}@media screen and (max-width: 1055px){html.theme--documenter-dark .navbar>.container{display:block}html.theme--documenter-dark .navbar-brand .navbar-item,html.theme--documenter-dark .navbar-tabs .navbar-item{align-items:center;display:flex}html.theme--documenter-dark .navbar-link::after{display:none}html.theme--documenter-dark .navbar-menu{background-color:#375a7f;box-shadow:0 8px 16px rgba(10,10,10,0.1);padding:0.5rem 0}html.theme--documenter-dark .navbar-menu.is-active{display:block}html.theme--documenter-dark .navbar.is-fixed-bottom-touch,html.theme--documenter-dark .navbar.is-fixed-top-touch{left:0;position:fixed;right:0;z-index:30}html.theme--documenter-dark .navbar.is-fixed-bottom-touch{bottom:0}html.theme--documenter-dark .navbar.is-fixed-bottom-touch.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--documenter-dark .navbar.is-fixed-top-touch{top:0}html.theme--documenter-dark .navbar.is-fixed-top .navbar-menu,html.theme--documenter-dark .navbar.is-fixed-top-touch .navbar-menu{-webkit-overflow-scrolling:touch;max-height:calc(100vh - 4rem);overflow:auto}html.theme--documenter-dark html.has-navbar-fixed-top-touch,html.theme--documenter-dark body.has-navbar-fixed-top-touch{padding-top:4rem}html.theme--documenter-dark html.has-navbar-fixed-bottom-touch,html.theme--documenter-dark body.has-navbar-fixed-bottom-touch{padding-bottom:4rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .navbar,html.theme--documenter-dark .navbar-menu,html.theme--documenter-dark .navbar-start,html.theme--documenter-dark .navbar-end{align-items:stretch;display:flex}html.theme--documenter-dark .navbar{min-height:4rem}html.theme--documenter-dark .navbar.is-spaced{padding:1rem 2rem}html.theme--documenter-dark .navbar.is-spaced .navbar-start,html.theme--documenter-dark .navbar.is-spaced .navbar-end{align-items:center}html.theme--documenter-dark .navbar.is-spaced a.navbar-item,html.theme--documenter-dark .navbar.is-spaced .navbar-link{border-radius:.4em}html.theme--documenter-dark .navbar.is-transparent a.navbar-item:focus,html.theme--documenter-dark .navbar.is-transparent a.navbar-item:hover,html.theme--documenter-dark .navbar.is-transparent a.navbar-item.is-active,html.theme--documenter-dark .navbar.is-transparent .navbar-link:focus,html.theme--documenter-dark .navbar.is-transparent .navbar-link:hover,html.theme--documenter-dark .navbar.is-transparent .navbar-link.is-active{background-color:transparent !important}html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link,html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link,html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link,html.theme--documenter-dark .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link{background-color:transparent !important}html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item:focus,html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#dbdee0}html.theme--documenter-dark .navbar.is-transparent .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#1abc9c}html.theme--documenter-dark .navbar-burger{display:none}html.theme--documenter-dark .navbar-item,html.theme--documenter-dark .navbar-link{align-items:center;display:flex}html.theme--documenter-dark .navbar-item.has-dropdown{align-items:stretch}html.theme--documenter-dark .navbar-item.has-dropdown-up .navbar-link::after{transform:rotate(135deg) translate(0.25em, -0.25em)}html.theme--documenter-dark .navbar-item.has-dropdown-up .navbar-dropdown{border-bottom:1px solid rgba(0,0,0,0.2);border-radius:8px 8px 0 0;border-top:none;bottom:100%;box-shadow:0 -8px 8px rgba(10,10,10,0.1);top:auto}html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-active .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed,.navbar.is-spaced html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown,html.theme--documenter-dark .navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed{opacity:1;pointer-events:auto;transform:translateY(0)}html.theme--documenter-dark .navbar-menu{flex-grow:1;flex-shrink:0}html.theme--documenter-dark .navbar-start{justify-content:flex-start;margin-right:auto}html.theme--documenter-dark .navbar-end{justify-content:flex-end;margin-left:auto}html.theme--documenter-dark .navbar-dropdown{background-color:#375a7f;border-bottom-left-radius:8px;border-bottom-right-radius:8px;border-top:1px solid rgba(0,0,0,0.2);box-shadow:0 8px 8px rgba(10,10,10,0.1);display:none;font-size:0.875rem;left:0;min-width:100%;position:absolute;top:100%;z-index:20}html.theme--documenter-dark .navbar-dropdown .navbar-item{padding:0.375rem 1rem;white-space:nowrap}html.theme--documenter-dark .navbar-dropdown a.navbar-item{padding-right:3rem}html.theme--documenter-dark .navbar-dropdown a.navbar-item:focus,html.theme--documenter-dark .navbar-dropdown a.navbar-item:hover{background-color:rgba(0,0,0,0);color:#dbdee0}html.theme--documenter-dark .navbar-dropdown a.navbar-item.is-active{background-color:rgba(0,0,0,0);color:#1abc9c}.navbar.is-spaced html.theme--documenter-dark .navbar-dropdown,html.theme--documenter-dark .navbar-dropdown.is-boxed{border-radius:8px;border-top:none;box-shadow:0 8px 8px rgba(10,10,10,0.1), 0 0 0 1px rgba(10,10,10,0.1);display:block;opacity:0;pointer-events:none;top:calc(100% + (-4px));transform:translateY(-5px);transition-duration:86ms;transition-property:opacity, transform}html.theme--documenter-dark .navbar-dropdown.is-right{left:auto;right:0}html.theme--documenter-dark .navbar-divider{display:block}html.theme--documenter-dark .navbar>.container .navbar-brand,html.theme--documenter-dark .container>.navbar .navbar-brand{margin-left:-.75rem}html.theme--documenter-dark .navbar>.container .navbar-menu,html.theme--documenter-dark .container>.navbar .navbar-menu{margin-right:-.75rem}html.theme--documenter-dark .navbar.is-fixed-bottom-desktop,html.theme--documenter-dark .navbar.is-fixed-top-desktop{left:0;position:fixed;right:0;z-index:30}html.theme--documenter-dark .navbar.is-fixed-bottom-desktop{bottom:0}html.theme--documenter-dark .navbar.is-fixed-bottom-desktop.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}html.theme--documenter-dark .navbar.is-fixed-top-desktop{top:0}html.theme--documenter-dark html.has-navbar-fixed-top-desktop,html.theme--documenter-dark body.has-navbar-fixed-top-desktop{padding-top:4rem}html.theme--documenter-dark html.has-navbar-fixed-bottom-desktop,html.theme--documenter-dark body.has-navbar-fixed-bottom-desktop{padding-bottom:4rem}html.theme--documenter-dark html.has-spaced-navbar-fixed-top,html.theme--documenter-dark body.has-spaced-navbar-fixed-top{padding-top:6rem}html.theme--documenter-dark html.has-spaced-navbar-fixed-bottom,html.theme--documenter-dark body.has-spaced-navbar-fixed-bottom{padding-bottom:6rem}html.theme--documenter-dark a.navbar-item.is-active,html.theme--documenter-dark .navbar-link.is-active{color:#1abc9c}html.theme--documenter-dark a.navbar-item.is-active:not(:focus):not(:hover),html.theme--documenter-dark .navbar-link.is-active:not(:focus):not(:hover){background-color:rgba(0,0,0,0)}html.theme--documenter-dark .navbar-item.has-dropdown:focus .navbar-link,html.theme--documenter-dark .navbar-item.has-dropdown:hover .navbar-link,html.theme--documenter-dark .navbar-item.has-dropdown.is-active .navbar-link{background-color:rgba(0,0,0,0)}}html.theme--documenter-dark .hero.is-fullheight-with-navbar{min-height:calc(100vh - 4rem)}html.theme--documenter-dark .pagination{font-size:1rem;margin:-.25rem}html.theme--documenter-dark .pagination.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination{font-size:.75rem}html.theme--documenter-dark .pagination.is-medium{font-size:1.25rem}html.theme--documenter-dark .pagination.is-large{font-size:1.5rem}html.theme--documenter-dark .pagination.is-rounded .pagination-previous,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination .pagination-previous,html.theme--documenter-dark .pagination.is-rounded .pagination-next,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination .pagination-next{padding-left:1em;padding-right:1em;border-radius:9999px}html.theme--documenter-dark .pagination.is-rounded .pagination-link,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.pagination .pagination-link{border-radius:9999px}html.theme--documenter-dark .pagination,html.theme--documenter-dark .pagination-list{align-items:center;display:flex;justify-content:center;text-align:center}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis{font-size:1em;justify-content:center;margin:.25rem;padding-left:.5em;padding-right:.5em;text-align:center}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link{border-color:#5e6d6f;color:#1abc9c;min-width:2.5em}html.theme--documenter-dark .pagination-previous:hover,html.theme--documenter-dark .pagination-next:hover,html.theme--documenter-dark .pagination-link:hover{border-color:#8c9b9d;color:#1dd2af}html.theme--documenter-dark .pagination-previous:focus,html.theme--documenter-dark .pagination-next:focus,html.theme--documenter-dark .pagination-link:focus{border-color:#8c9b9d}html.theme--documenter-dark .pagination-previous:active,html.theme--documenter-dark .pagination-next:active,html.theme--documenter-dark .pagination-link:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2)}html.theme--documenter-dark .pagination-previous[disabled],html.theme--documenter-dark .pagination-previous.is-disabled,html.theme--documenter-dark .pagination-next[disabled],html.theme--documenter-dark .pagination-next.is-disabled,html.theme--documenter-dark .pagination-link[disabled],html.theme--documenter-dark .pagination-link.is-disabled{background-color:#5e6d6f;border-color:#5e6d6f;box-shadow:none;color:#fff;opacity:0.5}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next{padding-left:.75em;padding-right:.75em;white-space:nowrap}html.theme--documenter-dark .pagination-link.is-current{background-color:#1abc9c;border-color:#1abc9c;color:#fff}html.theme--documenter-dark .pagination-ellipsis{color:#8c9b9d;pointer-events:none}html.theme--documenter-dark .pagination-list{flex-wrap:wrap}html.theme--documenter-dark .pagination-list li{list-style:none}@media screen and (max-width: 768px){html.theme--documenter-dark .pagination{flex-wrap:wrap}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .pagination-list li{flex-grow:1;flex-shrink:1}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .pagination-list{flex-grow:1;flex-shrink:1;justify-content:flex-start;order:1}html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-ellipsis{margin-bottom:0;margin-top:0}html.theme--documenter-dark .pagination-previous{order:2}html.theme--documenter-dark .pagination-next{order:3}html.theme--documenter-dark .pagination{justify-content:space-between;margin-bottom:0;margin-top:0}html.theme--documenter-dark .pagination.is-centered .pagination-previous{order:1}html.theme--documenter-dark .pagination.is-centered .pagination-list{justify-content:center;order:2}html.theme--documenter-dark .pagination.is-centered .pagination-next{order:3}html.theme--documenter-dark .pagination.is-right .pagination-previous{order:1}html.theme--documenter-dark .pagination.is-right .pagination-next{order:2}html.theme--documenter-dark .pagination.is-right .pagination-list{justify-content:flex-end;order:3}}html.theme--documenter-dark .panel{border-radius:8px;box-shadow:#171717;font-size:1rem}html.theme--documenter-dark .panel:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .panel.is-white .panel-heading{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .panel.is-white .panel-tabs a.is-active{border-bottom-color:#fff}html.theme--documenter-dark .panel.is-white .panel-block.is-active .panel-icon{color:#fff}html.theme--documenter-dark .panel.is-black .panel-heading{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .panel.is-black .panel-tabs a.is-active{border-bottom-color:#0a0a0a}html.theme--documenter-dark .panel.is-black .panel-block.is-active .panel-icon{color:#0a0a0a}html.theme--documenter-dark .panel.is-light .panel-heading{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .panel.is-light .panel-tabs a.is-active{border-bottom-color:#ecf0f1}html.theme--documenter-dark .panel.is-light .panel-block.is-active .panel-icon{color:#ecf0f1}html.theme--documenter-dark .panel.is-dark .panel-heading,html.theme--documenter-dark .content kbd.panel .panel-heading{background-color:#282f2f;color:#fff}html.theme--documenter-dark .panel.is-dark .panel-tabs a.is-active,html.theme--documenter-dark .content kbd.panel .panel-tabs a.is-active{border-bottom-color:#282f2f}html.theme--documenter-dark .panel.is-dark .panel-block.is-active .panel-icon,html.theme--documenter-dark .content kbd.panel .panel-block.is-active .panel-icon{color:#282f2f}html.theme--documenter-dark .panel.is-primary .panel-heading,html.theme--documenter-dark .docstring>section>a.panel.docs-sourcelink .panel-heading{background-color:#375a7f;color:#fff}html.theme--documenter-dark .panel.is-primary .panel-tabs a.is-active,html.theme--documenter-dark .docstring>section>a.panel.docs-sourcelink .panel-tabs a.is-active{border-bottom-color:#375a7f}html.theme--documenter-dark .panel.is-primary .panel-block.is-active .panel-icon,html.theme--documenter-dark .docstring>section>a.panel.docs-sourcelink .panel-block.is-active .panel-icon{color:#375a7f}html.theme--documenter-dark .panel.is-link .panel-heading{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .panel.is-link .panel-tabs a.is-active{border-bottom-color:#1abc9c}html.theme--documenter-dark .panel.is-link .panel-block.is-active .panel-icon{color:#1abc9c}html.theme--documenter-dark .panel.is-info .panel-heading{background-color:#024c7d;color:#fff}html.theme--documenter-dark .panel.is-info .panel-tabs a.is-active{border-bottom-color:#024c7d}html.theme--documenter-dark .panel.is-info .panel-block.is-active .panel-icon{color:#024c7d}html.theme--documenter-dark .panel.is-success .panel-heading{background-color:#008438;color:#fff}html.theme--documenter-dark .panel.is-success .panel-tabs a.is-active{border-bottom-color:#008438}html.theme--documenter-dark .panel.is-success .panel-block.is-active .panel-icon{color:#008438}html.theme--documenter-dark .panel.is-warning .panel-heading{background-color:#ad8100;color:#fff}html.theme--documenter-dark .panel.is-warning .panel-tabs a.is-active{border-bottom-color:#ad8100}html.theme--documenter-dark .panel.is-warning .panel-block.is-active .panel-icon{color:#ad8100}html.theme--documenter-dark .panel.is-danger .panel-heading{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .panel.is-danger .panel-tabs a.is-active{border-bottom-color:#9e1b0d}html.theme--documenter-dark .panel.is-danger .panel-block.is-active .panel-icon{color:#9e1b0d}html.theme--documenter-dark .panel-tabs:not(:last-child),html.theme--documenter-dark .panel-block:not(:last-child){border-bottom:1px solid #ededed}html.theme--documenter-dark .panel-heading{background-color:#343c3d;border-radius:8px 8px 0 0;color:#f2f2f2;font-size:1.25em;font-weight:700;line-height:1.25;padding:0.75em 1em}html.theme--documenter-dark .panel-tabs{align-items:flex-end;display:flex;font-size:.875em;justify-content:center}html.theme--documenter-dark .panel-tabs a{border-bottom:1px solid #5e6d6f;margin-bottom:-1px;padding:0.5em}html.theme--documenter-dark .panel-tabs a.is-active{border-bottom-color:#343c3d;color:#17a689}html.theme--documenter-dark .panel-list a{color:#fff}html.theme--documenter-dark .panel-list a:hover{color:#1abc9c}html.theme--documenter-dark .panel-block{align-items:center;color:#f2f2f2;display:flex;justify-content:flex-start;padding:0.5em 0.75em}html.theme--documenter-dark .panel-block input[type="checkbox"]{margin-right:.75em}html.theme--documenter-dark .panel-block>.control{flex-grow:1;flex-shrink:1;width:100%}html.theme--documenter-dark .panel-block.is-wrapped{flex-wrap:wrap}html.theme--documenter-dark .panel-block.is-active{border-left-color:#1abc9c;color:#17a689}html.theme--documenter-dark .panel-block.is-active .panel-icon{color:#1abc9c}html.theme--documenter-dark .panel-block:last-child{border-bottom-left-radius:8px;border-bottom-right-radius:8px}html.theme--documenter-dark a.panel-block,html.theme--documenter-dark label.panel-block{cursor:pointer}html.theme--documenter-dark a.panel-block:hover,html.theme--documenter-dark label.panel-block:hover{background-color:#282f2f}html.theme--documenter-dark .panel-icon{display:inline-block;font-size:14px;height:1em;line-height:1em;text-align:center;vertical-align:top;width:1em;color:#fff;margin-right:.75em}html.theme--documenter-dark .panel-icon .fa{font-size:inherit;line-height:inherit}html.theme--documenter-dark .tabs{-webkit-overflow-scrolling:touch;align-items:stretch;display:flex;font-size:1rem;justify-content:space-between;overflow:hidden;overflow-x:auto;white-space:nowrap}html.theme--documenter-dark .tabs a{align-items:center;border-bottom-color:#5e6d6f;border-bottom-style:solid;border-bottom-width:1px;color:#fff;display:flex;justify-content:center;margin-bottom:-1px;padding:0.5em 1em;vertical-align:top}html.theme--documenter-dark .tabs a:hover{border-bottom-color:#f2f2f2;color:#f2f2f2}html.theme--documenter-dark .tabs li{display:block}html.theme--documenter-dark .tabs li.is-active a{border-bottom-color:#1abc9c;color:#1abc9c}html.theme--documenter-dark .tabs ul{align-items:center;border-bottom-color:#5e6d6f;border-bottom-style:solid;border-bottom-width:1px;display:flex;flex-grow:1;flex-shrink:0;justify-content:flex-start}html.theme--documenter-dark .tabs ul.is-left{padding-right:0.75em}html.theme--documenter-dark .tabs ul.is-center{flex:none;justify-content:center;padding-left:0.75em;padding-right:0.75em}html.theme--documenter-dark .tabs ul.is-right{justify-content:flex-end;padding-left:0.75em}html.theme--documenter-dark .tabs .icon:first-child{margin-right:.5em}html.theme--documenter-dark .tabs .icon:last-child{margin-left:.5em}html.theme--documenter-dark .tabs.is-centered ul{justify-content:center}html.theme--documenter-dark .tabs.is-right ul{justify-content:flex-end}html.theme--documenter-dark .tabs.is-boxed a{border:1px solid transparent;border-radius:.4em .4em 0 0}html.theme--documenter-dark .tabs.is-boxed a:hover{background-color:#282f2f;border-bottom-color:#5e6d6f}html.theme--documenter-dark .tabs.is-boxed li.is-active a{background-color:#fff;border-color:#5e6d6f;border-bottom-color:rgba(0,0,0,0) !important}html.theme--documenter-dark .tabs.is-fullwidth li{flex-grow:1;flex-shrink:0}html.theme--documenter-dark .tabs.is-toggle a{border-color:#5e6d6f;border-style:solid;border-width:1px;margin-bottom:0;position:relative}html.theme--documenter-dark .tabs.is-toggle a:hover{background-color:#282f2f;border-color:#8c9b9d;z-index:2}html.theme--documenter-dark .tabs.is-toggle li+li{margin-left:-1px}html.theme--documenter-dark .tabs.is-toggle li:first-child a{border-top-left-radius:.4em;border-bottom-left-radius:.4em}html.theme--documenter-dark .tabs.is-toggle li:last-child a{border-top-right-radius:.4em;border-bottom-right-radius:.4em}html.theme--documenter-dark .tabs.is-toggle li.is-active a{background-color:#1abc9c;border-color:#1abc9c;color:#fff;z-index:1}html.theme--documenter-dark .tabs.is-toggle ul{border-bottom:none}html.theme--documenter-dark .tabs.is-toggle.is-toggle-rounded li:first-child a{border-bottom-left-radius:9999px;border-top-left-radius:9999px;padding-left:1.25em}html.theme--documenter-dark .tabs.is-toggle.is-toggle-rounded li:last-child a{border-bottom-right-radius:9999px;border-top-right-radius:9999px;padding-right:1.25em}html.theme--documenter-dark .tabs.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.tabs{font-size:.75rem}html.theme--documenter-dark .tabs.is-medium{font-size:1.25rem}html.theme--documenter-dark .tabs.is-large{font-size:1.5rem}html.theme--documenter-dark .column{display:block;flex-basis:0;flex-grow:1;flex-shrink:1;padding:.75rem}.columns.is-mobile>html.theme--documenter-dark .column.is-narrow{flex:none;width:unset}.columns.is-mobile>html.theme--documenter-dark .column.is-full{flex:none;width:100%}.columns.is-mobile>html.theme--documenter-dark .column.is-three-quarters{flex:none;width:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-two-thirds{flex:none;width:66.6666%}.columns.is-mobile>html.theme--documenter-dark .column.is-half{flex:none;width:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-one-third{flex:none;width:33.3333%}.columns.is-mobile>html.theme--documenter-dark .column.is-one-quarter{flex:none;width:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-one-fifth{flex:none;width:20%}.columns.is-mobile>html.theme--documenter-dark .column.is-two-fifths{flex:none;width:40%}.columns.is-mobile>html.theme--documenter-dark .column.is-three-fifths{flex:none;width:60%}.columns.is-mobile>html.theme--documenter-dark .column.is-four-fifths{flex:none;width:80%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-three-quarters{margin-left:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-two-thirds{margin-left:66.6666%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-half{margin-left:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-one-third{margin-left:33.3333%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-one-quarter{margin-left:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-one-fifth{margin-left:20%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-two-fifths{margin-left:40%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-three-fifths{margin-left:60%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-four-fifths{margin-left:80%}.columns.is-mobile>html.theme--documenter-dark .column.is-0{flex:none;width:0%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-0{margin-left:0%}.columns.is-mobile>html.theme--documenter-dark .column.is-1{flex:none;width:8.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-1{margin-left:8.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-2{flex:none;width:16.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-2{margin-left:16.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-3{flex:none;width:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-3{margin-left:25%}.columns.is-mobile>html.theme--documenter-dark .column.is-4{flex:none;width:33.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-4{margin-left:33.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-5{flex:none;width:41.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-5{margin-left:41.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-6{flex:none;width:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-6{margin-left:50%}.columns.is-mobile>html.theme--documenter-dark .column.is-7{flex:none;width:58.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-7{margin-left:58.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-8{flex:none;width:66.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-8{margin-left:66.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-9{flex:none;width:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-9{margin-left:75%}.columns.is-mobile>html.theme--documenter-dark .column.is-10{flex:none;width:83.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-10{margin-left:83.33333337%}.columns.is-mobile>html.theme--documenter-dark .column.is-11{flex:none;width:91.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-11{margin-left:91.66666674%}.columns.is-mobile>html.theme--documenter-dark .column.is-12{flex:none;width:100%}.columns.is-mobile>html.theme--documenter-dark .column.is-offset-12{margin-left:100%}@media screen and (max-width: 768px){html.theme--documenter-dark .column.is-narrow-mobile{flex:none;width:unset}html.theme--documenter-dark .column.is-full-mobile{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-mobile{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-mobile{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-mobile{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-mobile{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-mobile{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-mobile{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-mobile{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-mobile{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-mobile{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-mobile{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-mobile{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-mobile{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-mobile{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-mobile{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-mobile{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-mobile{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-mobile{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-mobile{margin-left:80%}html.theme--documenter-dark .column.is-0-mobile{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-mobile{margin-left:0%}html.theme--documenter-dark .column.is-1-mobile{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-mobile{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-mobile{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-mobile{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-mobile{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-mobile{margin-left:25%}html.theme--documenter-dark .column.is-4-mobile{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-mobile{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-mobile{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-mobile{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-mobile{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-mobile{margin-left:50%}html.theme--documenter-dark .column.is-7-mobile{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-mobile{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-mobile{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-mobile{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-mobile{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-mobile{margin-left:75%}html.theme--documenter-dark .column.is-10-mobile{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-mobile{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-mobile{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-mobile{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-mobile{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-mobile{margin-left:100%}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .column.is-narrow,html.theme--documenter-dark .column.is-narrow-tablet{flex:none;width:unset}html.theme--documenter-dark .column.is-full,html.theme--documenter-dark .column.is-full-tablet{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters,html.theme--documenter-dark .column.is-three-quarters-tablet{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds,html.theme--documenter-dark .column.is-two-thirds-tablet{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half,html.theme--documenter-dark .column.is-half-tablet{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third,html.theme--documenter-dark .column.is-one-third-tablet{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter,html.theme--documenter-dark .column.is-one-quarter-tablet{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth,html.theme--documenter-dark .column.is-one-fifth-tablet{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths,html.theme--documenter-dark .column.is-two-fifths-tablet{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths,html.theme--documenter-dark .column.is-three-fifths-tablet{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths,html.theme--documenter-dark .column.is-four-fifths-tablet{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters,html.theme--documenter-dark .column.is-offset-three-quarters-tablet{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds,html.theme--documenter-dark .column.is-offset-two-thirds-tablet{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half,html.theme--documenter-dark .column.is-offset-half-tablet{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third,html.theme--documenter-dark .column.is-offset-one-third-tablet{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter,html.theme--documenter-dark .column.is-offset-one-quarter-tablet{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth,html.theme--documenter-dark .column.is-offset-one-fifth-tablet{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths,html.theme--documenter-dark .column.is-offset-two-fifths-tablet{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths,html.theme--documenter-dark .column.is-offset-three-fifths-tablet{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths,html.theme--documenter-dark .column.is-offset-four-fifths-tablet{margin-left:80%}html.theme--documenter-dark .column.is-0,html.theme--documenter-dark .column.is-0-tablet{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0,html.theme--documenter-dark .column.is-offset-0-tablet{margin-left:0%}html.theme--documenter-dark .column.is-1,html.theme--documenter-dark .column.is-1-tablet{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1,html.theme--documenter-dark .column.is-offset-1-tablet{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2,html.theme--documenter-dark .column.is-2-tablet{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2,html.theme--documenter-dark .column.is-offset-2-tablet{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3,html.theme--documenter-dark .column.is-3-tablet{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3,html.theme--documenter-dark .column.is-offset-3-tablet{margin-left:25%}html.theme--documenter-dark .column.is-4,html.theme--documenter-dark .column.is-4-tablet{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4,html.theme--documenter-dark .column.is-offset-4-tablet{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5,html.theme--documenter-dark .column.is-5-tablet{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5,html.theme--documenter-dark .column.is-offset-5-tablet{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6,html.theme--documenter-dark .column.is-6-tablet{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6,html.theme--documenter-dark .column.is-offset-6-tablet{margin-left:50%}html.theme--documenter-dark .column.is-7,html.theme--documenter-dark .column.is-7-tablet{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7,html.theme--documenter-dark .column.is-offset-7-tablet{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8,html.theme--documenter-dark .column.is-8-tablet{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8,html.theme--documenter-dark .column.is-offset-8-tablet{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9,html.theme--documenter-dark .column.is-9-tablet{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9,html.theme--documenter-dark .column.is-offset-9-tablet{margin-left:75%}html.theme--documenter-dark .column.is-10,html.theme--documenter-dark .column.is-10-tablet{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10,html.theme--documenter-dark .column.is-offset-10-tablet{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11,html.theme--documenter-dark .column.is-11-tablet{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11,html.theme--documenter-dark .column.is-offset-11-tablet{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12,html.theme--documenter-dark .column.is-12-tablet{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12,html.theme--documenter-dark .column.is-offset-12-tablet{margin-left:100%}}@media screen and (max-width: 1055px){html.theme--documenter-dark .column.is-narrow-touch{flex:none;width:unset}html.theme--documenter-dark .column.is-full-touch{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-touch{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-touch{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-touch{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-touch{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-touch{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-touch{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-touch{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-touch{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-touch{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-touch{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-touch{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-touch{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-touch{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-touch{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-touch{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-touch{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-touch{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-touch{margin-left:80%}html.theme--documenter-dark .column.is-0-touch{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-touch{margin-left:0%}html.theme--documenter-dark .column.is-1-touch{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-touch{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-touch{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-touch{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-touch{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-touch{margin-left:25%}html.theme--documenter-dark .column.is-4-touch{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-touch{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-touch{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-touch{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-touch{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-touch{margin-left:50%}html.theme--documenter-dark .column.is-7-touch{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-touch{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-touch{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-touch{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-touch{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-touch{margin-left:75%}html.theme--documenter-dark .column.is-10-touch{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-touch{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-touch{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-touch{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-touch{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-touch{margin-left:100%}}@media screen and (min-width: 1056px){html.theme--documenter-dark .column.is-narrow-desktop{flex:none;width:unset}html.theme--documenter-dark .column.is-full-desktop{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-desktop{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-desktop{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-desktop{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-desktop{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-desktop{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-desktop{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-desktop{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-desktop{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-desktop{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-desktop{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-desktop{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-desktop{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-desktop{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-desktop{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-desktop{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-desktop{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-desktop{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-desktop{margin-left:80%}html.theme--documenter-dark .column.is-0-desktop{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-desktop{margin-left:0%}html.theme--documenter-dark .column.is-1-desktop{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-desktop{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-desktop{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-desktop{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-desktop{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-desktop{margin-left:25%}html.theme--documenter-dark .column.is-4-desktop{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-desktop{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-desktop{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-desktop{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-desktop{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-desktop{margin-left:50%}html.theme--documenter-dark .column.is-7-desktop{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-desktop{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-desktop{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-desktop{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-desktop{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-desktop{margin-left:75%}html.theme--documenter-dark .column.is-10-desktop{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-desktop{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-desktop{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-desktop{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-desktop{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-desktop{margin-left:100%}}@media screen and (min-width: 1216px){html.theme--documenter-dark .column.is-narrow-widescreen{flex:none;width:unset}html.theme--documenter-dark .column.is-full-widescreen{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-widescreen{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-widescreen{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-widescreen{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-widescreen{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-widescreen{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-widescreen{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-widescreen{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-widescreen{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-widescreen{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-widescreen{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-widescreen{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-widescreen{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-widescreen{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-widescreen{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-widescreen{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-widescreen{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-widescreen{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-widescreen{margin-left:80%}html.theme--documenter-dark .column.is-0-widescreen{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-widescreen{margin-left:0%}html.theme--documenter-dark .column.is-1-widescreen{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-widescreen{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-widescreen{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-widescreen{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-widescreen{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-widescreen{margin-left:25%}html.theme--documenter-dark .column.is-4-widescreen{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-widescreen{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-widescreen{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-widescreen{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-widescreen{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-widescreen{margin-left:50%}html.theme--documenter-dark .column.is-7-widescreen{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-widescreen{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-widescreen{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-widescreen{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-widescreen{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-widescreen{margin-left:75%}html.theme--documenter-dark .column.is-10-widescreen{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-widescreen{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-widescreen{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-widescreen{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-widescreen{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-widescreen{margin-left:100%}}@media screen and (min-width: 1408px){html.theme--documenter-dark .column.is-narrow-fullhd{flex:none;width:unset}html.theme--documenter-dark .column.is-full-fullhd{flex:none;width:100%}html.theme--documenter-dark .column.is-three-quarters-fullhd{flex:none;width:75%}html.theme--documenter-dark .column.is-two-thirds-fullhd{flex:none;width:66.6666%}html.theme--documenter-dark .column.is-half-fullhd{flex:none;width:50%}html.theme--documenter-dark .column.is-one-third-fullhd{flex:none;width:33.3333%}html.theme--documenter-dark .column.is-one-quarter-fullhd{flex:none;width:25%}html.theme--documenter-dark .column.is-one-fifth-fullhd{flex:none;width:20%}html.theme--documenter-dark .column.is-two-fifths-fullhd{flex:none;width:40%}html.theme--documenter-dark .column.is-three-fifths-fullhd{flex:none;width:60%}html.theme--documenter-dark .column.is-four-fifths-fullhd{flex:none;width:80%}html.theme--documenter-dark .column.is-offset-three-quarters-fullhd{margin-left:75%}html.theme--documenter-dark .column.is-offset-two-thirds-fullhd{margin-left:66.6666%}html.theme--documenter-dark .column.is-offset-half-fullhd{margin-left:50%}html.theme--documenter-dark .column.is-offset-one-third-fullhd{margin-left:33.3333%}html.theme--documenter-dark .column.is-offset-one-quarter-fullhd{margin-left:25%}html.theme--documenter-dark .column.is-offset-one-fifth-fullhd{margin-left:20%}html.theme--documenter-dark .column.is-offset-two-fifths-fullhd{margin-left:40%}html.theme--documenter-dark .column.is-offset-three-fifths-fullhd{margin-left:60%}html.theme--documenter-dark .column.is-offset-four-fifths-fullhd{margin-left:80%}html.theme--documenter-dark .column.is-0-fullhd{flex:none;width:0%}html.theme--documenter-dark .column.is-offset-0-fullhd{margin-left:0%}html.theme--documenter-dark .column.is-1-fullhd{flex:none;width:8.33333337%}html.theme--documenter-dark .column.is-offset-1-fullhd{margin-left:8.33333337%}html.theme--documenter-dark .column.is-2-fullhd{flex:none;width:16.66666674%}html.theme--documenter-dark .column.is-offset-2-fullhd{margin-left:16.66666674%}html.theme--documenter-dark .column.is-3-fullhd{flex:none;width:25%}html.theme--documenter-dark .column.is-offset-3-fullhd{margin-left:25%}html.theme--documenter-dark .column.is-4-fullhd{flex:none;width:33.33333337%}html.theme--documenter-dark .column.is-offset-4-fullhd{margin-left:33.33333337%}html.theme--documenter-dark .column.is-5-fullhd{flex:none;width:41.66666674%}html.theme--documenter-dark .column.is-offset-5-fullhd{margin-left:41.66666674%}html.theme--documenter-dark .column.is-6-fullhd{flex:none;width:50%}html.theme--documenter-dark .column.is-offset-6-fullhd{margin-left:50%}html.theme--documenter-dark .column.is-7-fullhd{flex:none;width:58.33333337%}html.theme--documenter-dark .column.is-offset-7-fullhd{margin-left:58.33333337%}html.theme--documenter-dark .column.is-8-fullhd{flex:none;width:66.66666674%}html.theme--documenter-dark .column.is-offset-8-fullhd{margin-left:66.66666674%}html.theme--documenter-dark .column.is-9-fullhd{flex:none;width:75%}html.theme--documenter-dark .column.is-offset-9-fullhd{margin-left:75%}html.theme--documenter-dark .column.is-10-fullhd{flex:none;width:83.33333337%}html.theme--documenter-dark .column.is-offset-10-fullhd{margin-left:83.33333337%}html.theme--documenter-dark .column.is-11-fullhd{flex:none;width:91.66666674%}html.theme--documenter-dark .column.is-offset-11-fullhd{margin-left:91.66666674%}html.theme--documenter-dark .column.is-12-fullhd{flex:none;width:100%}html.theme--documenter-dark .column.is-offset-12-fullhd{margin-left:100%}}html.theme--documenter-dark .columns{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--documenter-dark .columns:last-child{margin-bottom:-.75rem}html.theme--documenter-dark .columns:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}html.theme--documenter-dark .columns.is-centered{justify-content:center}html.theme--documenter-dark .columns.is-gapless{margin-left:0;margin-right:0;margin-top:0}html.theme--documenter-dark .columns.is-gapless>.column{margin:0;padding:0 !important}html.theme--documenter-dark .columns.is-gapless:not(:last-child){margin-bottom:1.5rem}html.theme--documenter-dark .columns.is-gapless:last-child{margin-bottom:0}html.theme--documenter-dark .columns.is-mobile{display:flex}html.theme--documenter-dark .columns.is-multiline{flex-wrap:wrap}html.theme--documenter-dark .columns.is-vcentered{align-items:center}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns:not(.is-desktop){display:flex}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-desktop{display:flex}}html.theme--documenter-dark .columns.is-variable{--columnGap: 0.75rem;margin-left:calc(-1 * var(--columnGap));margin-right:calc(-1 * var(--columnGap))}html.theme--documenter-dark .columns.is-variable>.column{padding-left:var(--columnGap);padding-right:var(--columnGap)}html.theme--documenter-dark .columns.is-variable.is-0{--columnGap: 0rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-0-mobile{--columnGap: 0rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-0-tablet{--columnGap: 0rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-0-tablet-only{--columnGap: 0rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-0-touch{--columnGap: 0rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-0-desktop{--columnGap: 0rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-0-desktop-only{--columnGap: 0rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-0-widescreen{--columnGap: 0rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-0-widescreen-only{--columnGap: 0rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-0-fullhd{--columnGap: 0rem}}html.theme--documenter-dark .columns.is-variable.is-1{--columnGap: .25rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-1-mobile{--columnGap: .25rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-1-tablet{--columnGap: .25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-1-tablet-only{--columnGap: .25rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-1-touch{--columnGap: .25rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-1-desktop{--columnGap: .25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-1-desktop-only{--columnGap: .25rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-1-widescreen{--columnGap: .25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-1-widescreen-only{--columnGap: .25rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-1-fullhd{--columnGap: .25rem}}html.theme--documenter-dark .columns.is-variable.is-2{--columnGap: .5rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-2-mobile{--columnGap: .5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-2-tablet{--columnGap: .5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-2-tablet-only{--columnGap: .5rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-2-touch{--columnGap: .5rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-2-desktop{--columnGap: .5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-2-desktop-only{--columnGap: .5rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-2-widescreen{--columnGap: .5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-2-widescreen-only{--columnGap: .5rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-2-fullhd{--columnGap: .5rem}}html.theme--documenter-dark .columns.is-variable.is-3{--columnGap: .75rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-3-mobile{--columnGap: .75rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-3-tablet{--columnGap: .75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-3-tablet-only{--columnGap: .75rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-3-touch{--columnGap: .75rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-3-desktop{--columnGap: .75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-3-desktop-only{--columnGap: .75rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-3-widescreen{--columnGap: .75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-3-widescreen-only{--columnGap: .75rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-3-fullhd{--columnGap: .75rem}}html.theme--documenter-dark .columns.is-variable.is-4{--columnGap: 1rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-4-mobile{--columnGap: 1rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-4-tablet{--columnGap: 1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-4-tablet-only{--columnGap: 1rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-4-touch{--columnGap: 1rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-4-desktop{--columnGap: 1rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-4-desktop-only{--columnGap: 1rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-4-widescreen{--columnGap: 1rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-4-widescreen-only{--columnGap: 1rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-4-fullhd{--columnGap: 1rem}}html.theme--documenter-dark .columns.is-variable.is-5{--columnGap: 1.25rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-5-mobile{--columnGap: 1.25rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-5-tablet{--columnGap: 1.25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-5-tablet-only{--columnGap: 1.25rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-5-touch{--columnGap: 1.25rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-5-desktop{--columnGap: 1.25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-5-desktop-only{--columnGap: 1.25rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-5-widescreen{--columnGap: 1.25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-5-widescreen-only{--columnGap: 1.25rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-5-fullhd{--columnGap: 1.25rem}}html.theme--documenter-dark .columns.is-variable.is-6{--columnGap: 1.5rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-6-mobile{--columnGap: 1.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-6-tablet{--columnGap: 1.5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-6-tablet-only{--columnGap: 1.5rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-6-touch{--columnGap: 1.5rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-6-desktop{--columnGap: 1.5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-6-desktop-only{--columnGap: 1.5rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-6-widescreen{--columnGap: 1.5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-6-widescreen-only{--columnGap: 1.5rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-6-fullhd{--columnGap: 1.5rem}}html.theme--documenter-dark .columns.is-variable.is-7{--columnGap: 1.75rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-7-mobile{--columnGap: 1.75rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-7-tablet{--columnGap: 1.75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-7-tablet-only{--columnGap: 1.75rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-7-touch{--columnGap: 1.75rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-7-desktop{--columnGap: 1.75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-7-desktop-only{--columnGap: 1.75rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-7-widescreen{--columnGap: 1.75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-7-widescreen-only{--columnGap: 1.75rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-7-fullhd{--columnGap: 1.75rem}}html.theme--documenter-dark .columns.is-variable.is-8{--columnGap: 2rem}@media screen and (max-width: 768px){html.theme--documenter-dark .columns.is-variable.is-8-mobile{--columnGap: 2rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .columns.is-variable.is-8-tablet{--columnGap: 2rem}}@media screen and (min-width: 769px) and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-8-tablet-only{--columnGap: 2rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark .columns.is-variable.is-8-touch{--columnGap: 2rem}}@media screen and (min-width: 1056px){html.theme--documenter-dark .columns.is-variable.is-8-desktop{--columnGap: 2rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){html.theme--documenter-dark .columns.is-variable.is-8-desktop-only{--columnGap: 2rem}}@media screen and (min-width: 1216px){html.theme--documenter-dark .columns.is-variable.is-8-widescreen{--columnGap: 2rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){html.theme--documenter-dark .columns.is-variable.is-8-widescreen-only{--columnGap: 2rem}}@media screen and (min-width: 1408px){html.theme--documenter-dark .columns.is-variable.is-8-fullhd{--columnGap: 2rem}}html.theme--documenter-dark .tile{align-items:stretch;display:block;flex-basis:0;flex-grow:1;flex-shrink:1;min-height:min-content}html.theme--documenter-dark .tile.is-ancestor{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}html.theme--documenter-dark .tile.is-ancestor:last-child{margin-bottom:-.75rem}html.theme--documenter-dark .tile.is-ancestor:not(:last-child){margin-bottom:.75rem}html.theme--documenter-dark .tile.is-child{margin:0 !important}html.theme--documenter-dark .tile.is-parent{padding:.75rem}html.theme--documenter-dark .tile.is-vertical{flex-direction:column}html.theme--documenter-dark .tile.is-vertical>.tile.is-child:not(:last-child){margin-bottom:1.5rem !important}@media screen and (min-width: 769px),print{html.theme--documenter-dark .tile:not(.is-child){display:flex}html.theme--documenter-dark .tile.is-1{flex:none;width:8.33333337%}html.theme--documenter-dark .tile.is-2{flex:none;width:16.66666674%}html.theme--documenter-dark .tile.is-3{flex:none;width:25%}html.theme--documenter-dark .tile.is-4{flex:none;width:33.33333337%}html.theme--documenter-dark .tile.is-5{flex:none;width:41.66666674%}html.theme--documenter-dark .tile.is-6{flex:none;width:50%}html.theme--documenter-dark .tile.is-7{flex:none;width:58.33333337%}html.theme--documenter-dark .tile.is-8{flex:none;width:66.66666674%}html.theme--documenter-dark .tile.is-9{flex:none;width:75%}html.theme--documenter-dark .tile.is-10{flex:none;width:83.33333337%}html.theme--documenter-dark .tile.is-11{flex:none;width:91.66666674%}html.theme--documenter-dark .tile.is-12{flex:none;width:100%}}html.theme--documenter-dark .hero{align-items:stretch;display:flex;flex-direction:column;justify-content:space-between}html.theme--documenter-dark .hero .navbar{background:none}html.theme--documenter-dark .hero .tabs ul{border-bottom:none}html.theme--documenter-dark .hero.is-white{background-color:#fff;color:#0a0a0a}html.theme--documenter-dark .hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-white strong{color:inherit}html.theme--documenter-dark .hero.is-white .title{color:#0a0a0a}html.theme--documenter-dark .hero.is-white .subtitle{color:rgba(10,10,10,0.9)}html.theme--documenter-dark .hero.is-white .subtitle a:not(.button),html.theme--documenter-dark .hero.is-white .subtitle strong{color:#0a0a0a}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-white .navbar-menu{background-color:#fff}}html.theme--documenter-dark .hero.is-white .navbar-item,html.theme--documenter-dark .hero.is-white .navbar-link{color:rgba(10,10,10,0.7)}html.theme--documenter-dark .hero.is-white a.navbar-item:hover,html.theme--documenter-dark .hero.is-white a.navbar-item.is-active,html.theme--documenter-dark .hero.is-white .navbar-link:hover,html.theme--documenter-dark .hero.is-white .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}html.theme--documenter-dark .hero.is-white .tabs a{color:#0a0a0a;opacity:0.9}html.theme--documenter-dark .hero.is-white .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-white .tabs li.is-active a{color:#fff !important;opacity:1}html.theme--documenter-dark .hero.is-white .tabs.is-boxed a,html.theme--documenter-dark .hero.is-white .tabs.is-toggle a{color:#0a0a0a}html.theme--documenter-dark .hero.is-white .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-white .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-white .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-white .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-white .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-white .tabs.is-toggle li.is-active a:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}html.theme--documenter-dark .hero.is-white.is-bold{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-white.is-bold .navbar-menu{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}}html.theme--documenter-dark .hero.is-black{background-color:#0a0a0a;color:#fff}html.theme--documenter-dark .hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-black strong{color:inherit}html.theme--documenter-dark .hero.is-black .title{color:#fff}html.theme--documenter-dark .hero.is-black .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-black .subtitle a:not(.button),html.theme--documenter-dark .hero.is-black .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-black .navbar-menu{background-color:#0a0a0a}}html.theme--documenter-dark .hero.is-black .navbar-item,html.theme--documenter-dark .hero.is-black .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-black a.navbar-item:hover,html.theme--documenter-dark .hero.is-black a.navbar-item.is-active,html.theme--documenter-dark .hero.is-black .navbar-link:hover,html.theme--documenter-dark .hero.is-black .navbar-link.is-active{background-color:#000;color:#fff}html.theme--documenter-dark .hero.is-black .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-black .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-black .tabs li.is-active a{color:#0a0a0a !important;opacity:1}html.theme--documenter-dark .hero.is-black .tabs.is-boxed a,html.theme--documenter-dark .hero.is-black .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-black .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-black .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-black .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-black .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-black .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-black .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}html.theme--documenter-dark .hero.is-black.is-bold{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-black.is-bold .navbar-menu{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}}html.theme--documenter-dark .hero.is-light{background-color:#ecf0f1;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-light strong{color:inherit}html.theme--documenter-dark .hero.is-light .title{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light .subtitle{color:rgba(0,0,0,0.9)}html.theme--documenter-dark .hero.is-light .subtitle a:not(.button),html.theme--documenter-dark .hero.is-light .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-light .navbar-menu{background-color:#ecf0f1}}html.theme--documenter-dark .hero.is-light .navbar-item,html.theme--documenter-dark .hero.is-light .navbar-link{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light a.navbar-item:hover,html.theme--documenter-dark .hero.is-light a.navbar-item.is-active,html.theme--documenter-dark .hero.is-light .navbar-link:hover,html.theme--documenter-dark .hero.is-light .navbar-link.is-active{background-color:#dde4e6;color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}html.theme--documenter-dark .hero.is-light .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-light .tabs li.is-active a{color:#ecf0f1 !important;opacity:1}html.theme--documenter-dark .hero.is-light .tabs.is-boxed a,html.theme--documenter-dark .hero.is-light .tabs.is-toggle a{color:rgba(0,0,0,0.7)}html.theme--documenter-dark .hero.is-light .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-light .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-light .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-light .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-light .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-light .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#ecf0f1}html.theme--documenter-dark .hero.is-light.is-bold{background-image:linear-gradient(141deg, #cadfe0 0%, #ecf0f1 71%, #fafbfc 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-light.is-bold .navbar-menu{background-image:linear-gradient(141deg, #cadfe0 0%, #ecf0f1 71%, #fafbfc 100%)}}html.theme--documenter-dark .hero.is-dark,html.theme--documenter-dark .content kbd.hero{background-color:#282f2f;color:#fff}html.theme--documenter-dark .hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .content kbd.hero a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-dark strong,html.theme--documenter-dark .content kbd.hero strong{color:inherit}html.theme--documenter-dark .hero.is-dark .title,html.theme--documenter-dark .content kbd.hero .title{color:#fff}html.theme--documenter-dark .hero.is-dark .subtitle,html.theme--documenter-dark .content kbd.hero .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-dark .subtitle a:not(.button),html.theme--documenter-dark .content kbd.hero .subtitle a:not(.button),html.theme--documenter-dark .hero.is-dark .subtitle strong,html.theme--documenter-dark .content kbd.hero .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-dark .navbar-menu,html.theme--documenter-dark .content kbd.hero .navbar-menu{background-color:#282f2f}}html.theme--documenter-dark .hero.is-dark .navbar-item,html.theme--documenter-dark .content kbd.hero .navbar-item,html.theme--documenter-dark .hero.is-dark .navbar-link,html.theme--documenter-dark .content kbd.hero .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-dark a.navbar-item:hover,html.theme--documenter-dark .content kbd.hero a.navbar-item:hover,html.theme--documenter-dark .hero.is-dark a.navbar-item.is-active,html.theme--documenter-dark .content kbd.hero a.navbar-item.is-active,html.theme--documenter-dark .hero.is-dark .navbar-link:hover,html.theme--documenter-dark .content kbd.hero .navbar-link:hover,html.theme--documenter-dark .hero.is-dark .navbar-link.is-active,html.theme--documenter-dark .content kbd.hero .navbar-link.is-active{background-color:#1d2122;color:#fff}html.theme--documenter-dark .hero.is-dark .tabs a,html.theme--documenter-dark .content kbd.hero .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-dark .tabs a:hover,html.theme--documenter-dark .content kbd.hero .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-dark .tabs li.is-active a,html.theme--documenter-dark .content kbd.hero .tabs li.is-active a{color:#282f2f !important;opacity:1}html.theme--documenter-dark .hero.is-dark .tabs.is-boxed a,html.theme--documenter-dark .content kbd.hero .tabs.is-boxed a,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle a,html.theme--documenter-dark .content kbd.hero .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-dark .tabs.is-boxed a:hover,html.theme--documenter-dark .content kbd.hero .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle a:hover,html.theme--documenter-dark .content kbd.hero .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-dark .tabs.is-boxed li.is-active a,html.theme--documenter-dark .content kbd.hero .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-dark .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle li.is-active a,html.theme--documenter-dark .content kbd.hero .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-dark .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#282f2f}html.theme--documenter-dark .hero.is-dark.is-bold,html.theme--documenter-dark .content kbd.hero.is-bold{background-image:linear-gradient(141deg, #0f1615 0%, #282f2f 71%, #313c40 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-dark.is-bold .navbar-menu,html.theme--documenter-dark .content kbd.hero.is-bold .navbar-menu{background-image:linear-gradient(141deg, #0f1615 0%, #282f2f 71%, #313c40 100%)}}html.theme--documenter-dark .hero.is-primary,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink{background-color:#375a7f;color:#fff}html.theme--documenter-dark .hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-primary strong,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink strong{color:inherit}html.theme--documenter-dark .hero.is-primary .title,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .title{color:#fff}html.theme--documenter-dark .hero.is-primary .subtitle,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-primary .subtitle a:not(.button),html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .subtitle a:not(.button),html.theme--documenter-dark .hero.is-primary .subtitle strong,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-primary .navbar-menu,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-menu{background-color:#375a7f}}html.theme--documenter-dark .hero.is-primary .navbar-item,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-item,html.theme--documenter-dark .hero.is-primary .navbar-link,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-primary a.navbar-item:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink a.navbar-item:hover,html.theme--documenter-dark .hero.is-primary a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink a.navbar-item.is-active,html.theme--documenter-dark .hero.is-primary .navbar-link:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-link:hover,html.theme--documenter-dark .hero.is-primary .navbar-link.is-active,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar-link.is-active{background-color:#2f4d6d;color:#fff}html.theme--documenter-dark .hero.is-primary .tabs a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-primary .tabs a:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-primary .tabs li.is-active a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs li.is-active a{color:#375a7f !important;opacity:1}html.theme--documenter-dark .hero.is-primary .tabs.is-boxed a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-primary .tabs.is-boxed a:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle a:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-primary .tabs.is-boxed li.is-active a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-primary .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle li.is-active a,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-primary .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#375a7f}html.theme--documenter-dark .hero.is-primary.is-bold,html.theme--documenter-dark .docstring>section>a.hero.is-bold.docs-sourcelink{background-image:linear-gradient(141deg, #214b62 0%, #375a7f 71%, #3a5796 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-primary.is-bold .navbar-menu,html.theme--documenter-dark .docstring>section>a.hero.is-bold.docs-sourcelink .navbar-menu{background-image:linear-gradient(141deg, #214b62 0%, #375a7f 71%, #3a5796 100%)}}html.theme--documenter-dark .hero.is-link{background-color:#1abc9c;color:#fff}html.theme--documenter-dark .hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-link strong{color:inherit}html.theme--documenter-dark .hero.is-link .title{color:#fff}html.theme--documenter-dark .hero.is-link .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-link .subtitle a:not(.button),html.theme--documenter-dark .hero.is-link .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-link .navbar-menu{background-color:#1abc9c}}html.theme--documenter-dark .hero.is-link .navbar-item,html.theme--documenter-dark .hero.is-link .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-link a.navbar-item:hover,html.theme--documenter-dark .hero.is-link a.navbar-item.is-active,html.theme--documenter-dark .hero.is-link .navbar-link:hover,html.theme--documenter-dark .hero.is-link .navbar-link.is-active{background-color:#17a689;color:#fff}html.theme--documenter-dark .hero.is-link .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-link .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-link .tabs li.is-active a{color:#1abc9c !important;opacity:1}html.theme--documenter-dark .hero.is-link .tabs.is-boxed a,html.theme--documenter-dark .hero.is-link .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-link .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-link .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-link .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-link .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-link .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-link .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#1abc9c}html.theme--documenter-dark .hero.is-link.is-bold{background-image:linear-gradient(141deg, #0c9764 0%, #1abc9c 71%, #17d8d2 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-link.is-bold .navbar-menu{background-image:linear-gradient(141deg, #0c9764 0%, #1abc9c 71%, #17d8d2 100%)}}html.theme--documenter-dark .hero.is-info{background-color:#024c7d;color:#fff}html.theme--documenter-dark .hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-info strong{color:inherit}html.theme--documenter-dark .hero.is-info .title{color:#fff}html.theme--documenter-dark .hero.is-info .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-info .subtitle a:not(.button),html.theme--documenter-dark .hero.is-info .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-info .navbar-menu{background-color:#024c7d}}html.theme--documenter-dark .hero.is-info .navbar-item,html.theme--documenter-dark .hero.is-info .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-info a.navbar-item:hover,html.theme--documenter-dark .hero.is-info a.navbar-item.is-active,html.theme--documenter-dark .hero.is-info .navbar-link:hover,html.theme--documenter-dark .hero.is-info .navbar-link.is-active{background-color:#023d64;color:#fff}html.theme--documenter-dark .hero.is-info .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-info .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-info .tabs li.is-active a{color:#024c7d !important;opacity:1}html.theme--documenter-dark .hero.is-info .tabs.is-boxed a,html.theme--documenter-dark .hero.is-info .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-info .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-info .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-info .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-info .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-info .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-info .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#024c7d}html.theme--documenter-dark .hero.is-info.is-bold{background-image:linear-gradient(141deg, #003a4c 0%, #024c7d 71%, #004299 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-info.is-bold .navbar-menu{background-image:linear-gradient(141deg, #003a4c 0%, #024c7d 71%, #004299 100%)}}html.theme--documenter-dark .hero.is-success{background-color:#008438;color:#fff}html.theme--documenter-dark .hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-success strong{color:inherit}html.theme--documenter-dark .hero.is-success .title{color:#fff}html.theme--documenter-dark .hero.is-success .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-success .subtitle a:not(.button),html.theme--documenter-dark .hero.is-success .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-success .navbar-menu{background-color:#008438}}html.theme--documenter-dark .hero.is-success .navbar-item,html.theme--documenter-dark .hero.is-success .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-success a.navbar-item:hover,html.theme--documenter-dark .hero.is-success a.navbar-item.is-active,html.theme--documenter-dark .hero.is-success .navbar-link:hover,html.theme--documenter-dark .hero.is-success .navbar-link.is-active{background-color:#006b2d;color:#fff}html.theme--documenter-dark .hero.is-success .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-success .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-success .tabs li.is-active a{color:#008438 !important;opacity:1}html.theme--documenter-dark .hero.is-success .tabs.is-boxed a,html.theme--documenter-dark .hero.is-success .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-success .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-success .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-success .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-success .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-success .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-success .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#008438}html.theme--documenter-dark .hero.is-success.is-bold{background-image:linear-gradient(141deg, #005115 0%, #008438 71%, #009e5d 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-success.is-bold .navbar-menu{background-image:linear-gradient(141deg, #005115 0%, #008438 71%, #009e5d 100%)}}html.theme--documenter-dark .hero.is-warning{background-color:#ad8100;color:#fff}html.theme--documenter-dark .hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-warning strong{color:inherit}html.theme--documenter-dark .hero.is-warning .title{color:#fff}html.theme--documenter-dark .hero.is-warning .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-warning .subtitle a:not(.button),html.theme--documenter-dark .hero.is-warning .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-warning .navbar-menu{background-color:#ad8100}}html.theme--documenter-dark .hero.is-warning .navbar-item,html.theme--documenter-dark .hero.is-warning .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-warning a.navbar-item:hover,html.theme--documenter-dark .hero.is-warning a.navbar-item.is-active,html.theme--documenter-dark .hero.is-warning .navbar-link:hover,html.theme--documenter-dark .hero.is-warning .navbar-link.is-active{background-color:#946e00;color:#fff}html.theme--documenter-dark .hero.is-warning .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-warning .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-warning .tabs li.is-active a{color:#ad8100 !important;opacity:1}html.theme--documenter-dark .hero.is-warning .tabs.is-boxed a,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-warning .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-warning .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-warning .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-warning .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#ad8100}html.theme--documenter-dark .hero.is-warning.is-bold{background-image:linear-gradient(141deg, #7a4700 0%, #ad8100 71%, #c7b500 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-warning.is-bold .navbar-menu{background-image:linear-gradient(141deg, #7a4700 0%, #ad8100 71%, #c7b500 100%)}}html.theme--documenter-dark .hero.is-danger{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),html.theme--documenter-dark .hero.is-danger strong{color:inherit}html.theme--documenter-dark .hero.is-danger .title{color:#fff}html.theme--documenter-dark .hero.is-danger .subtitle{color:rgba(255,255,255,0.9)}html.theme--documenter-dark .hero.is-danger .subtitle a:not(.button),html.theme--documenter-dark .hero.is-danger .subtitle strong{color:#fff}@media screen and (max-width: 1055px){html.theme--documenter-dark .hero.is-danger .navbar-menu{background-color:#9e1b0d}}html.theme--documenter-dark .hero.is-danger .navbar-item,html.theme--documenter-dark .hero.is-danger .navbar-link{color:rgba(255,255,255,0.7)}html.theme--documenter-dark .hero.is-danger a.navbar-item:hover,html.theme--documenter-dark .hero.is-danger a.navbar-item.is-active,html.theme--documenter-dark .hero.is-danger .navbar-link:hover,html.theme--documenter-dark .hero.is-danger .navbar-link.is-active{background-color:#86170b;color:#fff}html.theme--documenter-dark .hero.is-danger .tabs a{color:#fff;opacity:0.9}html.theme--documenter-dark .hero.is-danger .tabs a:hover{opacity:1}html.theme--documenter-dark .hero.is-danger .tabs li.is-active a{color:#9e1b0d !important;opacity:1}html.theme--documenter-dark .hero.is-danger .tabs.is-boxed a,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle a{color:#fff}html.theme--documenter-dark .hero.is-danger .tabs.is-boxed a:hover,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}html.theme--documenter-dark .hero.is-danger .tabs.is-boxed li.is-active a,html.theme--documenter-dark .hero.is-danger .tabs.is-boxed li.is-active a:hover,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle li.is-active a,html.theme--documenter-dark .hero.is-danger .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#9e1b0d}html.theme--documenter-dark .hero.is-danger.is-bold{background-image:linear-gradient(141deg, #75030b 0%, #9e1b0d 71%, #ba380a 100%)}@media screen and (max-width: 768px){html.theme--documenter-dark .hero.is-danger.is-bold .navbar-menu{background-image:linear-gradient(141deg, #75030b 0%, #9e1b0d 71%, #ba380a 100%)}}html.theme--documenter-dark .hero.is-small .hero-body,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.hero .hero-body{padding:1.5rem}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero.is-medium .hero-body{padding:9rem 4.5rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero.is-large .hero-body{padding:18rem 6rem}}html.theme--documenter-dark .hero.is-halfheight .hero-body,html.theme--documenter-dark .hero.is-fullheight .hero-body,html.theme--documenter-dark .hero.is-fullheight-with-navbar .hero-body{align-items:center;display:flex}html.theme--documenter-dark .hero.is-halfheight .hero-body>.container,html.theme--documenter-dark .hero.is-fullheight .hero-body>.container,html.theme--documenter-dark .hero.is-fullheight-with-navbar .hero-body>.container{flex-grow:1;flex-shrink:1}html.theme--documenter-dark .hero.is-halfheight{min-height:50vh}html.theme--documenter-dark .hero.is-fullheight{min-height:100vh}html.theme--documenter-dark .hero-video{overflow:hidden}html.theme--documenter-dark .hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;transform:translate3d(-50%, -50%, 0)}html.theme--documenter-dark .hero-video.is-transparent{opacity:0.3}@media screen and (max-width: 768px){html.theme--documenter-dark .hero-video{display:none}}html.theme--documenter-dark .hero-buttons{margin-top:1.5rem}@media screen and (max-width: 768px){html.theme--documenter-dark .hero-buttons .button{display:flex}html.theme--documenter-dark .hero-buttons .button:not(:last-child){margin-bottom:0.75rem}}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero-buttons{display:flex;justify-content:center}html.theme--documenter-dark .hero-buttons .button:not(:last-child){margin-right:1.5rem}}html.theme--documenter-dark .hero-head,html.theme--documenter-dark .hero-foot{flex-grow:0;flex-shrink:0}html.theme--documenter-dark .hero-body{flex-grow:1;flex-shrink:0;padding:3rem 1.5rem}@media screen and (min-width: 769px),print{html.theme--documenter-dark .hero-body{padding:3rem 3rem}}html.theme--documenter-dark .section{padding:3rem 1.5rem}@media screen and (min-width: 1056px){html.theme--documenter-dark .section{padding:3rem 3rem}html.theme--documenter-dark .section.is-medium{padding:9rem 4.5rem}html.theme--documenter-dark .section.is-large{padding:18rem 6rem}}html.theme--documenter-dark .footer{background-color:#282f2f;padding:3rem 1.5rem 6rem}html.theme--documenter-dark hr{height:1px}html.theme--documenter-dark h6{text-transform:uppercase;letter-spacing:0.5px}html.theme--documenter-dark .hero{background-color:#343c3d}html.theme--documenter-dark a{transition:all 200ms ease}html.theme--documenter-dark .button{transition:all 200ms ease;border-width:1px;color:#fff}html.theme--documenter-dark .button.is-active,html.theme--documenter-dark .button.is-focused,html.theme--documenter-dark .button:active,html.theme--documenter-dark .button:focus{box-shadow:0 0 0 2px rgba(140,155,157,0.5)}html.theme--documenter-dark .button.is-white.is-hovered,html.theme--documenter-dark .button.is-white:hover{background-color:#fff}html.theme--documenter-dark .button.is-white.is-active,html.theme--documenter-dark .button.is-white.is-focused,html.theme--documenter-dark .button.is-white:active,html.theme--documenter-dark .button.is-white:focus{border-color:#fff;box-shadow:0 0 0 2px rgba(255,255,255,0.5)}html.theme--documenter-dark .button.is-black.is-hovered,html.theme--documenter-dark .button.is-black:hover{background-color:#1d1d1d}html.theme--documenter-dark .button.is-black.is-active,html.theme--documenter-dark .button.is-black.is-focused,html.theme--documenter-dark .button.is-black:active,html.theme--documenter-dark .button.is-black:focus{border-color:#0a0a0a;box-shadow:0 0 0 2px rgba(10,10,10,0.5)}html.theme--documenter-dark .button.is-light.is-hovered,html.theme--documenter-dark .button.is-light:hover{background-color:#fff}html.theme--documenter-dark .button.is-light.is-active,html.theme--documenter-dark .button.is-light.is-focused,html.theme--documenter-dark .button.is-light:active,html.theme--documenter-dark .button.is-light:focus{border-color:#ecf0f1;box-shadow:0 0 0 2px rgba(236,240,241,0.5)}html.theme--documenter-dark .button.is-dark.is-hovered,html.theme--documenter-dark .content kbd.button.is-hovered,html.theme--documenter-dark .button.is-dark:hover,html.theme--documenter-dark .content kbd.button:hover{background-color:#3a4344}html.theme--documenter-dark .button.is-dark.is-active,html.theme--documenter-dark .content kbd.button.is-active,html.theme--documenter-dark .button.is-dark.is-focused,html.theme--documenter-dark .content kbd.button.is-focused,html.theme--documenter-dark .button.is-dark:active,html.theme--documenter-dark .content kbd.button:active,html.theme--documenter-dark .button.is-dark:focus,html.theme--documenter-dark .content kbd.button:focus{border-color:#282f2f;box-shadow:0 0 0 2px rgba(40,47,47,0.5)}html.theme--documenter-dark .button.is-primary.is-hovered,html.theme--documenter-dark .docstring>section>a.button.is-hovered.docs-sourcelink,html.theme--documenter-dark .button.is-primary:hover,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:hover{background-color:#436d9a}html.theme--documenter-dark .button.is-primary.is-active,html.theme--documenter-dark .docstring>section>a.button.is-active.docs-sourcelink,html.theme--documenter-dark .button.is-primary.is-focused,html.theme--documenter-dark .docstring>section>a.button.is-focused.docs-sourcelink,html.theme--documenter-dark .button.is-primary:active,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:active,html.theme--documenter-dark .button.is-primary:focus,html.theme--documenter-dark .docstring>section>a.button.docs-sourcelink:focus{border-color:#375a7f;box-shadow:0 0 0 2px rgba(55,90,127,0.5)}html.theme--documenter-dark .button.is-link.is-hovered,html.theme--documenter-dark .button.is-link:hover{background-color:#1fdeb8}html.theme--documenter-dark .button.is-link.is-active,html.theme--documenter-dark .button.is-link.is-focused,html.theme--documenter-dark .button.is-link:active,html.theme--documenter-dark .button.is-link:focus{border-color:#1abc9c;box-shadow:0 0 0 2px rgba(26,188,156,0.5)}html.theme--documenter-dark .button.is-info.is-hovered,html.theme--documenter-dark .button.is-info:hover{background-color:#0363a3}html.theme--documenter-dark .button.is-info.is-active,html.theme--documenter-dark .button.is-info.is-focused,html.theme--documenter-dark .button.is-info:active,html.theme--documenter-dark .button.is-info:focus{border-color:#024c7d;box-shadow:0 0 0 2px rgba(2,76,125,0.5)}html.theme--documenter-dark .button.is-success.is-hovered,html.theme--documenter-dark .button.is-success:hover{background-color:#00aa48}html.theme--documenter-dark .button.is-success.is-active,html.theme--documenter-dark .button.is-success.is-focused,html.theme--documenter-dark .button.is-success:active,html.theme--documenter-dark .button.is-success:focus{border-color:#008438;box-shadow:0 0 0 2px rgba(0,132,56,0.5)}html.theme--documenter-dark .button.is-warning.is-hovered,html.theme--documenter-dark .button.is-warning:hover{background-color:#d39e00}html.theme--documenter-dark .button.is-warning.is-active,html.theme--documenter-dark .button.is-warning.is-focused,html.theme--documenter-dark .button.is-warning:active,html.theme--documenter-dark .button.is-warning:focus{border-color:#ad8100;box-shadow:0 0 0 2px rgba(173,129,0,0.5)}html.theme--documenter-dark .button.is-danger.is-hovered,html.theme--documenter-dark .button.is-danger:hover{background-color:#c12110}html.theme--documenter-dark .button.is-danger.is-active,html.theme--documenter-dark .button.is-danger.is-focused,html.theme--documenter-dark .button.is-danger:active,html.theme--documenter-dark .button.is-danger:focus{border-color:#9e1b0d;box-shadow:0 0 0 2px rgba(158,27,13,0.5)}html.theme--documenter-dark .label{color:#dbdee0}html.theme--documenter-dark .button,html.theme--documenter-dark .control.has-icons-left .icon,html.theme--documenter-dark .control.has-icons-right .icon,html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark .pagination-ellipsis,html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-previous,html.theme--documenter-dark .select,html.theme--documenter-dark .select select,html.theme--documenter-dark .textarea{height:2.5em}html.theme--documenter-dark .input,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark .textarea{transition:all 200ms ease;box-shadow:none;border-width:1px;padding-left:1em;padding-right:1em}html.theme--documenter-dark .select:after,html.theme--documenter-dark .select select{border-width:1px}html.theme--documenter-dark .control.has-addons .button,html.theme--documenter-dark .control.has-addons .input,html.theme--documenter-dark .control.has-addons #documenter .docs-sidebar form.docs-search>input,html.theme--documenter-dark #documenter .docs-sidebar .control.has-addons form.docs-search>input,html.theme--documenter-dark .control.has-addons .select{margin-right:-1px}html.theme--documenter-dark .notification{background-color:#343c3d}html.theme--documenter-dark .card{box-shadow:none;border:1px solid #343c3d;background-color:#282f2f;border-radius:.4em}html.theme--documenter-dark .card .card-image img{border-radius:.4em .4em 0 0}html.theme--documenter-dark .card .card-header{box-shadow:none;background-color:rgba(18,18,18,0.2);border-radius:.4em .4em 0 0}html.theme--documenter-dark .card .card-footer{background-color:rgba(18,18,18,0.2)}html.theme--documenter-dark .card .card-footer,html.theme--documenter-dark .card .card-footer-item{border-width:1px;border-color:#343c3d}html.theme--documenter-dark .notification.is-white a:not(.button){color:#0a0a0a;text-decoration:underline}html.theme--documenter-dark .notification.is-black a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-light a:not(.button){color:rgba(0,0,0,0.7);text-decoration:underline}html.theme--documenter-dark .notification.is-dark a:not(.button),html.theme--documenter-dark .content kbd.notification a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-primary a:not(.button),html.theme--documenter-dark .docstring>section>a.notification.docs-sourcelink a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-link a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-info a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-success a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-warning a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .notification.is-danger a:not(.button){color:#fff;text-decoration:underline}html.theme--documenter-dark .tag,html.theme--documenter-dark .content kbd,html.theme--documenter-dark .docstring>section>a.docs-sourcelink{border-radius:.4em}html.theme--documenter-dark .menu-list a{transition:all 300ms ease}html.theme--documenter-dark .modal-card-body{background-color:#282f2f}html.theme--documenter-dark .modal-card-foot,html.theme--documenter-dark .modal-card-head{border-color:#343c3d}html.theme--documenter-dark .message-header{font-weight:700;background-color:#343c3d;color:#fff}html.theme--documenter-dark .message-body{border-width:1px;border-color:#343c3d}html.theme--documenter-dark .navbar{border-radius:.4em}html.theme--documenter-dark .navbar.is-transparent{background:none}html.theme--documenter-dark .navbar.is-primary .navbar-dropdown a.navbar-item.is-active,html.theme--documenter-dark .docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#1abc9c}@media screen and (max-width: 1055px){html.theme--documenter-dark .navbar .navbar-menu{background-color:#375a7f;border-radius:0 0 .4em .4em}}html.theme--documenter-dark .hero .navbar,html.theme--documenter-dark body>.navbar{border-radius:0}html.theme--documenter-dark .pagination-link,html.theme--documenter-dark .pagination-next,html.theme--documenter-dark .pagination-previous{border-width:1px}html.theme--documenter-dark .panel-block,html.theme--documenter-dark .panel-heading,html.theme--documenter-dark .panel-tabs{border-width:1px}html.theme--documenter-dark .panel-block:first-child,html.theme--documenter-dark .panel-heading:first-child,html.theme--documenter-dark .panel-tabs:first-child{border-top-width:1px}html.theme--documenter-dark .panel-heading{font-weight:700}html.theme--documenter-dark .panel-tabs a{border-width:1px;margin-bottom:-1px}html.theme--documenter-dark .panel-tabs a.is-active{border-bottom-color:#17a689}html.theme--documenter-dark .panel-block:hover{color:#1dd2af}html.theme--documenter-dark .panel-block:hover .panel-icon{color:#1dd2af}html.theme--documenter-dark .panel-block.is-active .panel-icon{color:#17a689}html.theme--documenter-dark .tabs a{border-bottom-width:1px;margin-bottom:-1px}html.theme--documenter-dark .tabs ul{border-bottom-width:1px}html.theme--documenter-dark .tabs.is-boxed a{border-width:1px}html.theme--documenter-dark .tabs.is-boxed li.is-active a{background-color:#1f2424}html.theme--documenter-dark .tabs.is-toggle li a{border-width:1px;margin-bottom:0}html.theme--documenter-dark .tabs.is-toggle li+li{margin-left:-1px}html.theme--documenter-dark .hero.is-white .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-black .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-light .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-dark .navbar .navbar-dropdown .navbar-item:hover,html.theme--documenter-dark .content kbd.hero .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-primary .navbar .navbar-dropdown .navbar-item:hover,html.theme--documenter-dark .docstring>section>a.hero.docs-sourcelink .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-link .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-info .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-success .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-warning .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark .hero.is-danger .navbar .navbar-dropdown .navbar-item:hover{background-color:rgba(0,0,0,0)}html.theme--documenter-dark h1 .docs-heading-anchor,html.theme--documenter-dark h1 .docs-heading-anchor:hover,html.theme--documenter-dark h1 .docs-heading-anchor:visited,html.theme--documenter-dark h2 .docs-heading-anchor,html.theme--documenter-dark h2 .docs-heading-anchor:hover,html.theme--documenter-dark h2 .docs-heading-anchor:visited,html.theme--documenter-dark h3 .docs-heading-anchor,html.theme--documenter-dark h3 .docs-heading-anchor:hover,html.theme--documenter-dark h3 .docs-heading-anchor:visited,html.theme--documenter-dark h4 .docs-heading-anchor,html.theme--documenter-dark h4 .docs-heading-anchor:hover,html.theme--documenter-dark h4 .docs-heading-anchor:visited,html.theme--documenter-dark h5 .docs-heading-anchor,html.theme--documenter-dark h5 .docs-heading-anchor:hover,html.theme--documenter-dark h5 .docs-heading-anchor:visited,html.theme--documenter-dark h6 .docs-heading-anchor,html.theme--documenter-dark h6 .docs-heading-anchor:hover,html.theme--documenter-dark h6 .docs-heading-anchor:visited{color:#f2f2f2}html.theme--documenter-dark h1 .docs-heading-anchor-permalink,html.theme--documenter-dark h2 .docs-heading-anchor-permalink,html.theme--documenter-dark h3 .docs-heading-anchor-permalink,html.theme--documenter-dark h4 .docs-heading-anchor-permalink,html.theme--documenter-dark h5 .docs-heading-anchor-permalink,html.theme--documenter-dark h6 .docs-heading-anchor-permalink{visibility:hidden;vertical-align:middle;margin-left:0.5em;font-size:0.7rem}html.theme--documenter-dark h1 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h2 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h3 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h4 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h5 .docs-heading-anchor-permalink::before,html.theme--documenter-dark h6 .docs-heading-anchor-permalink::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f0c1"}html.theme--documenter-dark h1:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h2:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h3:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h4:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h5:hover .docs-heading-anchor-permalink,html.theme--documenter-dark h6:hover .docs-heading-anchor-permalink{visibility:visible}html.theme--documenter-dark .docs-light-only{display:none !important}html.theme--documenter-dark pre{position:relative;overflow:hidden}html.theme--documenter-dark pre code,html.theme--documenter-dark pre code.hljs{padding:0 .75rem !important;overflow:auto;display:block}html.theme--documenter-dark pre code:first-of-type,html.theme--documenter-dark pre code.hljs:first-of-type{padding-top:0.5rem !important}html.theme--documenter-dark pre code:last-of-type,html.theme--documenter-dark pre code.hljs:last-of-type{padding-bottom:0.5rem !important}html.theme--documenter-dark pre .copy-button{opacity:0.2;transition:opacity 0.2s;position:absolute;right:0em;top:0em;padding:0.5em;width:2.5em;height:2.5em;background:transparent;border:none;font-family:"Font Awesome 6 Free";color:#fff;cursor:pointer;text-align:center}html.theme--documenter-dark pre .copy-button:focus,html.theme--documenter-dark pre .copy-button:hover{opacity:1;background:rgba(255,255,255,0.1);color:#1abc9c}html.theme--documenter-dark pre .copy-button.success{color:#259a12;opacity:1}html.theme--documenter-dark pre .copy-button.error{color:#cb3c33;opacity:1}html.theme--documenter-dark pre:hover .copy-button{opacity:1}html.theme--documenter-dark .admonition{background-color:#282f2f;border-style:solid;border-width:1px;border-color:#5e6d6f;border-radius:.4em;font-size:1rem}html.theme--documenter-dark .admonition strong{color:currentColor}html.theme--documenter-dark .admonition.is-small,html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input.admonition{font-size:.75rem}html.theme--documenter-dark .admonition.is-medium{font-size:1.25rem}html.theme--documenter-dark .admonition.is-large{font-size:1.5rem}html.theme--documenter-dark .admonition.is-default{background-color:#282f2f;border-color:#5e6d6f}html.theme--documenter-dark .admonition.is-default>.admonition-header{background-color:#5e6d6f;color:#fff}html.theme--documenter-dark .admonition.is-default>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-info{background-color:#282f2f;border-color:#024c7d}html.theme--documenter-dark .admonition.is-info>.admonition-header{background-color:#024c7d;color:#fff}html.theme--documenter-dark .admonition.is-info>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-success{background-color:#282f2f;border-color:#008438}html.theme--documenter-dark .admonition.is-success>.admonition-header{background-color:#008438;color:#fff}html.theme--documenter-dark .admonition.is-success>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-warning{background-color:#282f2f;border-color:#ad8100}html.theme--documenter-dark .admonition.is-warning>.admonition-header{background-color:#ad8100;color:#fff}html.theme--documenter-dark .admonition.is-warning>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-danger{background-color:#282f2f;border-color:#9e1b0d}html.theme--documenter-dark .admonition.is-danger>.admonition-header{background-color:#9e1b0d;color:#fff}html.theme--documenter-dark .admonition.is-danger>.admonition-body{color:#fff}html.theme--documenter-dark .admonition.is-compat{background-color:#282f2f;border-color:#137886}html.theme--documenter-dark .admonition.is-compat>.admonition-header{background-color:#137886;color:#fff}html.theme--documenter-dark .admonition.is-compat>.admonition-body{color:#fff}html.theme--documenter-dark .admonition-header{color:#fff;background-color:#5e6d6f;align-items:center;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.5rem .75rem;position:relative}html.theme--documenter-dark .admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;margin-right:.75rem;content:"\f06a"}html.theme--documenter-dark details.admonition.is-details>.admonition-header{list-style:none}html.theme--documenter-dark details.admonition.is-details>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f055"}html.theme--documenter-dark details.admonition.is-details[open]>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f056"}html.theme--documenter-dark .admonition-body{color:#fff;padding:0.5rem .75rem}html.theme--documenter-dark .admonition-body pre{background-color:#282f2f}html.theme--documenter-dark .admonition-body code{background-color:rgba(255,255,255,0.05)}html.theme--documenter-dark .docstring{margin-bottom:1em;background-color:rgba(0,0,0,0);border:1px solid #5e6d6f;box-shadow:none;max-width:100%}html.theme--documenter-dark .docstring>header{cursor:pointer;display:flex;flex-grow:1;align-items:stretch;padding:0.5rem .75rem;background-color:#282f2f;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);box-shadow:none;border-bottom:1px solid #5e6d6f}html.theme--documenter-dark .docstring>header code{background-color:transparent}html.theme--documenter-dark .docstring>header .docstring-article-toggle-button{min-width:1.1rem;padding:0.2rem 0.2rem 0.2rem 0}html.theme--documenter-dark .docstring>header .docstring-binding{margin-right:0.3em}html.theme--documenter-dark .docstring>header .docstring-category{margin-left:0.3em}html.theme--documenter-dark .docstring>section{position:relative;padding:.75rem .75rem;border-bottom:1px solid #5e6d6f}html.theme--documenter-dark .docstring>section:last-child{border-bottom:none}html.theme--documenter-dark .docstring>section>a.docs-sourcelink{transition:opacity 0.3s;opacity:0;position:absolute;right:.375rem;bottom:.375rem}html.theme--documenter-dark .docstring>section>a.docs-sourcelink:focus{opacity:1 !important}html.theme--documenter-dark .docstring:hover>section>a.docs-sourcelink{opacity:0.2}html.theme--documenter-dark .docstring:focus-within>section>a.docs-sourcelink{opacity:0.2}html.theme--documenter-dark .docstring>section:hover a.docs-sourcelink{opacity:1}html.theme--documenter-dark .documenter-example-output{background-color:#1f2424}html.theme--documenter-dark .outdated-warning-overlay{position:fixed;top:0;left:0;right:0;box-shadow:0 0 10px rgba(0,0,0,0.3);z-index:999;background-color:#282f2f;color:#fff;border-bottom:3px solid #9e1b0d;padding:10px 35px;text-align:center;font-size:15px}html.theme--documenter-dark .outdated-warning-overlay .outdated-warning-closer{position:absolute;top:calc(50% - 10px);right:18px;cursor:pointer;width:12px}html.theme--documenter-dark .outdated-warning-overlay a{color:#1abc9c}html.theme--documenter-dark .outdated-warning-overlay a:hover{color:#1dd2af}html.theme--documenter-dark .content pre{border:1px solid #5e6d6f}html.theme--documenter-dark .content code{font-weight:inherit}html.theme--documenter-dark .content a code{color:#1abc9c}html.theme--documenter-dark .content h1 code,html.theme--documenter-dark .content h2 code,html.theme--documenter-dark .content h3 code,html.theme--documenter-dark .content h4 code,html.theme--documenter-dark .content h5 code,html.theme--documenter-dark .content h6 code{color:#f2f2f2}html.theme--documenter-dark .content table{display:block;width:initial;max-width:100%;overflow-x:auto}html.theme--documenter-dark .content blockquote>ul:first-child,html.theme--documenter-dark .content blockquote>ol:first-child,html.theme--documenter-dark .content .admonition-body>ul:first-child,html.theme--documenter-dark .content .admonition-body>ol:first-child{margin-top:0}html.theme--documenter-dark pre,html.theme--documenter-dark code{font-variant-ligatures:no-contextual}html.theme--documenter-dark .breadcrumb a.is-disabled{cursor:default;pointer-events:none}html.theme--documenter-dark .breadcrumb a.is-disabled,html.theme--documenter-dark .breadcrumb a.is-disabled:hover{color:#f2f2f2}html.theme--documenter-dark .hljs{background:initial !important}html.theme--documenter-dark .katex .katex-mathml{top:0;right:0}html.theme--documenter-dark .katex-display,html.theme--documenter-dark mjx-container,html.theme--documenter-dark .MathJax_Display{margin:0.5em 0 !important}html.theme--documenter-dark html{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto}html.theme--documenter-dark li.no-marker{list-style:none}html.theme--documenter-dark #documenter .docs-main>article{overflow-wrap:break-word}html.theme--documenter-dark #documenter .docs-main>article .math-container{overflow-x:auto;overflow-y:hidden}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-main{max-width:52rem;margin-left:20rem;padding-right:1rem}}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main{width:100%}html.theme--documenter-dark #documenter .docs-main>article{max-width:52rem;margin-left:auto;margin-right:auto;margin-bottom:1rem;padding:0 1rem}html.theme--documenter-dark #documenter .docs-main>header,html.theme--documenter-dark #documenter .docs-main>nav{max-width:100%;width:100%;margin:0}}html.theme--documenter-dark #documenter .docs-main header.docs-navbar{background-color:#1f2424;border-bottom:1px solid #5e6d6f;z-index:2;min-height:4rem;margin-bottom:1rem;display:flex}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .breadcrumb{flex-grow:1}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-sidebar-button{display:block;font-size:1.5rem;padding-bottom:0.1rem;margin-right:1rem}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right{display:flex;white-space:nowrap;gap:1rem;align-items:center}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-icon,html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-label{display:inline-block}html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-label{padding:0;margin-left:0.3em}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main header.docs-navbar .docs-right .docs-navbar-link{margin-left:0.4rem;margin-right:0.4rem}}html.theme--documenter-dark #documenter .docs-main header.docs-navbar>*{margin:auto 0}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main header.docs-navbar{position:sticky;top:0;padding:0 1rem;transition-property:top, box-shadow;-webkit-transition-property:top, box-shadow;transition-duration:0.3s;-webkit-transition-duration:0.3s}html.theme--documenter-dark #documenter .docs-main header.docs-navbar.headroom--not-top{box-shadow:.2rem 0rem .4rem #171717;transition-duration:0.7s;-webkit-transition-duration:0.7s}html.theme--documenter-dark #documenter .docs-main header.docs-navbar.headroom--unpinned.headroom--not-top.headroom--not-bottom{top:-4.5rem;transition-duration:0.7s;-webkit-transition-duration:0.7s}}html.theme--documenter-dark #documenter .docs-main section.footnotes{border-top:1px solid #5e6d6f}html.theme--documenter-dark #documenter .docs-main section.footnotes li .tag:first-child,html.theme--documenter-dark #documenter .docs-main section.footnotes li .docstring>section>a.docs-sourcelink:first-child,html.theme--documenter-dark #documenter .docs-main section.footnotes li .content kbd:first-child,html.theme--documenter-dark .content #documenter .docs-main section.footnotes li kbd:first-child{margin-right:1em;margin-bottom:0.4em}html.theme--documenter-dark #documenter .docs-main .docs-footer{display:flex;flex-wrap:wrap;margin-left:0;margin-right:0;border-top:1px solid #5e6d6f;padding-top:1rem;padding-bottom:1rem}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-main .docs-footer{padding-left:1rem;padding-right:1rem}}html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-nextpage,html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-prevpage{flex-grow:1}html.theme--documenter-dark #documenter .docs-main .docs-footer .docs-footer-nextpage{text-align:right}html.theme--documenter-dark #documenter .docs-main .docs-footer .flexbox-break{flex-basis:100%;height:0}html.theme--documenter-dark #documenter .docs-main .docs-footer .footer-message{font-size:0.8em;margin:0.5em auto 0 auto;text-align:center}html.theme--documenter-dark #documenter .docs-sidebar{display:flex;flex-direction:column;color:#fff;background-color:#282f2f;border-right:1px solid #5e6d6f;padding:0;flex:0 0 18rem;z-index:5;font-size:1rem;position:fixed;left:-18rem;width:18rem;height:100%;transition:left 0.3s}html.theme--documenter-dark #documenter .docs-sidebar.visible{left:0;box-shadow:.4rem 0rem .8rem #171717}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-sidebar.visible{box-shadow:none}}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-sidebar{left:0;top:0}}html.theme--documenter-dark #documenter .docs-sidebar .docs-logo{margin-top:1rem;padding:0 1rem}html.theme--documenter-dark #documenter .docs-sidebar .docs-logo>img{max-height:6rem;margin:auto}html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name{flex-shrink:0;font-size:1.5rem;font-weight:700;text-align:center;white-space:nowrap;overflow:hidden;padding:0.5rem 0}html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name .docs-autofit{max-width:16.2rem}html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name a,html.theme--documenter-dark #documenter .docs-sidebar .docs-package-name a:hover{color:#fff}html.theme--documenter-dark #documenter .docs-sidebar .docs-version-selector{border-top:1px solid #5e6d6f;display:none;padding:0.5rem}html.theme--documenter-dark #documenter .docs-sidebar .docs-version-selector.visible{display:flex}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu{flex-grow:1;user-select:none;border-top:1px solid #5e6d6f;padding-bottom:1.5rem}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu>li>.tocitem{font-weight:bold}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu>li li{font-size:.95rem;margin-left:1em;border-left:1px solid #5e6d6f}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input.collapse-toggle{display:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.collapsed{display:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input:checked~ul.collapsed{display:block}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem{display:flex}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-label{flex-grow:2}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-size:.75rem;margin-left:1rem;margin-top:auto;margin-bottom:auto}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f054"}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu input:checked~label.tocitem .docs-chevron::before{content:"\f078"}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem{display:block;padding:0.5rem 0.5rem}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem,html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu .tocitem:hover{color:#fff;background:#282f2f}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu a.tocitem:hover,html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu label.tocitem:hover{color:#fff;background-color:#32393a}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active{border-top:1px solid #5e6d6f;border-bottom:1px solid #5e6d6f;background-color:#1f2424}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem,html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active .tocitem:hover{background-color:#1f2424;color:#fff}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu li.is-active ul.internal .tocitem:hover{background-color:#32393a;color:#fff}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu>li.is-active:first-child{border-top:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal{margin:0 0.5rem 0.5rem;border-top:1px solid #5e6d6f}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal li{font-size:.85rem;border-left:none;margin-left:0;margin-top:0.5rem}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem{width:100%;padding:0}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu ul.internal .tocitem::before{content:"⚬";margin-right:0.4em}html.theme--documenter-dark #documenter .docs-sidebar form.docs-search{margin:auto;margin-top:0.5rem;margin-bottom:0.5rem}html.theme--documenter-dark #documenter .docs-sidebar form.docs-search>input{width:14.4rem}html.theme--documenter-dark #documenter .docs-sidebar #documenter-search-query{color:#868c98;width:14.4rem;box-shadow:inset 0 1px 2px rgba(10,10,10,0.1)}@media screen and (min-width: 1056px){html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar{width:.3rem;background:none}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#3b4445}html.theme--documenter-dark #documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb:hover{background:#4e5a5c}}@media screen and (max-width: 1055px){html.theme--documenter-dark #documenter .docs-sidebar{overflow-y:auto;-webkit-overflow-scroll:touch}html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar{width:.3rem;background:none}html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#3b4445}html.theme--documenter-dark #documenter .docs-sidebar::-webkit-scrollbar-thumb:hover{background:#4e5a5c}}html.theme--documenter-dark kbd.search-modal-key-hints{border-radius:0.25rem;border:1px solid rgba(245,245,245,0.6);box-shadow:0 2px 0 1px rgba(245,245,245,0.6);cursor:default;font-size:0.9rem;line-height:1.5;min-width:0.75rem;text-align:center;padding:0.1rem 0.3rem;position:relative;top:-1px}html.theme--documenter-dark .search-min-width-50{min-width:50%}html.theme--documenter-dark .search-min-height-100{min-height:100%}html.theme--documenter-dark .search-modal-card-body{max-height:calc(100vh - 15rem)}html.theme--documenter-dark .search-result-link{border-radius:0.7em;transition:all 300ms}html.theme--documenter-dark .search-result-link:hover,html.theme--documenter-dark .search-result-link:focus{background-color:rgba(0,128,128,0.1)}html.theme--documenter-dark .search-result-link .property-search-result-badge,html.theme--documenter-dark .search-result-link .search-filter{transition:all 300ms}html.theme--documenter-dark .property-search-result-badge,html.theme--documenter-dark .search-filter{padding:0.15em 0.5em;font-size:0.8em;font-style:italic;text-transform:none !important;line-height:1.5;color:#f5f5f5;background-color:rgba(51,65,85,0.501961);border-radius:0.6rem}html.theme--documenter-dark .search-result-link:hover .property-search-result-badge,html.theme--documenter-dark .search-result-link:hover .search-filter,html.theme--documenter-dark .search-result-link:focus .property-search-result-badge,html.theme--documenter-dark .search-result-link:focus .search-filter{color:#333;background-color:#f1f5f9}html.theme--documenter-dark .search-filter{color:#333;background-color:#f5f5f5;transition:all 300ms}html.theme--documenter-dark .search-filter:hover,html.theme--documenter-dark .search-filter:focus{color:#333}html.theme--documenter-dark .search-filter-selected{color:#f5f5f5;background-color:rgba(139,0,139,0.5)}html.theme--documenter-dark .search-filter-selected:hover,html.theme--documenter-dark .search-filter-selected:focus{color:#f5f5f5}html.theme--documenter-dark .search-result-highlight{background-color:#ffdd57;color:black}html.theme--documenter-dark .search-divider{border-bottom:1px solid #5e6d6f}html.theme--documenter-dark .search-result-title{width:85%;color:#f5f5f5}html.theme--documenter-dark .search-result-code-title{font-size:0.875rem;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}html.theme--documenter-dark #search-modal .modal-card-body::-webkit-scrollbar,html.theme--documenter-dark #search-modal .filter-tabs::-webkit-scrollbar{height:10px;width:10px;background-color:transparent}html.theme--documenter-dark #search-modal .modal-card-body::-webkit-scrollbar-thumb,html.theme--documenter-dark #search-modal .filter-tabs::-webkit-scrollbar-thumb{background-color:gray;border-radius:1rem}html.theme--documenter-dark #search-modal .modal-card-body::-webkit-scrollbar-track,html.theme--documenter-dark #search-modal .filter-tabs::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,0.6);background-color:transparent}html.theme--documenter-dark .w-100{width:100%}html.theme--documenter-dark .gap-2{gap:0.5rem}html.theme--documenter-dark .gap-4{gap:1rem}html.theme--documenter-dark .gap-8{gap:2rem}html.theme--documenter-dark{background-color:#1f2424;font-size:16px;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}html.theme--documenter-dark .ansi span.sgr1{font-weight:bolder}html.theme--documenter-dark .ansi span.sgr2{font-weight:lighter}html.theme--documenter-dark .ansi span.sgr3{font-style:italic}html.theme--documenter-dark .ansi span.sgr4{text-decoration:underline}html.theme--documenter-dark .ansi span.sgr7{color:#1f2424;background-color:#fff}html.theme--documenter-dark .ansi span.sgr8{color:transparent}html.theme--documenter-dark .ansi span.sgr8 span{color:transparent}html.theme--documenter-dark .ansi span.sgr9{text-decoration:line-through}html.theme--documenter-dark .ansi span.sgr30{color:#242424}html.theme--documenter-dark .ansi span.sgr31{color:#f6705f}html.theme--documenter-dark .ansi span.sgr32{color:#4fb43a}html.theme--documenter-dark .ansi span.sgr33{color:#f4c72f}html.theme--documenter-dark .ansi span.sgr34{color:#7587f0}html.theme--documenter-dark .ansi span.sgr35{color:#bc89d3}html.theme--documenter-dark .ansi span.sgr36{color:#49b6ca}html.theme--documenter-dark .ansi span.sgr37{color:#b3bdbe}html.theme--documenter-dark .ansi span.sgr40{background-color:#242424}html.theme--documenter-dark .ansi span.sgr41{background-color:#f6705f}html.theme--documenter-dark .ansi span.sgr42{background-color:#4fb43a}html.theme--documenter-dark .ansi span.sgr43{background-color:#f4c72f}html.theme--documenter-dark .ansi span.sgr44{background-color:#7587f0}html.theme--documenter-dark .ansi span.sgr45{background-color:#bc89d3}html.theme--documenter-dark .ansi span.sgr46{background-color:#49b6ca}html.theme--documenter-dark .ansi span.sgr47{background-color:#b3bdbe}html.theme--documenter-dark .ansi span.sgr90{color:#92a0a2}html.theme--documenter-dark .ansi span.sgr91{color:#ff8674}html.theme--documenter-dark .ansi span.sgr92{color:#79d462}html.theme--documenter-dark .ansi span.sgr93{color:#ffe76b}html.theme--documenter-dark .ansi span.sgr94{color:#8a98ff}html.theme--documenter-dark .ansi span.sgr95{color:#d2a4e6}html.theme--documenter-dark .ansi span.sgr96{color:#6bc8db}html.theme--documenter-dark .ansi span.sgr97{color:#ecf0f1}html.theme--documenter-dark .ansi span.sgr100{background-color:#92a0a2}html.theme--documenter-dark .ansi span.sgr101{background-color:#ff8674}html.theme--documenter-dark .ansi span.sgr102{background-color:#79d462}html.theme--documenter-dark .ansi span.sgr103{background-color:#ffe76b}html.theme--documenter-dark .ansi span.sgr104{background-color:#8a98ff}html.theme--documenter-dark .ansi span.sgr105{background-color:#d2a4e6}html.theme--documenter-dark .ansi span.sgr106{background-color:#6bc8db}html.theme--documenter-dark .ansi span.sgr107{background-color:#ecf0f1}html.theme--documenter-dark code.language-julia-repl>span.hljs-meta{color:#4fb43a;font-weight:bolder}html.theme--documenter-dark .hljs{background:#2b2b2b;color:#f8f8f2}html.theme--documenter-dark .hljs-comment,html.theme--documenter-dark .hljs-quote{color:#d4d0ab}html.theme--documenter-dark .hljs-variable,html.theme--documenter-dark .hljs-template-variable,html.theme--documenter-dark .hljs-tag,html.theme--documenter-dark .hljs-name,html.theme--documenter-dark .hljs-selector-id,html.theme--documenter-dark .hljs-selector-class,html.theme--documenter-dark .hljs-regexp,html.theme--documenter-dark .hljs-deletion{color:#ffa07a}html.theme--documenter-dark .hljs-number,html.theme--documenter-dark .hljs-built_in,html.theme--documenter-dark .hljs-literal,html.theme--documenter-dark .hljs-type,html.theme--documenter-dark .hljs-params,html.theme--documenter-dark .hljs-meta,html.theme--documenter-dark .hljs-link{color:#f5ab35}html.theme--documenter-dark .hljs-attribute{color:#ffd700}html.theme--documenter-dark .hljs-string,html.theme--documenter-dark .hljs-symbol,html.theme--documenter-dark .hljs-bullet,html.theme--documenter-dark .hljs-addition{color:#abe338}html.theme--documenter-dark .hljs-title,html.theme--documenter-dark .hljs-section{color:#00e0e0}html.theme--documenter-dark .hljs-keyword,html.theme--documenter-dark .hljs-selector-tag{color:#dcc6e0}html.theme--documenter-dark .hljs-emphasis{font-style:italic}html.theme--documenter-dark .hljs-strong{font-weight:bold}@media screen and (-ms-high-contrast: active){html.theme--documenter-dark .hljs-addition,html.theme--documenter-dark .hljs-attribute,html.theme--documenter-dark .hljs-built_in,html.theme--documenter-dark .hljs-bullet,html.theme--documenter-dark .hljs-comment,html.theme--documenter-dark .hljs-link,html.theme--documenter-dark .hljs-literal,html.theme--documenter-dark .hljs-meta,html.theme--documenter-dark .hljs-number,html.theme--documenter-dark .hljs-params,html.theme--documenter-dark .hljs-string,html.theme--documenter-dark .hljs-symbol,html.theme--documenter-dark .hljs-type,html.theme--documenter-dark .hljs-quote{color:highlight}html.theme--documenter-dark .hljs-keyword,html.theme--documenter-dark .hljs-selector-tag{font-weight:bold}}html.theme--documenter-dark .hljs-subst{color:#f8f8f2} diff --git a/dev/assets/themes/documenter-light.css b/dev/assets/themes/documenter-light.css index 9b9a14b..60a317a 100644 --- a/dev/assets/themes/documenter-light.css +++ b/dev/assets/themes/documenter-light.css @@ -1,4 +1,4 @@ -@keyframes spinAround{from{transform:rotate(0deg)}to{transform:rotate(359deg)}}.tabs,.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis,.breadcrumb,.file,.button,.is-unselectable,.modal-close,.delete{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.navbar-link:not(.is-arrowless)::after,.select:not(.is-multiple):not(.is-loading)::after{border:3px solid rgba(0,0,0,0);border-radius:2px;border-right:0;border-top:0;content:" ";display:block;height:0.625em;margin-top:-0.4375em;pointer-events:none;position:absolute;top:50%;transform:rotate(-45deg);transform-origin:center;width:0.625em}.admonition:not(:last-child),.tabs:not(:last-child),.message:not(:last-child),.list:not(:last-child),.level:not(:last-child),.breadcrumb:not(:last-child),.highlight:not(:last-child),.block:not(:last-child),.title:not(:last-child),.subtitle:not(:last-child),.table-container:not(:last-child),.table:not(:last-child),.progress:not(:last-child),.notification:not(:last-child),.content:not(:last-child),.box:not(:last-child){margin-bottom:1.5rem}.modal-close,.delete{-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,0.2);border:none;border-radius:290486px;cursor:pointer;pointer-events:auto;display:inline-block;flex-grow:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:none;position:relative;vertical-align:top;width:20px}.modal-close::before,.delete::before,.modal-close::after,.delete::after{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}.modal-close::before,.delete::before{height:2px;width:50%}.modal-close::after,.delete::after{height:50%;width:2px}.modal-close:hover,.delete:hover,.modal-close:focus,.delete:focus{background-color:rgba(10,10,10,0.3)}.modal-close:active,.delete:active{background-color:rgba(10,10,10,0.4)}.is-small.modal-close,#documenter .docs-sidebar form.docs-search>input.modal-close,.is-small.delete,#documenter .docs-sidebar form.docs-search>input.delete{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}.is-medium.modal-close,.is-medium.delete{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}.is-large.modal-close,.is-large.delete{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}.control.is-loading::after,.select.is-loading::after,.loader,.button.is-loading::after{animation:spinAround 500ms infinite linear;border:2px solid #dbdbdb;border-radius:290486px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em}.hero-video,.modal-background,.modal,.image.is-square img,#documenter .docs-sidebar .docs-logo>img.is-square img,.image.is-square .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,.image.is-1by1 img,#documenter .docs-sidebar .docs-logo>img.is-1by1 img,.image.is-1by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,.image.is-5by4 img,#documenter .docs-sidebar .docs-logo>img.is-5by4 img,.image.is-5by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,.image.is-4by3 img,#documenter .docs-sidebar .docs-logo>img.is-4by3 img,.image.is-4by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,.image.is-3by2 img,#documenter .docs-sidebar .docs-logo>img.is-3by2 img,.image.is-3by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,.image.is-5by3 img,#documenter .docs-sidebar .docs-logo>img.is-5by3 img,.image.is-5by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,.image.is-16by9 img,#documenter .docs-sidebar .docs-logo>img.is-16by9 img,.image.is-16by9 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,.image.is-2by1 img,#documenter .docs-sidebar .docs-logo>img.is-2by1 img,.image.is-2by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,.image.is-3by1 img,#documenter .docs-sidebar .docs-logo>img.is-3by1 img,.image.is-3by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,.image.is-4by5 img,#documenter .docs-sidebar .docs-logo>img.is-4by5 img,.image.is-4by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,.image.is-3by4 img,#documenter .docs-sidebar .docs-logo>img.is-3by4 img,.image.is-3by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,.image.is-2by3 img,#documenter .docs-sidebar .docs-logo>img.is-2by3 img,.image.is-2by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,.image.is-3by5 img,#documenter .docs-sidebar .docs-logo>img.is-3by5 img,.image.is-3by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,.image.is-9by16 img,#documenter .docs-sidebar .docs-logo>img.is-9by16 img,.image.is-9by16 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,.image.is-1by2 img,#documenter .docs-sidebar .docs-logo>img.is-1by2 img,.image.is-1by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,.image.is-1by3 img,#documenter .docs-sidebar .docs-logo>img.is-1by3 img,.image.is-1by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio,.is-overlay{bottom:0;left:0;position:absolute;right:0;top:0}.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis,.file-cta,.file-name,.select select,.textarea,.input,#documenter .docs-sidebar form.docs-search>input,.button{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;border-radius:4px;box-shadow:none;display:inline-flex;font-size:1rem;height:2.25em;justify-content:flex-start;line-height:1.5;padding-bottom:calc(0.375em - 1px);padding-left:calc(0.625em - 1px);padding-right:calc(0.625em - 1px);padding-top:calc(0.375em - 1px);position:relative;vertical-align:top}.pagination-previous:focus,.pagination-next:focus,.pagination-link:focus,.pagination-ellipsis:focus,.file-cta:focus,.file-name:focus,.select select:focus,.textarea:focus,.input:focus,#documenter .docs-sidebar form.docs-search>input:focus,.button:focus,.is-focused.pagination-previous,.is-focused.pagination-next,.is-focused.pagination-link,.is-focused.pagination-ellipsis,.is-focused.file-cta,.is-focused.file-name,.select select.is-focused,.is-focused.textarea,.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-focused.button,.pagination-previous:active,.pagination-next:active,.pagination-link:active,.pagination-ellipsis:active,.file-cta:active,.file-name:active,.select select:active,.textarea:active,.input:active,#documenter .docs-sidebar form.docs-search>input:active,.button:active,.is-active.pagination-previous,.is-active.pagination-next,.is-active.pagination-link,.is-active.pagination-ellipsis,.is-active.file-cta,.is-active.file-name,.select select.is-active,.is-active.textarea,.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active,.is-active.button{outline:none}.pagination-previous[disabled],.pagination-next[disabled],.pagination-link[disabled],.pagination-ellipsis[disabled],.file-cta[disabled],.file-name[disabled],.select select[disabled],.textarea[disabled],.input[disabled],#documenter .docs-sidebar form.docs-search>input[disabled],.button[disabled],fieldset[disabled] .pagination-previous,fieldset[disabled] .pagination-next,fieldset[disabled] .pagination-link,fieldset[disabled] .pagination-ellipsis,fieldset[disabled] .file-cta,fieldset[disabled] .file-name,fieldset[disabled] .select select,.select fieldset[disabled] select,fieldset[disabled] .textarea,fieldset[disabled] .input,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input,fieldset[disabled] .button{cursor:not-allowed}/*! minireset.css v0.0.4 | MIT License | github.com/jgthms/minireset.css */html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,embed,iframe,object,video{height:auto;max-width:100%}audio{max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:left}html{background-color:#fff;font-size:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}article,aside,figure,footer,header,hgroup,section{display:block}body,button,input,select,textarea{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif}code,pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}body{color:#222;font-size:1em;font-weight:400;line-height:1.5}a{color:#2e63b8;cursor:pointer;text-decoration:none}a strong{color:currentColor}a:hover{color:#363636}code{background-color:rgba(0,0,0,0.05);color:#000;font-size:.875em;font-weight:normal;padding:.1em}hr{background-color:#f5f5f5;border:none;display:block;height:2px;margin:1.5rem 0}img{height:auto;max-width:100%}input[type="checkbox"],input[type="radio"]{vertical-align:baseline}small{font-size:.875em}span{font-style:inherit;font-weight:inherit}strong{color:#222;font-weight:700}fieldset{border:none}pre{-webkit-overflow-scrolling:touch;background-color:#f5f5f5;color:#222;font-size:.875em;overflow-x:auto;padding:1.25rem 1.5rem;white-space:pre;word-wrap:normal}pre code{background-color:transparent;color:currentColor;font-size:1em;padding:0}table td,table th{vertical-align:top}table td:not([align]),table th:not([align]){text-align:left}table th{color:#222}.is-clearfix::after{clear:both;content:" ";display:table}.is-pulled-left{float:left !important}.is-pulled-right{float:right !important}.is-clipped{overflow:hidden !important}.is-size-1{font-size:3rem !important}.is-size-2{font-size:2.5rem !important}.is-size-3{font-size:2rem !important}.is-size-4{font-size:1.5rem !important}.is-size-5{font-size:1.25rem !important}.is-size-6{font-size:1rem !important}.is-size-7,.docstring>section>a.docs-sourcelink{font-size:.75rem !important}@media screen and (max-width: 768px){.is-size-1-mobile{font-size:3rem !important}.is-size-2-mobile{font-size:2.5rem !important}.is-size-3-mobile{font-size:2rem !important}.is-size-4-mobile{font-size:1.5rem !important}.is-size-5-mobile{font-size:1.25rem !important}.is-size-6-mobile{font-size:1rem !important}.is-size-7-mobile{font-size:.75rem !important}}@media screen and (min-width: 769px),print{.is-size-1-tablet{font-size:3rem !important}.is-size-2-tablet{font-size:2.5rem !important}.is-size-3-tablet{font-size:2rem !important}.is-size-4-tablet{font-size:1.5rem !important}.is-size-5-tablet{font-size:1.25rem !important}.is-size-6-tablet{font-size:1rem !important}.is-size-7-tablet{font-size:.75rem !important}}@media screen and (max-width: 1055px){.is-size-1-touch{font-size:3rem !important}.is-size-2-touch{font-size:2.5rem !important}.is-size-3-touch{font-size:2rem !important}.is-size-4-touch{font-size:1.5rem !important}.is-size-5-touch{font-size:1.25rem !important}.is-size-6-touch{font-size:1rem !important}.is-size-7-touch{font-size:.75rem !important}}@media screen and (min-width: 1056px){.is-size-1-desktop{font-size:3rem !important}.is-size-2-desktop{font-size:2.5rem !important}.is-size-3-desktop{font-size:2rem !important}.is-size-4-desktop{font-size:1.5rem !important}.is-size-5-desktop{font-size:1.25rem !important}.is-size-6-desktop{font-size:1rem !important}.is-size-7-desktop{font-size:.75rem !important}}@media screen and (min-width: 1216px){.is-size-1-widescreen{font-size:3rem !important}.is-size-2-widescreen{font-size:2.5rem !important}.is-size-3-widescreen{font-size:2rem !important}.is-size-4-widescreen{font-size:1.5rem !important}.is-size-5-widescreen{font-size:1.25rem !important}.is-size-6-widescreen{font-size:1rem !important}.is-size-7-widescreen{font-size:.75rem !important}}@media screen and (min-width: 1408px){.is-size-1-fullhd{font-size:3rem !important}.is-size-2-fullhd{font-size:2.5rem !important}.is-size-3-fullhd{font-size:2rem !important}.is-size-4-fullhd{font-size:1.5rem !important}.is-size-5-fullhd{font-size:1.25rem !important}.is-size-6-fullhd{font-size:1rem !important}.is-size-7-fullhd{font-size:.75rem !important}}.has-text-centered{text-align:center !important}.has-text-justified{text-align:justify !important}.has-text-left{text-align:left !important}.has-text-right{text-align:right !important}@media screen and (max-width: 768px){.has-text-centered-mobile{text-align:center !important}}@media screen and (min-width: 769px),print{.has-text-centered-tablet{text-align:center !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-centered-tablet-only{text-align:center !important}}@media screen and (max-width: 1055px){.has-text-centered-touch{text-align:center !important}}@media screen and (min-width: 1056px){.has-text-centered-desktop{text-align:center !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-centered-desktop-only{text-align:center !important}}@media screen and (min-width: 1216px){.has-text-centered-widescreen{text-align:center !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-centered-widescreen-only{text-align:center !important}}@media screen and (min-width: 1408px){.has-text-centered-fullhd{text-align:center !important}}@media screen and (max-width: 768px){.has-text-justified-mobile{text-align:justify !important}}@media screen and (min-width: 769px),print{.has-text-justified-tablet{text-align:justify !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-justified-tablet-only{text-align:justify !important}}@media screen and (max-width: 1055px){.has-text-justified-touch{text-align:justify !important}}@media screen and (min-width: 1056px){.has-text-justified-desktop{text-align:justify !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-justified-desktop-only{text-align:justify !important}}@media screen and (min-width: 1216px){.has-text-justified-widescreen{text-align:justify !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-justified-widescreen-only{text-align:justify !important}}@media screen and (min-width: 1408px){.has-text-justified-fullhd{text-align:justify !important}}@media screen and (max-width: 768px){.has-text-left-mobile{text-align:left !important}}@media screen and (min-width: 769px),print{.has-text-left-tablet{text-align:left !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-left-tablet-only{text-align:left !important}}@media screen and (max-width: 1055px){.has-text-left-touch{text-align:left !important}}@media screen and (min-width: 1056px){.has-text-left-desktop{text-align:left !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-left-desktop-only{text-align:left !important}}@media screen and (min-width: 1216px){.has-text-left-widescreen{text-align:left !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-left-widescreen-only{text-align:left !important}}@media screen and (min-width: 1408px){.has-text-left-fullhd{text-align:left !important}}@media screen and (max-width: 768px){.has-text-right-mobile{text-align:right !important}}@media screen and (min-width: 769px),print{.has-text-right-tablet{text-align:right !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-right-tablet-only{text-align:right !important}}@media screen and (max-width: 1055px){.has-text-right-touch{text-align:right !important}}@media screen and (min-width: 1056px){.has-text-right-desktop{text-align:right !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-right-desktop-only{text-align:right !important}}@media screen and (min-width: 1216px){.has-text-right-widescreen{text-align:right !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-right-widescreen-only{text-align:right !important}}@media screen and (min-width: 1408px){.has-text-right-fullhd{text-align:right !important}}.is-capitalized{text-transform:capitalize !important}.is-lowercase{text-transform:lowercase !important}.is-uppercase{text-transform:uppercase !important}.is-italic{font-style:italic !important}.has-text-white{color:#fff !important}a.has-text-white:hover,a.has-text-white:focus{color:#e6e6e6 !important}.has-background-white{background-color:#fff !important}.has-text-black{color:#0a0a0a !important}a.has-text-black:hover,a.has-text-black:focus{color:#000 !important}.has-background-black{background-color:#0a0a0a !important}.has-text-light{color:#f5f5f5 !important}a.has-text-light:hover,a.has-text-light:focus{color:#dbdbdb !important}.has-background-light{background-color:#f5f5f5 !important}.has-text-dark{color:#363636 !important}a.has-text-dark:hover,a.has-text-dark:focus{color:#1c1c1c !important}.has-background-dark{background-color:#363636 !important}.has-text-primary{color:#4eb5de !important}a.has-text-primary:hover,a.has-text-primary:focus{color:#27a1d2 !important}.has-background-primary{background-color:#4eb5de !important}.has-text-link{color:#2e63b8 !important}a.has-text-link:hover,a.has-text-link:focus{color:#244d8f !important}.has-background-link{background-color:#2e63b8 !important}.has-text-info{color:#209cee !important}a.has-text-info:hover,a.has-text-info:focus{color:#1081cb !important}.has-background-info{background-color:#209cee !important}.has-text-success{color:#22c35b !important}a.has-text-success:hover,a.has-text-success:focus{color:#1a9847 !important}.has-background-success{background-color:#22c35b !important}.has-text-warning{color:#ffdd57 !important}a.has-text-warning:hover,a.has-text-warning:focus{color:#ffd324 !important}.has-background-warning{background-color:#ffdd57 !important}.has-text-danger{color:#da0b00 !important}a.has-text-danger:hover,a.has-text-danger:focus{color:#a70800 !important}.has-background-danger{background-color:#da0b00 !important}.has-text-black-bis{color:#121212 !important}.has-background-black-bis{background-color:#121212 !important}.has-text-black-ter{color:#242424 !important}.has-background-black-ter{background-color:#242424 !important}.has-text-grey-darker{color:#363636 !important}.has-background-grey-darker{background-color:#363636 !important}.has-text-grey-dark{color:#4a4a4a !important}.has-background-grey-dark{background-color:#4a4a4a !important}.has-text-grey{color:#6b6b6b !important}.has-background-grey{background-color:#6b6b6b !important}.has-text-grey-light{color:#b5b5b5 !important}.has-background-grey-light{background-color:#b5b5b5 !important}.has-text-grey-lighter{color:#dbdbdb !important}.has-background-grey-lighter{background-color:#dbdbdb !important}.has-text-white-ter{color:#f5f5f5 !important}.has-background-white-ter{background-color:#f5f5f5 !important}.has-text-white-bis{color:#fafafa !important}.has-background-white-bis{background-color:#fafafa !important}.has-text-weight-light{font-weight:300 !important}.has-text-weight-normal{font-weight:400 !important}.has-text-weight-medium{font-weight:500 !important}.has-text-weight-semibold{font-weight:600 !important}.has-text-weight-bold{font-weight:700 !important}.is-family-primary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-secondary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-sans-serif{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-monospace{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-family-code{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-block{display:block !important}@media screen and (max-width: 768px){.is-block-mobile{display:block !important}}@media screen and (min-width: 769px),print{.is-block-tablet{display:block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-block-tablet-only{display:block !important}}@media screen and (max-width: 1055px){.is-block-touch{display:block !important}}@media screen and (min-width: 1056px){.is-block-desktop{display:block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-block-desktop-only{display:block !important}}@media screen and (min-width: 1216px){.is-block-widescreen{display:block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-block-widescreen-only{display:block !important}}@media screen and (min-width: 1408px){.is-block-fullhd{display:block !important}}.is-flex{display:flex !important}@media screen and (max-width: 768px){.is-flex-mobile{display:flex !important}}@media screen and (min-width: 769px),print{.is-flex-tablet{display:flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-flex-tablet-only{display:flex !important}}@media screen and (max-width: 1055px){.is-flex-touch{display:flex !important}}@media screen and (min-width: 1056px){.is-flex-desktop{display:flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-flex-desktop-only{display:flex !important}}@media screen and (min-width: 1216px){.is-flex-widescreen{display:flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-flex-widescreen-only{display:flex !important}}@media screen and (min-width: 1408px){.is-flex-fullhd{display:flex !important}}.is-inline{display:inline !important}@media screen and (max-width: 768px){.is-inline-mobile{display:inline !important}}@media screen and (min-width: 769px),print{.is-inline-tablet{display:inline !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-tablet-only{display:inline !important}}@media screen and (max-width: 1055px){.is-inline-touch{display:inline !important}}@media screen and (min-width: 1056px){.is-inline-desktop{display:inline !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-desktop-only{display:inline !important}}@media screen and (min-width: 1216px){.is-inline-widescreen{display:inline !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-widescreen-only{display:inline !important}}@media screen and (min-width: 1408px){.is-inline-fullhd{display:inline !important}}.is-inline-block{display:inline-block !important}@media screen and (max-width: 768px){.is-inline-block-mobile{display:inline-block !important}}@media screen and (min-width: 769px),print{.is-inline-block-tablet{display:inline-block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-block-tablet-only{display:inline-block !important}}@media screen and (max-width: 1055px){.is-inline-block-touch{display:inline-block !important}}@media screen and (min-width: 1056px){.is-inline-block-desktop{display:inline-block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-block-desktop-only{display:inline-block !important}}@media screen and (min-width: 1216px){.is-inline-block-widescreen{display:inline-block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-block-widescreen-only{display:inline-block !important}}@media screen and (min-width: 1408px){.is-inline-block-fullhd{display:inline-block !important}}.is-inline-flex{display:inline-flex !important}@media screen and (max-width: 768px){.is-inline-flex-mobile{display:inline-flex !important}}@media screen and (min-width: 769px),print{.is-inline-flex-tablet{display:inline-flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-flex-tablet-only{display:inline-flex !important}}@media screen and (max-width: 1055px){.is-inline-flex-touch{display:inline-flex !important}}@media screen and (min-width: 1056px){.is-inline-flex-desktop{display:inline-flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-flex-desktop-only{display:inline-flex !important}}@media screen and (min-width: 1216px){.is-inline-flex-widescreen{display:inline-flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-flex-widescreen-only{display:inline-flex !important}}@media screen and (min-width: 1408px){.is-inline-flex-fullhd{display:inline-flex !important}}.is-hidden{display:none !important}.is-sr-only{border:none !important;clip:rect(0, 0, 0, 0) !important;height:0.01em !important;overflow:hidden !important;padding:0 !important;position:absolute !important;white-space:nowrap !important;width:0.01em !important}@media screen and (max-width: 768px){.is-hidden-mobile{display:none !important}}@media screen and (min-width: 769px),print{.is-hidden-tablet{display:none !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-hidden-tablet-only{display:none !important}}@media screen and (max-width: 1055px){.is-hidden-touch{display:none !important}}@media screen and (min-width: 1056px){.is-hidden-desktop{display:none !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-hidden-desktop-only{display:none !important}}@media screen and (min-width: 1216px){.is-hidden-widescreen{display:none !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-hidden-widescreen-only{display:none !important}}@media screen and (min-width: 1408px){.is-hidden-fullhd{display:none !important}}.is-invisible{visibility:hidden !important}@media screen and (max-width: 768px){.is-invisible-mobile{visibility:hidden !important}}@media screen and (min-width: 769px),print{.is-invisible-tablet{visibility:hidden !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-invisible-tablet-only{visibility:hidden !important}}@media screen and (max-width: 1055px){.is-invisible-touch{visibility:hidden !important}}@media screen and (min-width: 1056px){.is-invisible-desktop{visibility:hidden !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-invisible-desktop-only{visibility:hidden !important}}@media screen and (min-width: 1216px){.is-invisible-widescreen{visibility:hidden !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-invisible-widescreen-only{visibility:hidden !important}}@media screen and (min-width: 1408px){.is-invisible-fullhd{visibility:hidden !important}}.is-marginless{margin:0 !important}.is-paddingless{padding:0 !important}.is-radiusless{border-radius:0 !important}.is-shadowless{box-shadow:none !important}.is-relative{position:relative !important}.box{background-color:#fff;border-radius:6px;box-shadow:0 2px 3px rgba(10,10,10,0.1),0 0 0 1px rgba(10,10,10,0.1);color:#222;display:block;padding:1.25rem}a.box:hover,a.box:focus{box-shadow:0 2px 3px rgba(10,10,10,0.1),0 0 0 1px #2e63b8}a.box:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2),0 0 0 1px #2e63b8}.button{background-color:#fff;border-color:#dbdbdb;border-width:1px;color:#363636;cursor:pointer;justify-content:center;padding-bottom:calc(0.375em - 1px);padding-left:.75em;padding-right:.75em;padding-top:calc(0.375em - 1px);text-align:center;white-space:nowrap}.button strong{color:inherit}.button .icon,.button .icon.is-small,.button #documenter .docs-sidebar form.docs-search>input.icon,#documenter .docs-sidebar .button form.docs-search>input.icon,.button .icon.is-medium,.button .icon.is-large{height:1.5em;width:1.5em}.button .icon:first-child:not(:last-child){margin-left:calc(-0.375em - 1px);margin-right:0.1875em}.button .icon:last-child:not(:first-child){margin-left:0.1875em;margin-right:calc(-0.375em - 1px)}.button .icon:first-child:last-child{margin-left:calc(-0.375em - 1px);margin-right:calc(-0.375em - 1px)}.button:hover,.button.is-hovered{border-color:#b5b5b5;color:#363636}.button:focus,.button.is-focused{border-color:#3c5dcd;color:#363636}.button:focus:not(:active),.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.button:active,.button.is-active{border-color:#4a4a4a;color:#363636}.button.is-text{background-color:transparent;border-color:transparent;color:#222;text-decoration:underline}.button.is-text:hover,.button.is-text.is-hovered,.button.is-text:focus,.button.is-text.is-focused{background-color:#f5f5f5;color:#222}.button.is-text:active,.button.is-text.is-active{background-color:#e8e8e8;color:#222}.button.is-text[disabled],fieldset[disabled] .button.is-text{background-color:transparent;border-color:transparent;box-shadow:none}.button.is-white{background-color:#fff;border-color:transparent;color:#0a0a0a}.button.is-white:hover,.button.is-white.is-hovered{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}.button.is-white:focus,.button.is-white.is-focused{border-color:transparent;color:#0a0a0a}.button.is-white:focus:not(:active),.button.is-white.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}.button.is-white:active,.button.is-white.is-active{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}.button.is-white[disabled],fieldset[disabled] .button.is-white{background-color:#fff;border-color:transparent;box-shadow:none}.button.is-white.is-inverted{background-color:#0a0a0a;color:#fff}.button.is-white.is-inverted:hover,.button.is-white.is-inverted.is-hovered{background-color:#000}.button.is-white.is-inverted[disabled],fieldset[disabled] .button.is-white.is-inverted{background-color:#0a0a0a;border-color:transparent;box-shadow:none;color:#fff}.button.is-white.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-white.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-white.is-outlined:hover,.button.is-white.is-outlined.is-hovered,.button.is-white.is-outlined:focus,.button.is-white.is-outlined.is-focused{background-color:#fff;border-color:#fff;color:#0a0a0a}.button.is-white.is-outlined.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-white.is-outlined.is-loading:hover::after,.button.is-white.is-outlined.is-loading.is-hovered::after,.button.is-white.is-outlined.is-loading:focus::after,.button.is-white.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-white.is-outlined[disabled],fieldset[disabled] .button.is-white.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}.button.is-white.is-inverted.is-outlined:hover,.button.is-white.is-inverted.is-outlined.is-hovered,.button.is-white.is-inverted.is-outlined:focus,.button.is-white.is-inverted.is-outlined.is-focused{background-color:#0a0a0a;color:#fff}.button.is-white.is-inverted.is-outlined.is-loading:hover::after,.button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-white.is-inverted.is-outlined.is-loading:focus::after,.button.is-white.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-white.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}.button.is-black{background-color:#0a0a0a;border-color:transparent;color:#fff}.button.is-black:hover,.button.is-black.is-hovered{background-color:#040404;border-color:transparent;color:#fff}.button.is-black:focus,.button.is-black.is-focused{border-color:transparent;color:#fff}.button.is-black:focus:not(:active),.button.is-black.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}.button.is-black:active,.button.is-black.is-active{background-color:#000;border-color:transparent;color:#fff}.button.is-black[disabled],fieldset[disabled] .button.is-black{background-color:#0a0a0a;border-color:transparent;box-shadow:none}.button.is-black.is-inverted{background-color:#fff;color:#0a0a0a}.button.is-black.is-inverted:hover,.button.is-black.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-black.is-inverted[disabled],fieldset[disabled] .button.is-black.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#0a0a0a}.button.is-black.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}.button.is-black.is-outlined:hover,.button.is-black.is-outlined.is-hovered,.button.is-black.is-outlined:focus,.button.is-black.is-outlined.is-focused{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.button.is-black.is-outlined.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-black.is-outlined.is-loading:hover::after,.button.is-black.is-outlined.is-loading.is-hovered::after,.button.is-black.is-outlined.is-loading:focus::after,.button.is-black.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-black.is-outlined[disabled],fieldset[disabled] .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}.button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-black.is-inverted.is-outlined:hover,.button.is-black.is-inverted.is-outlined.is-hovered,.button.is-black.is-inverted.is-outlined:focus,.button.is-black.is-inverted.is-outlined.is-focused{background-color:#fff;color:#0a0a0a}.button.is-black.is-inverted.is-outlined.is-loading:hover::after,.button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-black.is-inverted.is-outlined.is-loading:focus::after,.button.is-black.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-black.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-light{background-color:#f5f5f5;border-color:transparent;color:#363636}.button.is-light:hover,.button.is-light.is-hovered{background-color:#eee;border-color:transparent;color:#363636}.button.is-light:focus,.button.is-light.is-focused{border-color:transparent;color:#363636}.button.is-light:focus:not(:active),.button.is-light.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}.button.is-light:active,.button.is-light.is-active{background-color:#e8e8e8;border-color:transparent;color:#363636}.button.is-light[disabled],fieldset[disabled] .button.is-light{background-color:#f5f5f5;border-color:transparent;box-shadow:none}.button.is-light.is-inverted{background-color:#363636;color:#f5f5f5}.button.is-light.is-inverted:hover,.button.is-light.is-inverted.is-hovered{background-color:#292929}.button.is-light.is-inverted[disabled],fieldset[disabled] .button.is-light.is-inverted{background-color:#363636;border-color:transparent;box-shadow:none;color:#f5f5f5}.button.is-light.is-loading::after{border-color:transparent transparent #363636 #363636 !important}.button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;color:#f5f5f5}.button.is-light.is-outlined:hover,.button.is-light.is-outlined.is-hovered,.button.is-light.is-outlined:focus,.button.is-light.is-outlined.is-focused{background-color:#f5f5f5;border-color:#f5f5f5;color:#363636}.button.is-light.is-outlined.is-loading::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}.button.is-light.is-outlined.is-loading:hover::after,.button.is-light.is-outlined.is-loading.is-hovered::after,.button.is-light.is-outlined.is-loading:focus::after,.button.is-light.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #363636 #363636 !important}.button.is-light.is-outlined[disabled],fieldset[disabled] .button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;box-shadow:none;color:#f5f5f5}.button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:#363636;color:#363636}.button.is-light.is-inverted.is-outlined:hover,.button.is-light.is-inverted.is-outlined.is-hovered,.button.is-light.is-inverted.is-outlined:focus,.button.is-light.is-inverted.is-outlined.is-focused{background-color:#363636;color:#f5f5f5}.button.is-light.is-inverted.is-outlined.is-loading:hover::after,.button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-light.is-inverted.is-outlined.is-loading:focus::after,.button.is-light.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}.button.is-light.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:#363636;box-shadow:none;color:#363636}.button.is-dark,.content kbd.button{background-color:#363636;border-color:transparent;color:#f5f5f5}.button.is-dark:hover,.content kbd.button:hover,.button.is-dark.is-hovered,.content kbd.button.is-hovered{background-color:#2f2f2f;border-color:transparent;color:#f5f5f5}.button.is-dark:focus,.content kbd.button:focus,.button.is-dark.is-focused,.content kbd.button.is-focused{border-color:transparent;color:#f5f5f5}.button.is-dark:focus:not(:active),.content kbd.button:focus:not(:active),.button.is-dark.is-focused:not(:active),.content kbd.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(54,54,54,0.25)}.button.is-dark:active,.content kbd.button:active,.button.is-dark.is-active,.content kbd.button.is-active{background-color:#292929;border-color:transparent;color:#f5f5f5}.button.is-dark[disabled],.content kbd.button[disabled],fieldset[disabled] .button.is-dark,fieldset[disabled] .content kbd.button,.content fieldset[disabled] kbd.button{background-color:#363636;border-color:transparent;box-shadow:none}.button.is-dark.is-inverted,.content kbd.button.is-inverted{background-color:#f5f5f5;color:#363636}.button.is-dark.is-inverted:hover,.content kbd.button.is-inverted:hover,.button.is-dark.is-inverted.is-hovered,.content kbd.button.is-inverted.is-hovered{background-color:#e8e8e8}.button.is-dark.is-inverted[disabled],.content kbd.button.is-inverted[disabled],fieldset[disabled] .button.is-dark.is-inverted,fieldset[disabled] .content kbd.button.is-inverted,.content fieldset[disabled] kbd.button.is-inverted{background-color:#f5f5f5;border-color:transparent;box-shadow:none;color:#363636}.button.is-dark.is-loading::after,.content kbd.button.is-loading::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}.button.is-dark.is-outlined,.content kbd.button.is-outlined{background-color:transparent;border-color:#363636;color:#363636}.button.is-dark.is-outlined:hover,.content kbd.button.is-outlined:hover,.button.is-dark.is-outlined.is-hovered,.content kbd.button.is-outlined.is-hovered,.button.is-dark.is-outlined:focus,.content kbd.button.is-outlined:focus,.button.is-dark.is-outlined.is-focused,.content kbd.button.is-outlined.is-focused{background-color:#363636;border-color:#363636;color:#f5f5f5}.button.is-dark.is-outlined.is-loading::after,.content kbd.button.is-outlined.is-loading::after{border-color:transparent transparent #363636 #363636 !important}.button.is-dark.is-outlined.is-loading:hover::after,.content kbd.button.is-outlined.is-loading:hover::after,.button.is-dark.is-outlined.is-loading.is-hovered::after,.content kbd.button.is-outlined.is-loading.is-hovered::after,.button.is-dark.is-outlined.is-loading:focus::after,.content kbd.button.is-outlined.is-loading:focus::after,.button.is-dark.is-outlined.is-loading.is-focused::after,.content kbd.button.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}.button.is-dark.is-outlined[disabled],.content kbd.button.is-outlined[disabled],fieldset[disabled] .button.is-dark.is-outlined,fieldset[disabled] .content kbd.button.is-outlined,.content fieldset[disabled] kbd.button.is-outlined{background-color:transparent;border-color:#363636;box-shadow:none;color:#363636}.button.is-dark.is-inverted.is-outlined,.content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#f5f5f5;color:#f5f5f5}.button.is-dark.is-inverted.is-outlined:hover,.content kbd.button.is-inverted.is-outlined:hover,.button.is-dark.is-inverted.is-outlined.is-hovered,.content kbd.button.is-inverted.is-outlined.is-hovered,.button.is-dark.is-inverted.is-outlined:focus,.content kbd.button.is-inverted.is-outlined:focus,.button.is-dark.is-inverted.is-outlined.is-focused,.content kbd.button.is-inverted.is-outlined.is-focused{background-color:#f5f5f5;color:#363636}.button.is-dark.is-inverted.is-outlined.is-loading:hover::after,.content kbd.button.is-inverted.is-outlined.is-loading:hover::after,.button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after,.content kbd.button.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-dark.is-inverted.is-outlined.is-loading:focus::after,.content kbd.button.is-inverted.is-outlined.is-loading:focus::after,.button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after,.content kbd.button.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #363636 #363636 !important}.button.is-dark.is-inverted.is-outlined[disabled],.content kbd.button.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-dark.is-inverted.is-outlined,fieldset[disabled] .content kbd.button.is-inverted.is-outlined,.content fieldset[disabled] kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#f5f5f5;box-shadow:none;color:#f5f5f5}.button.is-primary,.docstring>section>a.button.docs-sourcelink{background-color:#4eb5de;border-color:transparent;color:#fff}.button.is-primary:hover,.docstring>section>a.button.docs-sourcelink:hover,.button.is-primary.is-hovered,.docstring>section>a.button.is-hovered.docs-sourcelink{background-color:#43b1dc;border-color:transparent;color:#fff}.button.is-primary:focus,.docstring>section>a.button.docs-sourcelink:focus,.button.is-primary.is-focused,.docstring>section>a.button.is-focused.docs-sourcelink{border-color:transparent;color:#fff}.button.is-primary:focus:not(:active),.docstring>section>a.button.docs-sourcelink:focus:not(:active),.button.is-primary.is-focused:not(:active),.docstring>section>a.button.is-focused.docs-sourcelink:not(:active){box-shadow:0 0 0 0.125em rgba(78,181,222,0.25)}.button.is-primary:active,.docstring>section>a.button.docs-sourcelink:active,.button.is-primary.is-active,.docstring>section>a.button.is-active.docs-sourcelink{background-color:#39acda;border-color:transparent;color:#fff}.button.is-primary[disabled],.docstring>section>a.button.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary,fieldset[disabled] .docstring>section>a.button.docs-sourcelink{background-color:#4eb5de;border-color:transparent;box-shadow:none}.button.is-primary.is-inverted,.docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;color:#4eb5de}.button.is-primary.is-inverted:hover,.docstring>section>a.button.is-inverted.docs-sourcelink:hover,.button.is-primary.is-inverted.is-hovered,.docstring>section>a.button.is-inverted.is-hovered.docs-sourcelink{background-color:#f2f2f2}.button.is-primary.is-inverted[disabled],.docstring>section>a.button.is-inverted.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary.is-inverted,fieldset[disabled] .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;border-color:transparent;box-shadow:none;color:#4eb5de}.button.is-primary.is-loading::after,.docstring>section>a.button.is-loading.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}.button.is-primary.is-outlined,.docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#4eb5de;color:#4eb5de}.button.is-primary.is-outlined:hover,.docstring>section>a.button.is-outlined.docs-sourcelink:hover,.button.is-primary.is-outlined.is-hovered,.docstring>section>a.button.is-outlined.is-hovered.docs-sourcelink,.button.is-primary.is-outlined:focus,.docstring>section>a.button.is-outlined.docs-sourcelink:focus,.button.is-primary.is-outlined.is-focused,.docstring>section>a.button.is-outlined.is-focused.docs-sourcelink{background-color:#4eb5de;border-color:#4eb5de;color:#fff}.button.is-primary.is-outlined.is-loading::after,.docstring>section>a.button.is-outlined.is-loading.docs-sourcelink::after{border-color:transparent transparent #4eb5de #4eb5de !important}.button.is-primary.is-outlined.is-loading:hover::after,.docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:hover::after,.button.is-primary.is-outlined.is-loading.is-hovered::after,.docstring>section>a.button.is-outlined.is-loading.is-hovered.docs-sourcelink::after,.button.is-primary.is-outlined.is-loading:focus::after,.docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:focus::after,.button.is-primary.is-outlined.is-loading.is-focused::after,.docstring>section>a.button.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}.button.is-primary.is-outlined[disabled],.docstring>section>a.button.is-outlined.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary.is-outlined,fieldset[disabled] .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#4eb5de;box-shadow:none;color:#4eb5de}.button.is-primary.is-inverted.is-outlined,.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;color:#fff}.button.is-primary.is-inverted.is-outlined:hover,.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:hover,.button.is-primary.is-inverted.is-outlined.is-hovered,.docstring>section>a.button.is-inverted.is-outlined.is-hovered.docs-sourcelink,.button.is-primary.is-inverted.is-outlined:focus,.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:focus,.button.is-primary.is-inverted.is-outlined.is-focused,.docstring>section>a.button.is-inverted.is-outlined.is-focused.docs-sourcelink{background-color:#fff;color:#4eb5de}.button.is-primary.is-inverted.is-outlined.is-loading:hover::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:hover::after,.button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.is-hovered.docs-sourcelink::after,.button.is-primary.is-inverted.is-outlined.is-loading:focus::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:focus::after,.button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #4eb5de #4eb5de !important}.button.is-primary.is-inverted.is-outlined[disabled],.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary.is-inverted.is-outlined,fieldset[disabled] .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-link{background-color:#2e63b8;border-color:transparent;color:#fff}.button.is-link:hover,.button.is-link.is-hovered{background-color:#2b5eae;border-color:transparent;color:#fff}.button.is-link:focus,.button.is-link.is-focused{border-color:transparent;color:#fff}.button.is-link:focus:not(:active),.button.is-link.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.button.is-link:active,.button.is-link.is-active{background-color:#2958a4;border-color:transparent;color:#fff}.button.is-link[disabled],fieldset[disabled] .button.is-link{background-color:#2e63b8;border-color:transparent;box-shadow:none}.button.is-link.is-inverted{background-color:#fff;color:#2e63b8}.button.is-link.is-inverted:hover,.button.is-link.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-link.is-inverted[disabled],fieldset[disabled] .button.is-link.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#2e63b8}.button.is-link.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-link.is-outlined{background-color:transparent;border-color:#2e63b8;color:#2e63b8}.button.is-link.is-outlined:hover,.button.is-link.is-outlined.is-hovered,.button.is-link.is-outlined:focus,.button.is-link.is-outlined.is-focused{background-color:#2e63b8;border-color:#2e63b8;color:#fff}.button.is-link.is-outlined.is-loading::after{border-color:transparent transparent #2e63b8 #2e63b8 !important}.button.is-link.is-outlined.is-loading:hover::after,.button.is-link.is-outlined.is-loading.is-hovered::after,.button.is-link.is-outlined.is-loading:focus::after,.button.is-link.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-link.is-outlined[disabled],fieldset[disabled] .button.is-link.is-outlined{background-color:transparent;border-color:#2e63b8;box-shadow:none;color:#2e63b8}.button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-link.is-inverted.is-outlined:hover,.button.is-link.is-inverted.is-outlined.is-hovered,.button.is-link.is-inverted.is-outlined:focus,.button.is-link.is-inverted.is-outlined.is-focused{background-color:#fff;color:#2e63b8}.button.is-link.is-inverted.is-outlined.is-loading:hover::after,.button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-link.is-inverted.is-outlined.is-loading:focus::after,.button.is-link.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #2e63b8 #2e63b8 !important}.button.is-link.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-info{background-color:#209cee;border-color:transparent;color:#fff}.button.is-info:hover,.button.is-info.is-hovered{background-color:#1497ed;border-color:transparent;color:#fff}.button.is-info:focus,.button.is-info.is-focused{border-color:transparent;color:#fff}.button.is-info:focus:not(:active),.button.is-info.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(32,156,238,0.25)}.button.is-info:active,.button.is-info.is-active{background-color:#1190e3;border-color:transparent;color:#fff}.button.is-info[disabled],fieldset[disabled] .button.is-info{background-color:#209cee;border-color:transparent;box-shadow:none}.button.is-info.is-inverted{background-color:#fff;color:#209cee}.button.is-info.is-inverted:hover,.button.is-info.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-info.is-inverted[disabled],fieldset[disabled] .button.is-info.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#209cee}.button.is-info.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-info.is-outlined{background-color:transparent;border-color:#209cee;color:#209cee}.button.is-info.is-outlined:hover,.button.is-info.is-outlined.is-hovered,.button.is-info.is-outlined:focus,.button.is-info.is-outlined.is-focused{background-color:#209cee;border-color:#209cee;color:#fff}.button.is-info.is-outlined.is-loading::after{border-color:transparent transparent #209cee #209cee !important}.button.is-info.is-outlined.is-loading:hover::after,.button.is-info.is-outlined.is-loading.is-hovered::after,.button.is-info.is-outlined.is-loading:focus::after,.button.is-info.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-info.is-outlined[disabled],fieldset[disabled] .button.is-info.is-outlined{background-color:transparent;border-color:#209cee;box-shadow:none;color:#209cee}.button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-info.is-inverted.is-outlined:hover,.button.is-info.is-inverted.is-outlined.is-hovered,.button.is-info.is-inverted.is-outlined:focus,.button.is-info.is-inverted.is-outlined.is-focused{background-color:#fff;color:#209cee}.button.is-info.is-inverted.is-outlined.is-loading:hover::after,.button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-info.is-inverted.is-outlined.is-loading:focus::after,.button.is-info.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #209cee #209cee !important}.button.is-info.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-success{background-color:#22c35b;border-color:transparent;color:#fff}.button.is-success:hover,.button.is-success.is-hovered{background-color:#20b856;border-color:transparent;color:#fff}.button.is-success:focus,.button.is-success.is-focused{border-color:transparent;color:#fff}.button.is-success:focus:not(:active),.button.is-success.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(34,195,91,0.25)}.button.is-success:active,.button.is-success.is-active{background-color:#1ead51;border-color:transparent;color:#fff}.button.is-success[disabled],fieldset[disabled] .button.is-success{background-color:#22c35b;border-color:transparent;box-shadow:none}.button.is-success.is-inverted{background-color:#fff;color:#22c35b}.button.is-success.is-inverted:hover,.button.is-success.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-success.is-inverted[disabled],fieldset[disabled] .button.is-success.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#22c35b}.button.is-success.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-success.is-outlined{background-color:transparent;border-color:#22c35b;color:#22c35b}.button.is-success.is-outlined:hover,.button.is-success.is-outlined.is-hovered,.button.is-success.is-outlined:focus,.button.is-success.is-outlined.is-focused{background-color:#22c35b;border-color:#22c35b;color:#fff}.button.is-success.is-outlined.is-loading::after{border-color:transparent transparent #22c35b #22c35b !important}.button.is-success.is-outlined.is-loading:hover::after,.button.is-success.is-outlined.is-loading.is-hovered::after,.button.is-success.is-outlined.is-loading:focus::after,.button.is-success.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-success.is-outlined[disabled],fieldset[disabled] .button.is-success.is-outlined{background-color:transparent;border-color:#22c35b;box-shadow:none;color:#22c35b}.button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-success.is-inverted.is-outlined:hover,.button.is-success.is-inverted.is-outlined.is-hovered,.button.is-success.is-inverted.is-outlined:focus,.button.is-success.is-inverted.is-outlined.is-focused{background-color:#fff;color:#22c35b}.button.is-success.is-inverted.is-outlined.is-loading:hover::after,.button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-success.is-inverted.is-outlined.is-loading:focus::after,.button.is-success.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #22c35b #22c35b !important}.button.is-success.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-warning{background-color:#ffdd57;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning:hover,.button.is-warning.is-hovered{background-color:#ffda4a;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning:focus,.button.is-warning.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning:focus:not(:active),.button.is-warning.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,221,87,0.25)}.button.is-warning:active,.button.is-warning.is-active{background-color:#ffd83e;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning[disabled],fieldset[disabled] .button.is-warning{background-color:#ffdd57;border-color:transparent;box-shadow:none}.button.is-warning.is-inverted{background-color:rgba(0,0,0,0.7);color:#ffdd57}.button.is-warning.is-inverted:hover,.button.is-warning.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}.button.is-warning.is-inverted[disabled],fieldset[disabled] .button.is-warning.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#ffdd57}.button.is-warning.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-warning.is-outlined{background-color:transparent;border-color:#ffdd57;color:#ffdd57}.button.is-warning.is-outlined:hover,.button.is-warning.is-outlined.is-hovered,.button.is-warning.is-outlined:focus,.button.is-warning.is-outlined.is-focused{background-color:#ffdd57;border-color:#ffdd57;color:rgba(0,0,0,0.7)}.button.is-warning.is-outlined.is-loading::after{border-color:transparent transparent #ffdd57 #ffdd57 !important}.button.is-warning.is-outlined.is-loading:hover::after,.button.is-warning.is-outlined.is-loading.is-hovered::after,.button.is-warning.is-outlined.is-loading:focus::after,.button.is-warning.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-warning.is-outlined[disabled],fieldset[disabled] .button.is-warning.is-outlined{background-color:transparent;border-color:#ffdd57;box-shadow:none;color:#ffdd57}.button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}.button.is-warning.is-inverted.is-outlined:hover,.button.is-warning.is-inverted.is-outlined.is-hovered,.button.is-warning.is-inverted.is-outlined:focus,.button.is-warning.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#ffdd57}.button.is-warning.is-inverted.is-outlined.is-loading:hover::after,.button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-warning.is-inverted.is-outlined.is-loading:focus::after,.button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #ffdd57 #ffdd57 !important}.button.is-warning.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}.button.is-danger{background-color:#da0b00;border-color:transparent;color:#fff}.button.is-danger:hover,.button.is-danger.is-hovered{background-color:#cd0a00;border-color:transparent;color:#fff}.button.is-danger:focus,.button.is-danger.is-focused{border-color:transparent;color:#fff}.button.is-danger:focus:not(:active),.button.is-danger.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(218,11,0,0.25)}.button.is-danger:active,.button.is-danger.is-active{background-color:#c10a00;border-color:transparent;color:#fff}.button.is-danger[disabled],fieldset[disabled] .button.is-danger{background-color:#da0b00;border-color:transparent;box-shadow:none}.button.is-danger.is-inverted{background-color:#fff;color:#da0b00}.button.is-danger.is-inverted:hover,.button.is-danger.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-danger.is-inverted[disabled],fieldset[disabled] .button.is-danger.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#da0b00}.button.is-danger.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-danger.is-outlined{background-color:transparent;border-color:#da0b00;color:#da0b00}.button.is-danger.is-outlined:hover,.button.is-danger.is-outlined.is-hovered,.button.is-danger.is-outlined:focus,.button.is-danger.is-outlined.is-focused{background-color:#da0b00;border-color:#da0b00;color:#fff}.button.is-danger.is-outlined.is-loading::after{border-color:transparent transparent #da0b00 #da0b00 !important}.button.is-danger.is-outlined.is-loading:hover::after,.button.is-danger.is-outlined.is-loading.is-hovered::after,.button.is-danger.is-outlined.is-loading:focus::after,.button.is-danger.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-danger.is-outlined[disabled],fieldset[disabled] .button.is-danger.is-outlined{background-color:transparent;border-color:#da0b00;box-shadow:none;color:#da0b00}.button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-danger.is-inverted.is-outlined:hover,.button.is-danger.is-inverted.is-outlined.is-hovered,.button.is-danger.is-inverted.is-outlined:focus,.button.is-danger.is-inverted.is-outlined.is-focused{background-color:#fff;color:#da0b00}.button.is-danger.is-inverted.is-outlined.is-loading:hover::after,.button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-danger.is-inverted.is-outlined.is-loading:focus::after,.button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #da0b00 #da0b00 !important}.button.is-danger.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-small,#documenter .docs-sidebar form.docs-search>input.button{border-radius:2px;font-size:.75rem}.button.is-normal{font-size:1rem}.button.is-medium{font-size:1.25rem}.button.is-large{font-size:1.5rem}.button[disabled],fieldset[disabled] .button{background-color:#fff;border-color:#dbdbdb;box-shadow:none;opacity:.5}.button.is-fullwidth{display:flex;width:100%}.button.is-loading{color:transparent !important;pointer-events:none}.button.is-loading::after{position:absolute;left:calc(50% - (1em / 2));top:calc(50% - (1em / 2));position:absolute !important}.button.is-static{background-color:#f5f5f5;border-color:#dbdbdb;color:#6b6b6b;box-shadow:none;pointer-events:none}.button.is-rounded,#documenter .docs-sidebar form.docs-search>input.button{border-radius:290486px;padding-left:1em;padding-right:1em}.buttons{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}.buttons .button{margin-bottom:0.5rem}.buttons .button:not(:last-child):not(.is-fullwidth){margin-right:0.5rem}.buttons:last-child{margin-bottom:-0.5rem}.buttons:not(:last-child){margin-bottom:1rem}.buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large){border-radius:2px;font-size:.75rem}.buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large){font-size:1.25rem}.buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium){font-size:1.5rem}.buttons.has-addons .button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.buttons.has-addons .button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.buttons.has-addons .button:last-child{margin-right:0}.buttons.has-addons .button:hover,.buttons.has-addons .button.is-hovered{z-index:2}.buttons.has-addons .button:focus,.buttons.has-addons .button.is-focused,.buttons.has-addons .button:active,.buttons.has-addons .button.is-active,.buttons.has-addons .button.is-selected{z-index:3}.buttons.has-addons .button:focus:hover,.buttons.has-addons .button.is-focused:hover,.buttons.has-addons .button:active:hover,.buttons.has-addons .button.is-active:hover,.buttons.has-addons .button.is-selected:hover{z-index:4}.buttons.has-addons .button.is-expanded{flex-grow:1;flex-shrink:1}.buttons.is-centered{justify-content:center}.buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}.buttons.is-right{justify-content:flex-end}.buttons.is-right:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}.container{flex-grow:1;margin:0 auto;position:relative;width:auto}@media screen and (min-width: 1056px){.container{max-width:992px}.container.is-fluid{margin-left:32px;margin-right:32px;max-width:none}}@media screen and (max-width: 1215px){.container.is-widescreen{max-width:1152px}}@media screen and (max-width: 1407px){.container.is-fullhd{max-width:1344px}}@media screen and (min-width: 1216px){.container{max-width:1152px}}@media screen and (min-width: 1408px){.container{max-width:1344px}}.content li+li{margin-top:0.25em}.content p:not(:last-child),.content dl:not(:last-child),.content ol:not(:last-child),.content ul:not(:last-child),.content blockquote:not(:last-child),.content pre:not(:last-child),.content table:not(:last-child){margin-bottom:1em}.content h1,.content h2,.content h3,.content h4,.content h5,.content h6{color:#222;font-weight:600;line-height:1.125}.content h1{font-size:2em;margin-bottom:0.5em}.content h1:not(:first-child){margin-top:1em}.content h2{font-size:1.75em;margin-bottom:0.5714em}.content h2:not(:first-child){margin-top:1.1428em}.content h3{font-size:1.5em;margin-bottom:0.6666em}.content h3:not(:first-child){margin-top:1.3333em}.content h4{font-size:1.25em;margin-bottom:0.8em}.content h5{font-size:1.125em;margin-bottom:0.8888em}.content h6{font-size:1em;margin-bottom:1em}.content blockquote{background-color:#f5f5f5;border-left:5px solid #dbdbdb;padding:1.25em 1.5em}.content ol{list-style-position:outside;margin-left:2em;margin-top:1em}.content ol:not([type]){list-style-type:decimal}.content ol.is-lower-alpha:not([type]){list-style-type:lower-alpha}.content ol.is-lower-roman:not([type]){list-style-type:lower-roman}.content ol.is-upper-alpha:not([type]){list-style-type:upper-alpha}.content ol.is-upper-roman:not([type]){list-style-type:upper-roman}.content ul{list-style:disc outside;margin-left:2em;margin-top:1em}.content ul ul{list-style-type:circle;margin-top:0.5em}.content ul ul ul{list-style-type:square}.content dd{margin-left:2em}.content figure{margin-left:2em;margin-right:2em;text-align:center}.content figure:not(:first-child){margin-top:2em}.content figure:not(:last-child){margin-bottom:2em}.content figure img{display:inline-block}.content figure figcaption{font-style:italic}.content pre{-webkit-overflow-scrolling:touch;overflow-x:auto;padding:0;white-space:pre;word-wrap:normal}.content sup,.content sub{font-size:75%}.content table{width:100%}.content table td,.content table th{border:1px solid #dbdbdb;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}.content table th{color:#222}.content table th:not([align]){text-align:left}.content table thead td,.content table thead th{border-width:0 0 2px;color:#222}.content table tfoot td,.content table tfoot th{border-width:2px 0 0;color:#222}.content table tbody tr:last-child td,.content table tbody tr:last-child th{border-bottom-width:0}.content .tabs li+li{margin-top:0}.content.is-small,#documenter .docs-sidebar form.docs-search>input.content{font-size:.75rem}.content.is-medium{font-size:1.25rem}.content.is-large{font-size:1.5rem}.icon{align-items:center;display:inline-flex;justify-content:center;height:1.5rem;width:1.5rem}.icon.is-small,#documenter .docs-sidebar form.docs-search>input.icon{height:1rem;width:1rem}.icon.is-medium{height:2rem;width:2rem}.icon.is-large{height:3rem;width:3rem}.image,#documenter .docs-sidebar .docs-logo>img{display:block;position:relative}.image img,#documenter .docs-sidebar .docs-logo>img img{display:block;height:auto;width:100%}.image img.is-rounded,#documenter .docs-sidebar .docs-logo>img img.is-rounded{border-radius:290486px}.image.is-square img,#documenter .docs-sidebar .docs-logo>img.is-square img,.image.is-square .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,.image.is-1by1 img,#documenter .docs-sidebar .docs-logo>img.is-1by1 img,.image.is-1by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,.image.is-5by4 img,#documenter .docs-sidebar .docs-logo>img.is-5by4 img,.image.is-5by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,.image.is-4by3 img,#documenter .docs-sidebar .docs-logo>img.is-4by3 img,.image.is-4by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,.image.is-3by2 img,#documenter .docs-sidebar .docs-logo>img.is-3by2 img,.image.is-3by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,.image.is-5by3 img,#documenter .docs-sidebar .docs-logo>img.is-5by3 img,.image.is-5by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,.image.is-16by9 img,#documenter .docs-sidebar .docs-logo>img.is-16by9 img,.image.is-16by9 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,.image.is-2by1 img,#documenter .docs-sidebar .docs-logo>img.is-2by1 img,.image.is-2by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,.image.is-3by1 img,#documenter .docs-sidebar .docs-logo>img.is-3by1 img,.image.is-3by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,.image.is-4by5 img,#documenter .docs-sidebar .docs-logo>img.is-4by5 img,.image.is-4by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,.image.is-3by4 img,#documenter .docs-sidebar .docs-logo>img.is-3by4 img,.image.is-3by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,.image.is-2by3 img,#documenter .docs-sidebar .docs-logo>img.is-2by3 img,.image.is-2by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,.image.is-3by5 img,#documenter .docs-sidebar .docs-logo>img.is-3by5 img,.image.is-3by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,.image.is-9by16 img,#documenter .docs-sidebar .docs-logo>img.is-9by16 img,.image.is-9by16 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,.image.is-1by2 img,#documenter .docs-sidebar .docs-logo>img.is-1by2 img,.image.is-1by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,.image.is-1by3 img,#documenter .docs-sidebar .docs-logo>img.is-1by3 img,.image.is-1by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio{height:100%;width:100%}.image.is-square,#documenter .docs-sidebar .docs-logo>img.is-square,.image.is-1by1,#documenter .docs-sidebar .docs-logo>img.is-1by1{padding-top:100%}.image.is-5by4,#documenter .docs-sidebar .docs-logo>img.is-5by4{padding-top:80%}.image.is-4by3,#documenter .docs-sidebar .docs-logo>img.is-4by3{padding-top:75%}.image.is-3by2,#documenter .docs-sidebar .docs-logo>img.is-3by2{padding-top:66.6666%}.image.is-5by3,#documenter .docs-sidebar .docs-logo>img.is-5by3{padding-top:60%}.image.is-16by9,#documenter .docs-sidebar .docs-logo>img.is-16by9{padding-top:56.25%}.image.is-2by1,#documenter .docs-sidebar .docs-logo>img.is-2by1{padding-top:50%}.image.is-3by1,#documenter .docs-sidebar .docs-logo>img.is-3by1{padding-top:33.3333%}.image.is-4by5,#documenter .docs-sidebar .docs-logo>img.is-4by5{padding-top:125%}.image.is-3by4,#documenter .docs-sidebar .docs-logo>img.is-3by4{padding-top:133.3333%}.image.is-2by3,#documenter .docs-sidebar .docs-logo>img.is-2by3{padding-top:150%}.image.is-3by5,#documenter .docs-sidebar .docs-logo>img.is-3by5{padding-top:166.6666%}.image.is-9by16,#documenter .docs-sidebar .docs-logo>img.is-9by16{padding-top:177.7777%}.image.is-1by2,#documenter .docs-sidebar .docs-logo>img.is-1by2{padding-top:200%}.image.is-1by3,#documenter .docs-sidebar .docs-logo>img.is-1by3{padding-top:300%}.image.is-16x16,#documenter .docs-sidebar .docs-logo>img.is-16x16{height:16px;width:16px}.image.is-24x24,#documenter .docs-sidebar .docs-logo>img.is-24x24{height:24px;width:24px}.image.is-32x32,#documenter .docs-sidebar .docs-logo>img.is-32x32{height:32px;width:32px}.image.is-48x48,#documenter .docs-sidebar .docs-logo>img.is-48x48{height:48px;width:48px}.image.is-64x64,#documenter .docs-sidebar .docs-logo>img.is-64x64{height:64px;width:64px}.image.is-96x96,#documenter .docs-sidebar .docs-logo>img.is-96x96{height:96px;width:96px}.image.is-128x128,#documenter .docs-sidebar .docs-logo>img.is-128x128{height:128px;width:128px}.notification{background-color:#f5f5f5;border-radius:4px;padding:1.25rem 2.5rem 1.25rem 1.5rem;position:relative}.notification a:not(.button):not(.dropdown-item){color:currentColor;text-decoration:underline}.notification strong{color:currentColor}.notification code,.notification pre{background:#fff}.notification pre code{background:transparent}.notification>.delete{position:absolute;right:0.5rem;top:0.5rem}.notification .title,.notification .subtitle,.notification .content{color:currentColor}.notification.is-white{background-color:#fff;color:#0a0a0a}.notification.is-black{background-color:#0a0a0a;color:#fff}.notification.is-light{background-color:#f5f5f5;color:#363636}.notification.is-dark,.content kbd.notification{background-color:#363636;color:#f5f5f5}.notification.is-primary,.docstring>section>a.notification.docs-sourcelink{background-color:#4eb5de;color:#fff}.notification.is-link{background-color:#2e63b8;color:#fff}.notification.is-info{background-color:#209cee;color:#fff}.notification.is-success{background-color:#22c35b;color:#fff}.notification.is-warning{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.notification.is-danger{background-color:#da0b00;color:#fff}.progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:290486px;display:block;height:1rem;overflow:hidden;padding:0;width:100%}.progress::-webkit-progress-bar{background-color:#dbdbdb}.progress::-webkit-progress-value{background-color:#222}.progress::-moz-progress-bar{background-color:#222}.progress::-ms-fill{background-color:#222;border:none}.progress.is-white::-webkit-progress-value{background-color:#fff}.progress.is-white::-moz-progress-bar{background-color:#fff}.progress.is-white::-ms-fill{background-color:#fff}.progress.is-white:indeterminate{background-image:linear-gradient(to right, #fff 30%, #dbdbdb 30%)}.progress.is-black::-webkit-progress-value{background-color:#0a0a0a}.progress.is-black::-moz-progress-bar{background-color:#0a0a0a}.progress.is-black::-ms-fill{background-color:#0a0a0a}.progress.is-black:indeterminate{background-image:linear-gradient(to right, #0a0a0a 30%, #dbdbdb 30%)}.progress.is-light::-webkit-progress-value{background-color:#f5f5f5}.progress.is-light::-moz-progress-bar{background-color:#f5f5f5}.progress.is-light::-ms-fill{background-color:#f5f5f5}.progress.is-light:indeterminate{background-image:linear-gradient(to right, #f5f5f5 30%, #dbdbdb 30%)}.progress.is-dark::-webkit-progress-value,.content kbd.progress::-webkit-progress-value{background-color:#363636}.progress.is-dark::-moz-progress-bar,.content kbd.progress::-moz-progress-bar{background-color:#363636}.progress.is-dark::-ms-fill,.content kbd.progress::-ms-fill{background-color:#363636}.progress.is-dark:indeterminate,.content kbd.progress:indeterminate{background-image:linear-gradient(to right, #363636 30%, #dbdbdb 30%)}.progress.is-primary::-webkit-progress-value,.docstring>section>a.progress.docs-sourcelink::-webkit-progress-value{background-color:#4eb5de}.progress.is-primary::-moz-progress-bar,.docstring>section>a.progress.docs-sourcelink::-moz-progress-bar{background-color:#4eb5de}.progress.is-primary::-ms-fill,.docstring>section>a.progress.docs-sourcelink::-ms-fill{background-color:#4eb5de}.progress.is-primary:indeterminate,.docstring>section>a.progress.docs-sourcelink:indeterminate{background-image:linear-gradient(to right, #4eb5de 30%, #dbdbdb 30%)}.progress.is-link::-webkit-progress-value{background-color:#2e63b8}.progress.is-link::-moz-progress-bar{background-color:#2e63b8}.progress.is-link::-ms-fill{background-color:#2e63b8}.progress.is-link:indeterminate{background-image:linear-gradient(to right, #2e63b8 30%, #dbdbdb 30%)}.progress.is-info::-webkit-progress-value{background-color:#209cee}.progress.is-info::-moz-progress-bar{background-color:#209cee}.progress.is-info::-ms-fill{background-color:#209cee}.progress.is-info:indeterminate{background-image:linear-gradient(to right, #209cee 30%, #dbdbdb 30%)}.progress.is-success::-webkit-progress-value{background-color:#22c35b}.progress.is-success::-moz-progress-bar{background-color:#22c35b}.progress.is-success::-ms-fill{background-color:#22c35b}.progress.is-success:indeterminate{background-image:linear-gradient(to right, #22c35b 30%, #dbdbdb 30%)}.progress.is-warning::-webkit-progress-value{background-color:#ffdd57}.progress.is-warning::-moz-progress-bar{background-color:#ffdd57}.progress.is-warning::-ms-fill{background-color:#ffdd57}.progress.is-warning:indeterminate{background-image:linear-gradient(to right, #ffdd57 30%, #dbdbdb 30%)}.progress.is-danger::-webkit-progress-value{background-color:#da0b00}.progress.is-danger::-moz-progress-bar{background-color:#da0b00}.progress.is-danger::-ms-fill{background-color:#da0b00}.progress.is-danger:indeterminate{background-image:linear-gradient(to right, #da0b00 30%, #dbdbdb 30%)}.progress:indeterminate{animation-duration:1.5s;animation-iteration-count:infinite;animation-name:moveIndeterminate;animation-timing-function:linear;background-color:#dbdbdb;background-image:linear-gradient(to right, #222 30%, #dbdbdb 30%);background-position:top left;background-repeat:no-repeat;background-size:150% 150%}.progress:indeterminate::-webkit-progress-bar{background-color:transparent}.progress:indeterminate::-moz-progress-bar{background-color:transparent}.progress.is-small,#documenter .docs-sidebar form.docs-search>input.progress{height:.75rem}.progress.is-medium{height:1.25rem}.progress.is-large{height:1.5rem}@keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}.table{background-color:#fff;color:#363636}.table td,.table th{border:1px solid #dbdbdb;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}.table td.is-white,.table th.is-white{background-color:#fff;border-color:#fff;color:#0a0a0a}.table td.is-black,.table th.is-black{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.table td.is-light,.table th.is-light{background-color:#f5f5f5;border-color:#f5f5f5;color:#363636}.table td.is-dark,.table th.is-dark{background-color:#363636;border-color:#363636;color:#f5f5f5}.table td.is-primary,.table th.is-primary{background-color:#4eb5de;border-color:#4eb5de;color:#fff}.table td.is-link,.table th.is-link{background-color:#2e63b8;border-color:#2e63b8;color:#fff}.table td.is-info,.table th.is-info{background-color:#209cee;border-color:#209cee;color:#fff}.table td.is-success,.table th.is-success{background-color:#22c35b;border-color:#22c35b;color:#fff}.table td.is-warning,.table th.is-warning{background-color:#ffdd57;border-color:#ffdd57;color:rgba(0,0,0,0.7)}.table td.is-danger,.table th.is-danger{background-color:#da0b00;border-color:#da0b00;color:#fff}.table td.is-narrow,.table th.is-narrow{white-space:nowrap;width:1%}.table td.is-selected,.table th.is-selected{background-color:#4eb5de;color:#fff}.table td.is-selected a,.table td.is-selected strong,.table th.is-selected a,.table th.is-selected strong{color:currentColor}.table th{color:#222}.table th:not([align]){text-align:left}.table tr.is-selected{background-color:#4eb5de;color:#fff}.table tr.is-selected a,.table tr.is-selected strong{color:currentColor}.table tr.is-selected td,.table tr.is-selected th{border-color:#fff;color:currentColor}.table thead{background-color:rgba(0,0,0,0)}.table thead td,.table thead th{border-width:0 0 2px;color:#222}.table tfoot{background-color:rgba(0,0,0,0)}.table tfoot td,.table tfoot th{border-width:2px 0 0;color:#222}.table tbody{background-color:rgba(0,0,0,0)}.table tbody tr:last-child td,.table tbody tr:last-child th{border-bottom-width:0}.table.is-bordered td,.table.is-bordered th{border-width:1px}.table.is-bordered tr:last-child td,.table.is-bordered tr:last-child th{border-bottom-width:1px}.table.is-fullwidth{width:100%}.table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#fafafa}.table.is-hoverable.is-striped tbody tr:not(.is-selected):hover{background-color:#fafafa}.table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even){background-color:#f5f5f5}.table.is-narrow td,.table.is-narrow th{padding:0.25em 0.5em}.table.is-striped tbody tr:not(.is-selected):nth-child(even){background-color:#fafafa}.table-container{-webkit-overflow-scrolling:touch;overflow:auto;overflow-y:hidden;max-width:100%}.tags{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}.tags .tag,.tags .content kbd,.content .tags kbd,.tags .docstring>section>a.docs-sourcelink{margin-bottom:0.5rem}.tags .tag:not(:last-child),.tags .content kbd:not(:last-child),.content .tags kbd:not(:last-child),.tags .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:0.5rem}.tags:last-child{margin-bottom:-0.5rem}.tags:not(:last-child){margin-bottom:1rem}.tags.are-medium .tag:not(.is-normal):not(.is-large),.tags.are-medium .content kbd:not(.is-normal):not(.is-large),.content .tags.are-medium kbd:not(.is-normal):not(.is-large),.tags.are-medium .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-large){font-size:1rem}.tags.are-large .tag:not(.is-normal):not(.is-medium),.tags.are-large .content kbd:not(.is-normal):not(.is-medium),.content .tags.are-large kbd:not(.is-normal):not(.is-medium),.tags.are-large .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-medium){font-size:1.25rem}.tags.is-centered{justify-content:center}.tags.is-centered .tag,.tags.is-centered .content kbd,.content .tags.is-centered kbd,.tags.is-centered .docstring>section>a.docs-sourcelink{margin-right:0.25rem;margin-left:0.25rem}.tags.is-right{justify-content:flex-end}.tags.is-right .tag:not(:first-child),.tags.is-right .content kbd:not(:first-child),.content .tags.is-right kbd:not(:first-child),.tags.is-right .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0.5rem}.tags.is-right .tag:not(:last-child),.tags.is-right .content kbd:not(:last-child),.content .tags.is-right kbd:not(:last-child),.tags.is-right .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:0}.tags.has-addons .tag,.tags.has-addons .content kbd,.content .tags.has-addons kbd,.tags.has-addons .docstring>section>a.docs-sourcelink{margin-right:0}.tags.has-addons .tag:not(:first-child),.tags.has-addons .content kbd:not(:first-child),.content .tags.has-addons kbd:not(:first-child),.tags.has-addons .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0;border-bottom-left-radius:0;border-top-left-radius:0}.tags.has-addons .tag:not(:last-child),.tags.has-addons .content kbd:not(:last-child),.content .tags.has-addons kbd:not(:last-child),.tags.has-addons .docstring>section>a.docs-sourcelink:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.tag:not(body),.content kbd:not(body),.docstring>section>a.docs-sourcelink:not(body){align-items:center;background-color:#f5f5f5;border-radius:4px;color:#222;display:inline-flex;font-size:.75rem;height:2em;justify-content:center;line-height:1.5;padding-left:0.75em;padding-right:0.75em;white-space:nowrap}.tag:not(body) .delete,.content kbd:not(body) .delete,.docstring>section>a.docs-sourcelink:not(body) .delete{margin-left:0.25rem;margin-right:-0.375rem}.tag.is-white:not(body),.content kbd.is-white:not(body),.docstring>section>a.docs-sourcelink.is-white:not(body){background-color:#fff;color:#0a0a0a}.tag.is-black:not(body),.content kbd.is-black:not(body),.docstring>section>a.docs-sourcelink.is-black:not(body){background-color:#0a0a0a;color:#fff}.tag.is-light:not(body),.content kbd.is-light:not(body),.docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#f5f5f5;color:#363636}.tag.is-dark:not(body),.content kbd:not(body),.docstring>section>a.docs-sourcelink.is-dark:not(body),.content .docstring>section>kbd:not(body){background-color:#363636;color:#f5f5f5}.tag.is-primary:not(body),.content kbd.is-primary:not(body),.docstring>section>a.docs-sourcelink:not(body){background-color:#4eb5de;color:#fff}.tag.is-link:not(body),.content kbd.is-link:not(body),.docstring>section>a.docs-sourcelink.is-link:not(body){background-color:#2e63b8;color:#fff}.tag.is-info:not(body),.content kbd.is-info:not(body),.docstring>section>a.docs-sourcelink.is-info:not(body){background-color:#209cee;color:#fff}.tag.is-success:not(body),.content kbd.is-success:not(body),.docstring>section>a.docs-sourcelink.is-success:not(body){background-color:#22c35b;color:#fff}.tag.is-warning:not(body),.content kbd.is-warning:not(body),.docstring>section>a.docs-sourcelink.is-warning:not(body){background-color:#ffdd57;color:rgba(0,0,0,0.7)}.tag.is-danger:not(body),.content kbd.is-danger:not(body),.docstring>section>a.docs-sourcelink.is-danger:not(body){background-color:#da0b00;color:#fff}.tag.is-normal:not(body),.content kbd.is-normal:not(body),.docstring>section>a.docs-sourcelink.is-normal:not(body){font-size:.75rem}.tag.is-medium:not(body),.content kbd.is-medium:not(body),.docstring>section>a.docs-sourcelink.is-medium:not(body){font-size:1rem}.tag.is-large:not(body),.content kbd.is-large:not(body),.docstring>section>a.docs-sourcelink.is-large:not(body){font-size:1.25rem}.tag:not(body) .icon:first-child:not(:last-child),.content kbd:not(body) .icon:first-child:not(:last-child),.docstring>section>a.docs-sourcelink:not(body) .icon:first-child:not(:last-child){margin-left:-0.375em;margin-right:0.1875em}.tag:not(body) .icon:last-child:not(:first-child),.content kbd:not(body) .icon:last-child:not(:first-child),.docstring>section>a.docs-sourcelink:not(body) .icon:last-child:not(:first-child){margin-left:0.1875em;margin-right:-0.375em}.tag:not(body) .icon:first-child:last-child,.content kbd:not(body) .icon:first-child:last-child,.docstring>section>a.docs-sourcelink:not(body) .icon:first-child:last-child{margin-left:-0.375em;margin-right:-0.375em}.tag.is-delete:not(body),.content kbd.is-delete:not(body),.docstring>section>a.docs-sourcelink.is-delete:not(body){margin-left:1px;padding:0;position:relative;width:2em}.tag.is-delete:not(body)::before,.content kbd.is-delete:not(body)::before,.docstring>section>a.docs-sourcelink.is-delete:not(body)::before,.tag.is-delete:not(body)::after,.content kbd.is-delete:not(body)::after,.docstring>section>a.docs-sourcelink.is-delete:not(body)::after{background-color:currentColor;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}.tag.is-delete:not(body)::before,.content kbd.is-delete:not(body)::before,.docstring>section>a.docs-sourcelink.is-delete:not(body)::before{height:1px;width:50%}.tag.is-delete:not(body)::after,.content kbd.is-delete:not(body)::after,.docstring>section>a.docs-sourcelink.is-delete:not(body)::after{height:50%;width:1px}.tag.is-delete:not(body):hover,.content kbd.is-delete:not(body):hover,.docstring>section>a.docs-sourcelink.is-delete:not(body):hover,.tag.is-delete:not(body):focus,.content kbd.is-delete:not(body):focus,.docstring>section>a.docs-sourcelink.is-delete:not(body):focus{background-color:#e8e8e8}.tag.is-delete:not(body):active,.content kbd.is-delete:not(body):active,.docstring>section>a.docs-sourcelink.is-delete:not(body):active{background-color:#dbdbdb}.tag.is-rounded:not(body),#documenter .docs-sidebar form.docs-search>input:not(body),.content kbd.is-rounded:not(body),#documenter .docs-sidebar .content form.docs-search>input:not(body),.docstring>section>a.docs-sourcelink.is-rounded:not(body){border-radius:290486px}a.tag:hover,.docstring>section>a.docs-sourcelink:hover{text-decoration:underline}.title,.subtitle{word-break:break-word}.title em,.title span,.subtitle em,.subtitle span{font-weight:inherit}.title sub,.subtitle sub{font-size:.75em}.title sup,.subtitle sup{font-size:.75em}.title .tag,.title .content kbd,.content .title kbd,.title .docstring>section>a.docs-sourcelink,.subtitle .tag,.subtitle .content kbd,.content .subtitle kbd,.subtitle .docstring>section>a.docs-sourcelink{vertical-align:middle}.title{color:#363636;font-size:2rem;font-weight:600;line-height:1.125}.title strong{color:inherit;font-weight:inherit}.title+.highlight{margin-top:-0.75rem}.title:not(.is-spaced)+.subtitle{margin-top:-1.25rem}.title.is-1{font-size:3rem}.title.is-2{font-size:2.5rem}.title.is-3{font-size:2rem}.title.is-4{font-size:1.5rem}.title.is-5{font-size:1.25rem}.title.is-6{font-size:1rem}.title.is-7{font-size:.75rem}.subtitle{color:#4a4a4a;font-size:1.25rem;font-weight:400;line-height:1.25}.subtitle strong{color:#363636;font-weight:600}.subtitle:not(.is-spaced)+.title{margin-top:-1.25rem}.subtitle.is-1{font-size:3rem}.subtitle.is-2{font-size:2.5rem}.subtitle.is-3{font-size:2rem}.subtitle.is-4{font-size:1.5rem}.subtitle.is-5{font-size:1.25rem}.subtitle.is-6{font-size:1rem}.subtitle.is-7{font-size:.75rem}.heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}.highlight{font-weight:400;max-width:100%;overflow:hidden;padding:0}.highlight pre{overflow:auto;max-width:100%}.number{align-items:center;background-color:#f5f5f5;border-radius:290486px;display:inline-flex;font-size:1.25rem;height:2em;justify-content:center;margin-right:1.5rem;min-width:2.5em;padding:0.25rem 0.5rem;text-align:center;vertical-align:top}.select select,.textarea,.input,#documenter .docs-sidebar form.docs-search>input{background-color:#fff;border-color:#dbdbdb;border-radius:4px;color:#363636}.select select::-moz-placeholder,.textarea::-moz-placeholder,.input::-moz-placeholder,#documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:rgba(54,54,54,0.3)}.select select::-webkit-input-placeholder,.textarea::-webkit-input-placeholder,.input::-webkit-input-placeholder,#documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:rgba(54,54,54,0.3)}.select select:-moz-placeholder,.textarea:-moz-placeholder,.input:-moz-placeholder,#documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:rgba(54,54,54,0.3)}.select select:-ms-input-placeholder,.textarea:-ms-input-placeholder,.input:-ms-input-placeholder,#documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:rgba(54,54,54,0.3)}.select select:hover,.textarea:hover,.input:hover,#documenter .docs-sidebar form.docs-search>input:hover,.select select.is-hovered,.is-hovered.textarea,.is-hovered.input,#documenter .docs-sidebar form.docs-search>input.is-hovered{border-color:#b5b5b5}.select select:focus,.textarea:focus,.input:focus,#documenter .docs-sidebar form.docs-search>input:focus,.select select.is-focused,.is-focused.textarea,.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.select select:active,.textarea:active,.input:active,#documenter .docs-sidebar form.docs-search>input:active,.select select.is-active,.is-active.textarea,.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{border-color:#2e63b8;box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.select select[disabled],.textarea[disabled],.input[disabled],#documenter .docs-sidebar form.docs-search>input[disabled],fieldset[disabled] .select select,.select fieldset[disabled] select,fieldset[disabled] .textarea,fieldset[disabled] .input,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none;color:#6b6b6b}.select select[disabled]::-moz-placeholder,.textarea[disabled]::-moz-placeholder,.input[disabled]::-moz-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]::-moz-placeholder,fieldset[disabled] .select select::-moz-placeholder,.select fieldset[disabled] select::-moz-placeholder,fieldset[disabled] .textarea::-moz-placeholder,fieldset[disabled] .input::-moz-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input::-moz-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input::-moz-placeholder{color:rgba(107,107,107,0.3)}.select select[disabled]::-webkit-input-placeholder,.textarea[disabled]::-webkit-input-placeholder,.input[disabled]::-webkit-input-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]::-webkit-input-placeholder,fieldset[disabled] .select select::-webkit-input-placeholder,.select fieldset[disabled] select::-webkit-input-placeholder,fieldset[disabled] .textarea::-webkit-input-placeholder,fieldset[disabled] .input::-webkit-input-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input::-webkit-input-placeholder{color:rgba(107,107,107,0.3)}.select select[disabled]:-moz-placeholder,.textarea[disabled]:-moz-placeholder,.input[disabled]:-moz-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]:-moz-placeholder,fieldset[disabled] .select select:-moz-placeholder,.select fieldset[disabled] select:-moz-placeholder,fieldset[disabled] .textarea:-moz-placeholder,fieldset[disabled] .input:-moz-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input:-moz-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input:-moz-placeholder{color:rgba(107,107,107,0.3)}.select select[disabled]:-ms-input-placeholder,.textarea[disabled]:-ms-input-placeholder,.input[disabled]:-ms-input-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]:-ms-input-placeholder,fieldset[disabled] .select select:-ms-input-placeholder,.select fieldset[disabled] select:-ms-input-placeholder,fieldset[disabled] .textarea:-ms-input-placeholder,fieldset[disabled] .input:-ms-input-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input:-ms-input-placeholder{color:rgba(107,107,107,0.3)}.textarea,.input,#documenter .docs-sidebar form.docs-search>input{box-shadow:inset 0 1px 2px rgba(10,10,10,0.1);max-width:100%;width:100%}.textarea[readonly],.input[readonly],#documenter .docs-sidebar form.docs-search>input[readonly]{box-shadow:none}.is-white.textarea,.is-white.input,#documenter .docs-sidebar form.docs-search>input.is-white{border-color:#fff}.is-white.textarea:focus,.is-white.input:focus,#documenter .docs-sidebar form.docs-search>input.is-white:focus,.is-white.is-focused.textarea,.is-white.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-white.textarea:active,.is-white.input:active,#documenter .docs-sidebar form.docs-search>input.is-white:active,.is-white.is-active.textarea,.is-white.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}.is-black.textarea,.is-black.input,#documenter .docs-sidebar form.docs-search>input.is-black{border-color:#0a0a0a}.is-black.textarea:focus,.is-black.input:focus,#documenter .docs-sidebar form.docs-search>input.is-black:focus,.is-black.is-focused.textarea,.is-black.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-black.textarea:active,.is-black.input:active,#documenter .docs-sidebar form.docs-search>input.is-black:active,.is-black.is-active.textarea,.is-black.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}.is-light.textarea,.is-light.input,#documenter .docs-sidebar form.docs-search>input.is-light{border-color:#f5f5f5}.is-light.textarea:focus,.is-light.input:focus,#documenter .docs-sidebar form.docs-search>input.is-light:focus,.is-light.is-focused.textarea,.is-light.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-light.textarea:active,.is-light.input:active,#documenter .docs-sidebar form.docs-search>input.is-light:active,.is-light.is-active.textarea,.is-light.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}.is-dark.textarea,.content kbd.textarea,.is-dark.input,#documenter .docs-sidebar form.docs-search>input.is-dark,.content kbd.input{border-color:#363636}.is-dark.textarea:focus,.content kbd.textarea:focus,.is-dark.input:focus,#documenter .docs-sidebar form.docs-search>input.is-dark:focus,.content kbd.input:focus,.is-dark.is-focused.textarea,.content kbd.is-focused.textarea,.is-dark.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.content kbd.is-focused.input,#documenter .docs-sidebar .content form.docs-search>input.is-focused,.is-dark.textarea:active,.content kbd.textarea:active,.is-dark.input:active,#documenter .docs-sidebar form.docs-search>input.is-dark:active,.content kbd.input:active,.is-dark.is-active.textarea,.content kbd.is-active.textarea,.is-dark.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active,.content kbd.is-active.input,#documenter .docs-sidebar .content form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(54,54,54,0.25)}.is-primary.textarea,.docstring>section>a.textarea.docs-sourcelink,.is-primary.input,#documenter .docs-sidebar form.docs-search>input.is-primary,.docstring>section>a.input.docs-sourcelink{border-color:#4eb5de}.is-primary.textarea:focus,.docstring>section>a.textarea.docs-sourcelink:focus,.is-primary.input:focus,#documenter .docs-sidebar form.docs-search>input.is-primary:focus,.docstring>section>a.input.docs-sourcelink:focus,.is-primary.is-focused.textarea,.docstring>section>a.is-focused.textarea.docs-sourcelink,.is-primary.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.docstring>section>a.is-focused.input.docs-sourcelink,.is-primary.textarea:active,.docstring>section>a.textarea.docs-sourcelink:active,.is-primary.input:active,#documenter .docs-sidebar form.docs-search>input.is-primary:active,.docstring>section>a.input.docs-sourcelink:active,.is-primary.is-active.textarea,.docstring>section>a.is-active.textarea.docs-sourcelink,.is-primary.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active,.docstring>section>a.is-active.input.docs-sourcelink{box-shadow:0 0 0 0.125em rgba(78,181,222,0.25)}.is-link.textarea,.is-link.input,#documenter .docs-sidebar form.docs-search>input.is-link{border-color:#2e63b8}.is-link.textarea:focus,.is-link.input:focus,#documenter .docs-sidebar form.docs-search>input.is-link:focus,.is-link.is-focused.textarea,.is-link.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-link.textarea:active,.is-link.input:active,#documenter .docs-sidebar form.docs-search>input.is-link:active,.is-link.is-active.textarea,.is-link.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.is-info.textarea,.is-info.input,#documenter .docs-sidebar form.docs-search>input.is-info{border-color:#209cee}.is-info.textarea:focus,.is-info.input:focus,#documenter .docs-sidebar form.docs-search>input.is-info:focus,.is-info.is-focused.textarea,.is-info.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-info.textarea:active,.is-info.input:active,#documenter .docs-sidebar form.docs-search>input.is-info:active,.is-info.is-active.textarea,.is-info.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(32,156,238,0.25)}.is-success.textarea,.is-success.input,#documenter .docs-sidebar form.docs-search>input.is-success{border-color:#22c35b}.is-success.textarea:focus,.is-success.input:focus,#documenter .docs-sidebar form.docs-search>input.is-success:focus,.is-success.is-focused.textarea,.is-success.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-success.textarea:active,.is-success.input:active,#documenter .docs-sidebar form.docs-search>input.is-success:active,.is-success.is-active.textarea,.is-success.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(34,195,91,0.25)}.is-warning.textarea,.is-warning.input,#documenter .docs-sidebar form.docs-search>input.is-warning{border-color:#ffdd57}.is-warning.textarea:focus,.is-warning.input:focus,#documenter .docs-sidebar form.docs-search>input.is-warning:focus,.is-warning.is-focused.textarea,.is-warning.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-warning.textarea:active,.is-warning.input:active,#documenter .docs-sidebar form.docs-search>input.is-warning:active,.is-warning.is-active.textarea,.is-warning.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,221,87,0.25)}.is-danger.textarea,.is-danger.input,#documenter .docs-sidebar form.docs-search>input.is-danger{border-color:#da0b00}.is-danger.textarea:focus,.is-danger.input:focus,#documenter .docs-sidebar form.docs-search>input.is-danger:focus,.is-danger.is-focused.textarea,.is-danger.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-danger.textarea:active,.is-danger.input:active,#documenter .docs-sidebar form.docs-search>input.is-danger:active,.is-danger.is-active.textarea,.is-danger.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(218,11,0,0.25)}.is-small.textarea,.is-small.input,#documenter .docs-sidebar form.docs-search>input{border-radius:2px;font-size:.75rem}.is-medium.textarea,.is-medium.input,#documenter .docs-sidebar form.docs-search>input.is-medium{font-size:1.25rem}.is-large.textarea,.is-large.input,#documenter .docs-sidebar form.docs-search>input.is-large{font-size:1.5rem}.is-fullwidth.textarea,.is-fullwidth.input,#documenter .docs-sidebar form.docs-search>input.is-fullwidth{display:block;width:100%}.is-inline.textarea,.is-inline.input,#documenter .docs-sidebar form.docs-search>input.is-inline{display:inline;width:auto}.input.is-rounded,#documenter .docs-sidebar form.docs-search>input{border-radius:290486px;padding-left:1em;padding-right:1em}.input.is-static,#documenter .docs-sidebar form.docs-search>input.is-static{background-color:transparent;border-color:transparent;box-shadow:none;padding-left:0;padding-right:0}.textarea{display:block;max-width:100%;min-width:100%;padding:0.625em;resize:vertical}.textarea:not([rows]){max-height:600px;min-height:120px}.textarea[rows]{height:initial}.textarea.has-fixed-size{resize:none}.radio,.checkbox{cursor:pointer;display:inline-block;line-height:1.25;position:relative}.radio input,.checkbox input{cursor:pointer}.radio:hover,.checkbox:hover{color:#363636}.radio[disabled],.checkbox[disabled],fieldset[disabled] .radio,fieldset[disabled] .checkbox{color:#6b6b6b;cursor:not-allowed}.radio+.radio{margin-left:0.5em}.select{display:inline-block;max-width:100%;position:relative;vertical-align:top}.select:not(.is-multiple){height:2.25em}.select:not(.is-multiple):not(.is-loading)::after{border-color:#2e63b8;right:1.125em;z-index:4}.select.is-rounded select,#documenter .docs-sidebar form.docs-search>input.select select{border-radius:290486px;padding-left:1em}.select select{cursor:pointer;display:block;font-size:1em;max-width:100%;outline:none}.select select::-ms-expand{display:none}.select select[disabled]:hover,fieldset[disabled] .select select:hover{border-color:#f5f5f5}.select select:not([multiple]){padding-right:2.5em}.select select[multiple]{height:auto;padding:0}.select select[multiple] option{padding:0.5em 1em}.select:not(.is-multiple):not(.is-loading):hover::after{border-color:#363636}.select.is-white:not(:hover)::after{border-color:#fff}.select.is-white select{border-color:#fff}.select.is-white select:hover,.select.is-white select.is-hovered{border-color:#f2f2f2}.select.is-white select:focus,.select.is-white select.is-focused,.select.is-white select:active,.select.is-white select.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}.select.is-black:not(:hover)::after{border-color:#0a0a0a}.select.is-black select{border-color:#0a0a0a}.select.is-black select:hover,.select.is-black select.is-hovered{border-color:#000}.select.is-black select:focus,.select.is-black select.is-focused,.select.is-black select:active,.select.is-black select.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}.select.is-light:not(:hover)::after{border-color:#f5f5f5}.select.is-light select{border-color:#f5f5f5}.select.is-light select:hover,.select.is-light select.is-hovered{border-color:#e8e8e8}.select.is-light select:focus,.select.is-light select.is-focused,.select.is-light select:active,.select.is-light select.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}.select.is-dark:not(:hover)::after,.content kbd.select:not(:hover)::after{border-color:#363636}.select.is-dark select,.content kbd.select select{border-color:#363636}.select.is-dark select:hover,.content kbd.select select:hover,.select.is-dark select.is-hovered,.content kbd.select select.is-hovered{border-color:#292929}.select.is-dark select:focus,.content kbd.select select:focus,.select.is-dark select.is-focused,.content kbd.select select.is-focused,.select.is-dark select:active,.content kbd.select select:active,.select.is-dark select.is-active,.content kbd.select select.is-active{box-shadow:0 0 0 0.125em rgba(54,54,54,0.25)}.select.is-primary:not(:hover)::after,.docstring>section>a.select.docs-sourcelink:not(:hover)::after{border-color:#4eb5de}.select.is-primary select,.docstring>section>a.select.docs-sourcelink select{border-color:#4eb5de}.select.is-primary select:hover,.docstring>section>a.select.docs-sourcelink select:hover,.select.is-primary select.is-hovered,.docstring>section>a.select.docs-sourcelink select.is-hovered{border-color:#39acda}.select.is-primary select:focus,.docstring>section>a.select.docs-sourcelink select:focus,.select.is-primary select.is-focused,.docstring>section>a.select.docs-sourcelink select.is-focused,.select.is-primary select:active,.docstring>section>a.select.docs-sourcelink select:active,.select.is-primary select.is-active,.docstring>section>a.select.docs-sourcelink select.is-active{box-shadow:0 0 0 0.125em rgba(78,181,222,0.25)}.select.is-link:not(:hover)::after{border-color:#2e63b8}.select.is-link select{border-color:#2e63b8}.select.is-link select:hover,.select.is-link select.is-hovered{border-color:#2958a4}.select.is-link select:focus,.select.is-link select.is-focused,.select.is-link select:active,.select.is-link select.is-active{box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.select.is-info:not(:hover)::after{border-color:#209cee}.select.is-info select{border-color:#209cee}.select.is-info select:hover,.select.is-info select.is-hovered{border-color:#1190e3}.select.is-info select:focus,.select.is-info select.is-focused,.select.is-info select:active,.select.is-info select.is-active{box-shadow:0 0 0 0.125em rgba(32,156,238,0.25)}.select.is-success:not(:hover)::after{border-color:#22c35b}.select.is-success select{border-color:#22c35b}.select.is-success select:hover,.select.is-success select.is-hovered{border-color:#1ead51}.select.is-success select:focus,.select.is-success select.is-focused,.select.is-success select:active,.select.is-success select.is-active{box-shadow:0 0 0 0.125em rgba(34,195,91,0.25)}.select.is-warning:not(:hover)::after{border-color:#ffdd57}.select.is-warning select{border-color:#ffdd57}.select.is-warning select:hover,.select.is-warning select.is-hovered{border-color:#ffd83e}.select.is-warning select:focus,.select.is-warning select.is-focused,.select.is-warning select:active,.select.is-warning select.is-active{box-shadow:0 0 0 0.125em rgba(255,221,87,0.25)}.select.is-danger:not(:hover)::after{border-color:#da0b00}.select.is-danger select{border-color:#da0b00}.select.is-danger select:hover,.select.is-danger select.is-hovered{border-color:#c10a00}.select.is-danger select:focus,.select.is-danger select.is-focused,.select.is-danger select:active,.select.is-danger select.is-active{box-shadow:0 0 0 0.125em rgba(218,11,0,0.25)}.select.is-small,#documenter .docs-sidebar form.docs-search>input.select{border-radius:2px;font-size:.75rem}.select.is-medium{font-size:1.25rem}.select.is-large{font-size:1.5rem}.select.is-disabled::after{border-color:#6b6b6b}.select.is-fullwidth{width:100%}.select.is-fullwidth select{width:100%}.select.is-loading::after{margin-top:0;position:absolute;right:0.625em;top:0.625em;transform:none}.select.is-loading.is-small:after,#documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}.select.is-loading.is-medium:after{font-size:1.25rem}.select.is-loading.is-large:after{font-size:1.5rem}.file{align-items:stretch;display:flex;justify-content:flex-start;position:relative}.file.is-white .file-cta{background-color:#fff;border-color:transparent;color:#0a0a0a}.file.is-white:hover .file-cta,.file.is-white.is-hovered .file-cta{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}.file.is-white:focus .file-cta,.file.is-white.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,255,255,0.25);color:#0a0a0a}.file.is-white:active .file-cta,.file.is-white.is-active .file-cta{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}.file.is-black .file-cta{background-color:#0a0a0a;border-color:transparent;color:#fff}.file.is-black:hover .file-cta,.file.is-black.is-hovered .file-cta{background-color:#040404;border-color:transparent;color:#fff}.file.is-black:focus .file-cta,.file.is-black.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(10,10,10,0.25);color:#fff}.file.is-black:active .file-cta,.file.is-black.is-active .file-cta{background-color:#000;border-color:transparent;color:#fff}.file.is-light .file-cta{background-color:#f5f5f5;border-color:transparent;color:#363636}.file.is-light:hover .file-cta,.file.is-light.is-hovered .file-cta{background-color:#eee;border-color:transparent;color:#363636}.file.is-light:focus .file-cta,.file.is-light.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(245,245,245,0.25);color:#363636}.file.is-light:active .file-cta,.file.is-light.is-active .file-cta{background-color:#e8e8e8;border-color:transparent;color:#363636}.file.is-dark .file-cta,.content kbd.file .file-cta{background-color:#363636;border-color:transparent;color:#f5f5f5}.file.is-dark:hover .file-cta,.content kbd.file:hover .file-cta,.file.is-dark.is-hovered .file-cta,.content kbd.file.is-hovered .file-cta{background-color:#2f2f2f;border-color:transparent;color:#f5f5f5}.file.is-dark:focus .file-cta,.content kbd.file:focus .file-cta,.file.is-dark.is-focused .file-cta,.content kbd.file.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(54,54,54,0.25);color:#f5f5f5}.file.is-dark:active .file-cta,.content kbd.file:active .file-cta,.file.is-dark.is-active .file-cta,.content kbd.file.is-active .file-cta{background-color:#292929;border-color:transparent;color:#f5f5f5}.file.is-primary .file-cta,.docstring>section>a.file.docs-sourcelink .file-cta{background-color:#4eb5de;border-color:transparent;color:#fff}.file.is-primary:hover .file-cta,.docstring>section>a.file.docs-sourcelink:hover .file-cta,.file.is-primary.is-hovered .file-cta,.docstring>section>a.file.is-hovered.docs-sourcelink .file-cta{background-color:#43b1dc;border-color:transparent;color:#fff}.file.is-primary:focus .file-cta,.docstring>section>a.file.docs-sourcelink:focus .file-cta,.file.is-primary.is-focused .file-cta,.docstring>section>a.file.is-focused.docs-sourcelink .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(78,181,222,0.25);color:#fff}.file.is-primary:active .file-cta,.docstring>section>a.file.docs-sourcelink:active .file-cta,.file.is-primary.is-active .file-cta,.docstring>section>a.file.is-active.docs-sourcelink .file-cta{background-color:#39acda;border-color:transparent;color:#fff}.file.is-link .file-cta{background-color:#2e63b8;border-color:transparent;color:#fff}.file.is-link:hover .file-cta,.file.is-link.is-hovered .file-cta{background-color:#2b5eae;border-color:transparent;color:#fff}.file.is-link:focus .file-cta,.file.is-link.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(46,99,184,0.25);color:#fff}.file.is-link:active .file-cta,.file.is-link.is-active .file-cta{background-color:#2958a4;border-color:transparent;color:#fff}.file.is-info .file-cta{background-color:#209cee;border-color:transparent;color:#fff}.file.is-info:hover .file-cta,.file.is-info.is-hovered .file-cta{background-color:#1497ed;border-color:transparent;color:#fff}.file.is-info:focus .file-cta,.file.is-info.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(32,156,238,0.25);color:#fff}.file.is-info:active .file-cta,.file.is-info.is-active .file-cta{background-color:#1190e3;border-color:transparent;color:#fff}.file.is-success .file-cta{background-color:#22c35b;border-color:transparent;color:#fff}.file.is-success:hover .file-cta,.file.is-success.is-hovered .file-cta{background-color:#20b856;border-color:transparent;color:#fff}.file.is-success:focus .file-cta,.file.is-success.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(34,195,91,0.25);color:#fff}.file.is-success:active .file-cta,.file.is-success.is-active .file-cta{background-color:#1ead51;border-color:transparent;color:#fff}.file.is-warning .file-cta{background-color:#ffdd57;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-warning:hover .file-cta,.file.is-warning.is-hovered .file-cta{background-color:#ffda4a;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-warning:focus .file-cta,.file.is-warning.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,221,87,0.25);color:rgba(0,0,0,0.7)}.file.is-warning:active .file-cta,.file.is-warning.is-active .file-cta{background-color:#ffd83e;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-danger .file-cta{background-color:#da0b00;border-color:transparent;color:#fff}.file.is-danger:hover .file-cta,.file.is-danger.is-hovered .file-cta{background-color:#cd0a00;border-color:transparent;color:#fff}.file.is-danger:focus .file-cta,.file.is-danger.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(218,11,0,0.25);color:#fff}.file.is-danger:active .file-cta,.file.is-danger.is-active .file-cta{background-color:#c10a00;border-color:transparent;color:#fff}.file.is-small,#documenter .docs-sidebar form.docs-search>input.file{font-size:.75rem}.file.is-medium{font-size:1.25rem}.file.is-medium .file-icon .fa{font-size:21px}.file.is-large{font-size:1.5rem}.file.is-large .file-icon .fa{font-size:28px}.file.has-name .file-cta{border-bottom-right-radius:0;border-top-right-radius:0}.file.has-name .file-name{border-bottom-left-radius:0;border-top-left-radius:0}.file.has-name.is-empty .file-cta{border-radius:4px}.file.has-name.is-empty .file-name{display:none}.file.is-boxed .file-label{flex-direction:column}.file.is-boxed .file-cta{flex-direction:column;height:auto;padding:1em 3em}.file.is-boxed .file-name{border-width:0 1px 1px}.file.is-boxed .file-icon{height:1.5em;width:1.5em}.file.is-boxed .file-icon .fa{font-size:21px}.file.is-boxed.is-small .file-icon .fa,#documenter .docs-sidebar form.docs-search>input.is-boxed .file-icon .fa{font-size:14px}.file.is-boxed.is-medium .file-icon .fa{font-size:28px}.file.is-boxed.is-large .file-icon .fa{font-size:35px}.file.is-boxed.has-name .file-cta{border-radius:4px 4px 0 0}.file.is-boxed.has-name .file-name{border-radius:0 0 4px 4px;border-width:0 1px 1px}.file.is-centered{justify-content:center}.file.is-fullwidth .file-label{width:100%}.file.is-fullwidth .file-name{flex-grow:1;max-width:none}.file.is-right{justify-content:flex-end}.file.is-right .file-cta{border-radius:0 4px 4px 0}.file.is-right .file-name{border-radius:4px 0 0 4px;border-width:1px 0 1px 1px;order:-1}.file-label{align-items:stretch;display:flex;cursor:pointer;justify-content:flex-start;overflow:hidden;position:relative}.file-label:hover .file-cta{background-color:#eee;color:#363636}.file-label:hover .file-name{border-color:#d5d5d5}.file-label:active .file-cta{background-color:#e8e8e8;color:#363636}.file-label:active .file-name{border-color:#cfcfcf}.file-input{height:100%;left:0;opacity:0;outline:none;position:absolute;top:0;width:100%}.file-cta,.file-name{border-color:#dbdbdb;border-radius:4px;font-size:1em;padding-left:1em;padding-right:1em;white-space:nowrap}.file-cta{background-color:#f5f5f5;color:#4a4a4a}.file-name{border-color:#dbdbdb;border-style:solid;border-width:1px 1px 1px 0;display:block;max-width:16em;overflow:hidden;text-align:left;text-overflow:ellipsis}.file-icon{align-items:center;display:flex;height:1em;justify-content:center;margin-right:0.5em;width:1em}.file-icon .fa{font-size:14px}.label{color:#363636;display:block;font-size:1rem;font-weight:700}.label:not(:last-child){margin-bottom:0.5em}.label.is-small,#documenter .docs-sidebar form.docs-search>input.label{font-size:.75rem}.label.is-medium{font-size:1.25rem}.label.is-large{font-size:1.5rem}.help{display:block;font-size:.75rem;margin-top:0.25rem}.help.is-white{color:#fff}.help.is-black{color:#0a0a0a}.help.is-light{color:#f5f5f5}.help.is-dark,.content kbd.help{color:#363636}.help.is-primary,.docstring>section>a.help.docs-sourcelink{color:#4eb5de}.help.is-link{color:#2e63b8}.help.is-info{color:#209cee}.help.is-success{color:#22c35b}.help.is-warning{color:#ffdd57}.help.is-danger{color:#da0b00}.field:not(:last-child){margin-bottom:0.75rem}.field.has-addons{display:flex;justify-content:flex-start}.field.has-addons .control:not(:last-child){margin-right:-1px}.field.has-addons .control:not(:first-child):not(:last-child) .button,.field.has-addons .control:not(:first-child):not(:last-child) .input,.field.has-addons .control:not(:first-child):not(:last-child) #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .field.has-addons .control:not(:first-child):not(:last-child) form.docs-search>input,.field.has-addons .control:not(:first-child):not(:last-child) .select select{border-radius:0}.field.has-addons .control:first-child:not(:only-child) .button,.field.has-addons .control:first-child:not(:only-child) .input,.field.has-addons .control:first-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .field.has-addons .control:first-child:not(:only-child) form.docs-search>input,.field.has-addons .control:first-child:not(:only-child) .select select{border-bottom-right-radius:0;border-top-right-radius:0}.field.has-addons .control:last-child:not(:only-child) .button,.field.has-addons .control:last-child:not(:only-child) .input,.field.has-addons .control:last-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .field.has-addons .control:last-child:not(:only-child) form.docs-search>input,.field.has-addons .control:last-child:not(:only-child) .select select{border-bottom-left-radius:0;border-top-left-radius:0}.field.has-addons .control .button:not([disabled]):hover,.field.has-addons .control .button.is-hovered:not([disabled]),.field.has-addons .control .input:not([disabled]):hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):hover,.field.has-addons .control .input.is-hovered:not([disabled]),.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-hovered:not([disabled]),#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-hovered:not([disabled]),.field.has-addons .control .select select:not([disabled]):hover,.field.has-addons .control .select select.is-hovered:not([disabled]){z-index:2}.field.has-addons .control .button:not([disabled]):focus,.field.has-addons .control .button.is-focused:not([disabled]),.field.has-addons .control .button:not([disabled]):active,.field.has-addons .control .button.is-active:not([disabled]),.field.has-addons .control .input:not([disabled]):focus,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus,.field.has-addons .control .input.is-focused:not([disabled]),.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]),#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]),.field.has-addons .control .input:not([disabled]):active,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active,.field.has-addons .control .input.is-active:not([disabled]),.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]),#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]),.field.has-addons .control .select select:not([disabled]):focus,.field.has-addons .control .select select.is-focused:not([disabled]),.field.has-addons .control .select select:not([disabled]):active,.field.has-addons .control .select select.is-active:not([disabled]){z-index:3}.field.has-addons .control .button:not([disabled]):focus:hover,.field.has-addons .control .button.is-focused:not([disabled]):hover,.field.has-addons .control .button:not([disabled]):active:hover,.field.has-addons .control .button.is-active:not([disabled]):hover,.field.has-addons .control .input:not([disabled]):focus:hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus:hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus:hover,.field.has-addons .control .input.is-focused:not([disabled]):hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]):hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]):hover,.field.has-addons .control .input:not([disabled]):active:hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active:hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active:hover,.field.has-addons .control .input.is-active:not([disabled]):hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]):hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]):hover,.field.has-addons .control .select select:not([disabled]):focus:hover,.field.has-addons .control .select select.is-focused:not([disabled]):hover,.field.has-addons .control .select select:not([disabled]):active:hover,.field.has-addons .control .select select.is-active:not([disabled]):hover{z-index:4}.field.has-addons .control.is-expanded{flex-grow:1;flex-shrink:1}.field.has-addons.has-addons-centered{justify-content:center}.field.has-addons.has-addons-right{justify-content:flex-end}.field.has-addons.has-addons-fullwidth .control{flex-grow:1;flex-shrink:0}.field.is-grouped{display:flex;justify-content:flex-start}.field.is-grouped>.control{flex-shrink:0}.field.is-grouped>.control:not(:last-child){margin-bottom:0;margin-right:0.75rem}.field.is-grouped>.control.is-expanded{flex-grow:1;flex-shrink:1}.field.is-grouped.is-grouped-centered{justify-content:center}.field.is-grouped.is-grouped-right{justify-content:flex-end}.field.is-grouped.is-grouped-multiline{flex-wrap:wrap}.field.is-grouped.is-grouped-multiline>.control:last-child,.field.is-grouped.is-grouped-multiline>.control:not(:last-child){margin-bottom:0.75rem}.field.is-grouped.is-grouped-multiline:last-child{margin-bottom:-0.75rem}.field.is-grouped.is-grouped-multiline:not(:last-child){margin-bottom:0}@media screen and (min-width: 769px),print{.field.is-horizontal{display:flex}}.field-label .label{font-size:inherit}@media screen and (max-width: 768px){.field-label{margin-bottom:0.5rem}}@media screen and (min-width: 769px),print{.field-label{flex-basis:0;flex-grow:1;flex-shrink:0;margin-right:1.5rem;text-align:right}.field-label.is-small,#documenter .docs-sidebar form.docs-search>input.field-label{font-size:.75rem;padding-top:0.375em}.field-label.is-normal{padding-top:0.375em}.field-label.is-medium{font-size:1.25rem;padding-top:0.375em}.field-label.is-large{font-size:1.5rem;padding-top:0.375em}}.field-body .field .field{margin-bottom:0}@media screen and (min-width: 769px),print{.field-body{display:flex;flex-basis:0;flex-grow:5;flex-shrink:1}.field-body .field{margin-bottom:0}.field-body>.field{flex-shrink:1}.field-body>.field:not(.is-narrow){flex-grow:1}.field-body>.field:not(:last-child){margin-right:0.75rem}}.control{box-sizing:border-box;clear:both;font-size:1rem;position:relative;text-align:left}.control.has-icons-left .input:focus~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input:focus~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input:focus~.icon,.control.has-icons-left .select:focus~.icon,.control.has-icons-right .input:focus~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input:focus~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input:focus~.icon,.control.has-icons-right .select:focus~.icon{color:#6b6b6b}.control.has-icons-left .input.is-small~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input~.icon,.control.has-icons-left .select.is-small~.icon,.control.has-icons-right .input.is-small~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input~.icon,.control.has-icons-right .select.is-small~.icon{font-size:.75rem}.control.has-icons-left .input.is-medium~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-medium~.icon,.control.has-icons-left .select.is-medium~.icon,.control.has-icons-right .input.is-medium~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-medium~.icon,.control.has-icons-right .select.is-medium~.icon{font-size:1.25rem}.control.has-icons-left .input.is-large~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-large~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-large~.icon,.control.has-icons-left .select.is-large~.icon,.control.has-icons-right .input.is-large~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-large~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-large~.icon,.control.has-icons-right .select.is-large~.icon{font-size:1.5rem}.control.has-icons-left .icon,.control.has-icons-right .icon{color:#dbdbdb;height:2.25em;pointer-events:none;position:absolute;top:0;width:2.25em;z-index:4}.control.has-icons-left .input,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input,.control.has-icons-left .select select{padding-left:2.25em}.control.has-icons-left .icon.is-left{left:0}.control.has-icons-right .input,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input,.control.has-icons-right .select select{padding-right:2.25em}.control.has-icons-right .icon.is-right{right:0}.control.is-loading::after{position:absolute !important;right:0.625em;top:0.625em;z-index:4}.control.is-loading.is-small:after,#documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}.control.is-loading.is-medium:after{font-size:1.25rem}.control.is-loading.is-large:after{font-size:1.5rem}.breadcrumb{font-size:1rem;white-space:nowrap}.breadcrumb a{align-items:center;color:#2e63b8;display:flex;justify-content:center;padding:0 .75em}.breadcrumb a:hover{color:#363636}.breadcrumb li{align-items:center;display:flex}.breadcrumb li:first-child a{padding-left:0}.breadcrumb li.is-active a{color:#222;cursor:default;pointer-events:none}.breadcrumb li+li::before{color:#b5b5b5;content:"\0002f"}.breadcrumb ul,.breadcrumb ol{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:flex-start}.breadcrumb .icon:first-child{margin-right:0.5em}.breadcrumb .icon:last-child{margin-left:0.5em}.breadcrumb.is-centered ol,.breadcrumb.is-centered ul{justify-content:center}.breadcrumb.is-right ol,.breadcrumb.is-right ul{justify-content:flex-end}.breadcrumb.is-small,#documenter .docs-sidebar form.docs-search>input.breadcrumb{font-size:.75rem}.breadcrumb.is-medium{font-size:1.25rem}.breadcrumb.is-large{font-size:1.5rem}.breadcrumb.has-arrow-separator li+li::before{content:"\02192"}.breadcrumb.has-bullet-separator li+li::before{content:"\02022"}.breadcrumb.has-dot-separator li+li::before{content:"\000b7"}.breadcrumb.has-succeeds-separator li+li::before{content:"\0227B"}.card{background-color:#fff;box-shadow:0 2px 3px rgba(10,10,10,0.1),0 0 0 1px rgba(10,10,10,0.1);color:#222;max-width:100%;position:relative}.card-header{background-color:rgba(0,0,0,0);align-items:stretch;box-shadow:0 1px 2px rgba(10,10,10,0.1);display:flex}.card-header-title{align-items:center;color:#222;display:flex;flex-grow:1;font-weight:700;padding:.75rem}.card-header-title.is-centered{justify-content:center}.card-header-icon{align-items:center;cursor:pointer;display:flex;justify-content:center;padding:.75rem}.card-image{display:block;position:relative}.card-content{background-color:rgba(0,0,0,0);padding:1.5rem}.card-footer{background-color:rgba(0,0,0,0);border-top:1px solid #dbdbdb;align-items:stretch;display:flex}.card-footer-item{align-items:center;display:flex;flex-basis:0;flex-grow:1;flex-shrink:0;justify-content:center;padding:.75rem}.card-footer-item:not(:last-child){border-right:1px solid #dbdbdb}.card .media:not(:last-child){margin-bottom:1.5rem}.dropdown{display:inline-flex;position:relative;vertical-align:top}.dropdown.is-active .dropdown-menu,.dropdown.is-hoverable:hover .dropdown-menu{display:block}.dropdown.is-right .dropdown-menu{left:auto;right:0}.dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:initial;top:auto}.dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:20}.dropdown-content{background-color:#fff;border-radius:4px;box-shadow:0 2px 3px rgba(10,10,10,0.1),0 0 0 1px rgba(10,10,10,0.1);padding-bottom:.5rem;padding-top:.5rem}.dropdown-item{color:#4a4a4a;display:block;font-size:0.875rem;line-height:1.5;padding:0.375rem 1rem;position:relative}a.dropdown-item,button.dropdown-item{padding-right:3rem;text-align:left;white-space:nowrap;width:100%}a.dropdown-item:hover,button.dropdown-item:hover{background-color:#f5f5f5;color:#0a0a0a}a.dropdown-item.is-active,button.dropdown-item.is-active{background-color:#2e63b8;color:#fff}.dropdown-divider{background-color:#dbdbdb;border:none;display:block;height:1px;margin:0.5rem 0}.level{align-items:center;justify-content:space-between}.level code{border-radius:4px}.level img{display:inline-block;vertical-align:top}.level.is-mobile{display:flex}.level.is-mobile .level-left,.level.is-mobile .level-right{display:flex}.level.is-mobile .level-left+.level-right{margin-top:0}.level.is-mobile .level-item:not(:last-child){margin-bottom:0;margin-right:.75rem}.level.is-mobile .level-item:not(.is-narrow){flex-grow:1}@media screen and (min-width: 769px),print{.level{display:flex}.level>.level-item:not(.is-narrow){flex-grow:1}}.level-item{align-items:center;display:flex;flex-basis:auto;flex-grow:0;flex-shrink:0;justify-content:center}.level-item .title,.level-item .subtitle{margin-bottom:0}@media screen and (max-width: 768px){.level-item:not(:last-child){margin-bottom:.75rem}}.level-left,.level-right{flex-basis:auto;flex-grow:0;flex-shrink:0}.level-left .level-item.is-flexible,.level-right .level-item.is-flexible{flex-grow:1}@media screen and (min-width: 769px),print{.level-left .level-item:not(:last-child),.level-right .level-item:not(:last-child){margin-right:.75rem}}.level-left{align-items:center;justify-content:flex-start}@media screen and (max-width: 768px){.level-left+.level-right{margin-top:1.5rem}}@media screen and (min-width: 769px),print{.level-left{display:flex}}.level-right{align-items:center;justify-content:flex-end}@media screen and (min-width: 769px),print{.level-right{display:flex}}.list{background-color:#fff;border-radius:4px;box-shadow:0 2px 3px rgba(10,10,10,0.1),0 0 0 1px rgba(10,10,10,0.1)}.list-item{display:block;padding:0.5em 1em}.list-item:not(a){color:#222}.list-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-item:last-child{border-bottom-left-radius:4px;border-bottom-right-radius:4px}.list-item:not(:last-child){border-bottom:1px solid #dbdbdb}.list-item.is-active{background-color:#2e63b8;color:#fff}a.list-item{background-color:#f5f5f5;cursor:pointer}.media{align-items:flex-start;display:flex;text-align:left}.media .content:not(:last-child){margin-bottom:0.75rem}.media .media{border-top:1px solid rgba(219,219,219,0.5);display:flex;padding-top:0.75rem}.media .media .content:not(:last-child),.media .media .control:not(:last-child){margin-bottom:0.5rem}.media .media .media{padding-top:0.5rem}.media .media .media+.media{margin-top:0.5rem}.media+.media{border-top:1px solid rgba(219,219,219,0.5);margin-top:1rem;padding-top:1rem}.media.is-large+.media{margin-top:1.5rem;padding-top:1.5rem}.media-left,.media-right{flex-basis:auto;flex-grow:0;flex-shrink:0}.media-left{margin-right:1rem}.media-right{margin-left:1rem}.media-content{flex-basis:auto;flex-grow:1;flex-shrink:1;text-align:left}@media screen and (max-width: 768px){.media-content{overflow-x:auto}}.menu{font-size:1rem}.menu.is-small,#documenter .docs-sidebar form.docs-search>input.menu{font-size:.75rem}.menu.is-medium{font-size:1.25rem}.menu.is-large{font-size:1.5rem}.menu-list{line-height:1.25}.menu-list a{border-radius:2px;color:#222;display:block;padding:0.5em 0.75em}.menu-list a:hover{background-color:#f5f5f5;color:#222}.menu-list a.is-active{background-color:#2e63b8;color:#fff}.menu-list li ul{border-left:1px solid #dbdbdb;margin:.75em;padding-left:.75em}.menu-label{color:#6b6b6b;font-size:.75em;letter-spacing:.1em;text-transform:uppercase}.menu-label:not(:first-child){margin-top:1em}.menu-label:not(:last-child){margin-bottom:1em}.message{background-color:#f5f5f5;border-radius:4px;font-size:1rem}.message strong{color:currentColor}.message a:not(.button):not(.tag):not(.dropdown-item){color:currentColor;text-decoration:underline}.message.is-small,#documenter .docs-sidebar form.docs-search>input.message{font-size:.75rem}.message.is-medium{font-size:1.25rem}.message.is-large{font-size:1.5rem}.message.is-white{background-color:#fff}.message.is-white .message-header{background-color:#fff;color:#0a0a0a}.message.is-white .message-body{border-color:#fff;color:#4d4d4d}.message.is-black{background-color:#fafafa}.message.is-black .message-header{background-color:#0a0a0a;color:#fff}.message.is-black .message-body{border-color:#0a0a0a;color:#090909}.message.is-light{background-color:#fafafa}.message.is-light .message-header{background-color:#f5f5f5;color:#363636}.message.is-light .message-body{border-color:#f5f5f5;color:#505050}.message.is-dark,.content kbd.message{background-color:#fafafa}.message.is-dark .message-header,.content kbd.message .message-header{background-color:#363636;color:#f5f5f5}.message.is-dark .message-body,.content kbd.message .message-body{border-color:#363636;color:#2a2a2a}.message.is-primary,.docstring>section>a.message.docs-sourcelink{background-color:#f6fbfd}.message.is-primary .message-header,.docstring>section>a.message.docs-sourcelink .message-header{background-color:#4eb5de;color:#fff}.message.is-primary .message-body,.docstring>section>a.message.docs-sourcelink .message-body{border-color:#4eb5de;color:#1f556a}.message.is-link{background-color:#f7f9fd}.message.is-link .message-header{background-color:#2e63b8;color:#fff}.message.is-link .message-body{border-color:#2e63b8;color:#264981}.message.is-info{background-color:#f6fbfe}.message.is-info .message-header{background-color:#209cee;color:#fff}.message.is-info .message-body{border-color:#209cee;color:#12537d}.message.is-success{background-color:#f6fdf9}.message.is-success .message-header{background-color:#22c35b;color:#fff}.message.is-success .message-body{border-color:#22c35b;color:#0f361d}.message.is-warning{background-color:#fffdf5}.message.is-warning .message-header{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.message.is-warning .message-body{border-color:#ffdd57;color:#3c3108}.message.is-danger{background-color:#fff5f5}.message.is-danger .message-header{background-color:#da0b00;color:#fff}.message.is-danger .message-body{border-color:#da0b00;color:#9b0c04}.message-header{align-items:center;background-color:#222;border-radius:4px 4px 0 0;color:#fff;display:flex;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.75em 1em;position:relative}.message-header .delete{flex-grow:0;flex-shrink:0;margin-left:0.75em}.message-header+.message-body{border-width:0;border-top-left-radius:0;border-top-right-radius:0}.message-body{border-color:#dbdbdb;border-radius:4px;border-style:solid;border-width:0 0 0 4px;color:#222;padding:1.25em 1.5em}.message-body code,.message-body pre{background-color:#fff}.message-body pre code{background-color:rgba(0,0,0,0)}.modal{align-items:center;display:none;flex-direction:column;justify-content:center;overflow:hidden;position:fixed;z-index:40}.modal.is-active{display:flex}.modal-background{background-color:rgba(10,10,10,0.86)}.modal-content,.modal-card{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width: 769px),print{.modal-content,.modal-card{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}.modal-close{background:none;height:40px;position:fixed;right:20px;top:20px;width:40px}.modal-card{display:flex;flex-direction:column;max-height:calc(100vh - 40px);overflow:hidden;-ms-overflow-y:visible}.modal-card-head,.modal-card-foot{align-items:center;background-color:#f5f5f5;display:flex;flex-shrink:0;justify-content:flex-start;padding:20px;position:relative}.modal-card-head{border-bottom:1px solid #dbdbdb;border-top-left-radius:6px;border-top-right-radius:6px}.modal-card-title{color:#222;flex-grow:1;flex-shrink:0;font-size:1.5rem;line-height:1}.modal-card-foot{border-bottom-left-radius:6px;border-bottom-right-radius:6px;border-top:1px solid #dbdbdb}.modal-card-foot .button:not(:last-child){margin-right:0.5em}.modal-card-body{-webkit-overflow-scrolling:touch;background-color:#fff;flex-grow:1;flex-shrink:1;overflow:auto;padding:20px}.navbar{background-color:#fff;min-height:3.25rem;position:relative;z-index:30}.navbar.is-white{background-color:#fff;color:#0a0a0a}.navbar.is-white .navbar-brand>.navbar-item,.navbar.is-white .navbar-brand .navbar-link{color:#0a0a0a}.navbar.is-white .navbar-brand>a.navbar-item:focus,.navbar.is-white .navbar-brand>a.navbar-item:hover,.navbar.is-white .navbar-brand>a.navbar-item.is-active,.navbar.is-white .navbar-brand .navbar-link:focus,.navbar.is-white .navbar-brand .navbar-link:hover,.navbar.is-white .navbar-brand .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-brand .navbar-link::after{border-color:#0a0a0a}.navbar.is-white .navbar-burger{color:#0a0a0a}@media screen and (min-width: 1056px){.navbar.is-white .navbar-start>.navbar-item,.navbar.is-white .navbar-start .navbar-link,.navbar.is-white .navbar-end>.navbar-item,.navbar.is-white .navbar-end .navbar-link{color:#0a0a0a}.navbar.is-white .navbar-start>a.navbar-item:focus,.navbar.is-white .navbar-start>a.navbar-item:hover,.navbar.is-white .navbar-start>a.navbar-item.is-active,.navbar.is-white .navbar-start .navbar-link:focus,.navbar.is-white .navbar-start .navbar-link:hover,.navbar.is-white .navbar-start .navbar-link.is-active,.navbar.is-white .navbar-end>a.navbar-item:focus,.navbar.is-white .navbar-end>a.navbar-item:hover,.navbar.is-white .navbar-end>a.navbar-item.is-active,.navbar.is-white .navbar-end .navbar-link:focus,.navbar.is-white .navbar-end .navbar-link:hover,.navbar.is-white .navbar-end .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-start .navbar-link::after,.navbar.is-white .navbar-end .navbar-link::after{border-color:#0a0a0a}.navbar.is-white .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-white .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-dropdown a.navbar-item.is-active{background-color:#fff;color:#0a0a0a}}.navbar.is-black{background-color:#0a0a0a;color:#fff}.navbar.is-black .navbar-brand>.navbar-item,.navbar.is-black .navbar-brand .navbar-link{color:#fff}.navbar.is-black .navbar-brand>a.navbar-item:focus,.navbar.is-black .navbar-brand>a.navbar-item:hover,.navbar.is-black .navbar-brand>a.navbar-item.is-active,.navbar.is-black .navbar-brand .navbar-link:focus,.navbar.is-black .navbar-brand .navbar-link:hover,.navbar.is-black .navbar-brand .navbar-link.is-active{background-color:#000;color:#fff}.navbar.is-black .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-black .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-black .navbar-start>.navbar-item,.navbar.is-black .navbar-start .navbar-link,.navbar.is-black .navbar-end>.navbar-item,.navbar.is-black .navbar-end .navbar-link{color:#fff}.navbar.is-black .navbar-start>a.navbar-item:focus,.navbar.is-black .navbar-start>a.navbar-item:hover,.navbar.is-black .navbar-start>a.navbar-item.is-active,.navbar.is-black .navbar-start .navbar-link:focus,.navbar.is-black .navbar-start .navbar-link:hover,.navbar.is-black .navbar-start .navbar-link.is-active,.navbar.is-black .navbar-end>a.navbar-item:focus,.navbar.is-black .navbar-end>a.navbar-item:hover,.navbar.is-black .navbar-end>a.navbar-item.is-active,.navbar.is-black .navbar-end .navbar-link:focus,.navbar.is-black .navbar-end .navbar-link:hover,.navbar.is-black .navbar-end .navbar-link.is-active{background-color:#000;color:#fff}.navbar.is-black .navbar-start .navbar-link::after,.navbar.is-black .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-black .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-black .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link{background-color:#000;color:#fff}.navbar.is-black .navbar-dropdown a.navbar-item.is-active{background-color:#0a0a0a;color:#fff}}.navbar.is-light{background-color:#f5f5f5;color:#363636}.navbar.is-light .navbar-brand>.navbar-item,.navbar.is-light .navbar-brand .navbar-link{color:#363636}.navbar.is-light .navbar-brand>a.navbar-item:focus,.navbar.is-light .navbar-brand>a.navbar-item:hover,.navbar.is-light .navbar-brand>a.navbar-item.is-active,.navbar.is-light .navbar-brand .navbar-link:focus,.navbar.is-light .navbar-brand .navbar-link:hover,.navbar.is-light .navbar-brand .navbar-link.is-active{background-color:#e8e8e8;color:#363636}.navbar.is-light .navbar-brand .navbar-link::after{border-color:#363636}.navbar.is-light .navbar-burger{color:#363636}@media screen and (min-width: 1056px){.navbar.is-light .navbar-start>.navbar-item,.navbar.is-light .navbar-start .navbar-link,.navbar.is-light .navbar-end>.navbar-item,.navbar.is-light .navbar-end .navbar-link{color:#363636}.navbar.is-light .navbar-start>a.navbar-item:focus,.navbar.is-light .navbar-start>a.navbar-item:hover,.navbar.is-light .navbar-start>a.navbar-item.is-active,.navbar.is-light .navbar-start .navbar-link:focus,.navbar.is-light .navbar-start .navbar-link:hover,.navbar.is-light .navbar-start .navbar-link.is-active,.navbar.is-light .navbar-end>a.navbar-item:focus,.navbar.is-light .navbar-end>a.navbar-item:hover,.navbar.is-light .navbar-end>a.navbar-item.is-active,.navbar.is-light .navbar-end .navbar-link:focus,.navbar.is-light .navbar-end .navbar-link:hover,.navbar.is-light .navbar-end .navbar-link.is-active{background-color:#e8e8e8;color:#363636}.navbar.is-light .navbar-start .navbar-link::after,.navbar.is-light .navbar-end .navbar-link::after{border-color:#363636}.navbar.is-light .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-light .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link{background-color:#e8e8e8;color:#363636}.navbar.is-light .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#363636}}.navbar.is-dark,.content kbd.navbar{background-color:#363636;color:#f5f5f5}.navbar.is-dark .navbar-brand>.navbar-item,.content kbd.navbar .navbar-brand>.navbar-item,.navbar.is-dark .navbar-brand .navbar-link,.content kbd.navbar .navbar-brand .navbar-link{color:#f5f5f5}.navbar.is-dark .navbar-brand>a.navbar-item:focus,.content kbd.navbar .navbar-brand>a.navbar-item:focus,.navbar.is-dark .navbar-brand>a.navbar-item:hover,.content kbd.navbar .navbar-brand>a.navbar-item:hover,.navbar.is-dark .navbar-brand>a.navbar-item.is-active,.content kbd.navbar .navbar-brand>a.navbar-item.is-active,.navbar.is-dark .navbar-brand .navbar-link:focus,.content kbd.navbar .navbar-brand .navbar-link:focus,.navbar.is-dark .navbar-brand .navbar-link:hover,.content kbd.navbar .navbar-brand .navbar-link:hover,.navbar.is-dark .navbar-brand .navbar-link.is-active,.content kbd.navbar .navbar-brand .navbar-link.is-active{background-color:#292929;color:#f5f5f5}.navbar.is-dark .navbar-brand .navbar-link::after,.content kbd.navbar .navbar-brand .navbar-link::after{border-color:#f5f5f5}.navbar.is-dark .navbar-burger,.content kbd.navbar .navbar-burger{color:#f5f5f5}@media screen and (min-width: 1056px){.navbar.is-dark .navbar-start>.navbar-item,.content kbd.navbar .navbar-start>.navbar-item,.navbar.is-dark .navbar-start .navbar-link,.content kbd.navbar .navbar-start .navbar-link,.navbar.is-dark .navbar-end>.navbar-item,.content kbd.navbar .navbar-end>.navbar-item,.navbar.is-dark .navbar-end .navbar-link,.content kbd.navbar .navbar-end .navbar-link{color:#f5f5f5}.navbar.is-dark .navbar-start>a.navbar-item:focus,.content kbd.navbar .navbar-start>a.navbar-item:focus,.navbar.is-dark .navbar-start>a.navbar-item:hover,.content kbd.navbar .navbar-start>a.navbar-item:hover,.navbar.is-dark .navbar-start>a.navbar-item.is-active,.content kbd.navbar .navbar-start>a.navbar-item.is-active,.navbar.is-dark .navbar-start .navbar-link:focus,.content kbd.navbar .navbar-start .navbar-link:focus,.navbar.is-dark .navbar-start .navbar-link:hover,.content kbd.navbar .navbar-start .navbar-link:hover,.navbar.is-dark .navbar-start .navbar-link.is-active,.content kbd.navbar .navbar-start .navbar-link.is-active,.navbar.is-dark .navbar-end>a.navbar-item:focus,.content kbd.navbar .navbar-end>a.navbar-item:focus,.navbar.is-dark .navbar-end>a.navbar-item:hover,.content kbd.navbar .navbar-end>a.navbar-item:hover,.navbar.is-dark .navbar-end>a.navbar-item.is-active,.content kbd.navbar .navbar-end>a.navbar-item.is-active,.navbar.is-dark .navbar-end .navbar-link:focus,.content kbd.navbar .navbar-end .navbar-link:focus,.navbar.is-dark .navbar-end .navbar-link:hover,.content kbd.navbar .navbar-end .navbar-link:hover,.navbar.is-dark .navbar-end .navbar-link.is-active,.content kbd.navbar .navbar-end .navbar-link.is-active{background-color:#292929;color:#f5f5f5}.navbar.is-dark .navbar-start .navbar-link::after,.content kbd.navbar .navbar-start .navbar-link::after,.navbar.is-dark .navbar-end .navbar-link::after,.content kbd.navbar .navbar-end .navbar-link::after{border-color:#f5f5f5}.navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link,.content kbd.navbar .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link,.content kbd.navbar .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link,.content kbd.navbar .navbar-item.has-dropdown.is-active .navbar-link{background-color:#292929;color:#f5f5f5}.navbar.is-dark .navbar-dropdown a.navbar-item.is-active,.content kbd.navbar .navbar-dropdown a.navbar-item.is-active{background-color:#363636;color:#f5f5f5}}.navbar.is-primary,.docstring>section>a.navbar.docs-sourcelink{background-color:#4eb5de;color:#fff}.navbar.is-primary .navbar-brand>.navbar-item,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>.navbar-item,.navbar.is-primary .navbar-brand .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link{color:#fff}.navbar.is-primary .navbar-brand>a.navbar-item:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:focus,.navbar.is-primary .navbar-brand>a.navbar-item:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:hover,.navbar.is-primary .navbar-brand>a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item.is-active,.navbar.is-primary .navbar-brand .navbar-link:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:focus,.navbar.is-primary .navbar-brand .navbar-link:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:hover,.navbar.is-primary .navbar-brand .navbar-link.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link.is-active{background-color:#39acda;color:#fff}.navbar.is-primary .navbar-brand .navbar-link::after,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-primary .navbar-burger,.docstring>section>a.navbar.docs-sourcelink .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-primary .navbar-start>.navbar-item,.docstring>section>a.navbar.docs-sourcelink .navbar-start>.navbar-item,.navbar.is-primary .navbar-start .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link,.navbar.is-primary .navbar-end>.navbar-item,.docstring>section>a.navbar.docs-sourcelink .navbar-end>.navbar-item,.navbar.is-primary .navbar-end .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link{color:#fff}.navbar.is-primary .navbar-start>a.navbar-item:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:focus,.navbar.is-primary .navbar-start>a.navbar-item:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:hover,.navbar.is-primary .navbar-start>a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item.is-active,.navbar.is-primary .navbar-start .navbar-link:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:focus,.navbar.is-primary .navbar-start .navbar-link:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:hover,.navbar.is-primary .navbar-start .navbar-link.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link.is-active,.navbar.is-primary .navbar-end>a.navbar-item:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:focus,.navbar.is-primary .navbar-end>a.navbar-item:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:hover,.navbar.is-primary .navbar-end>a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item.is-active,.navbar.is-primary .navbar-end .navbar-link:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:focus,.navbar.is-primary .navbar-end .navbar-link:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:hover,.navbar.is-primary .navbar-end .navbar-link.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link.is-active{background-color:#39acda;color:#fff}.navbar.is-primary .navbar-start .navbar-link::after,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link::after,.navbar.is-primary .navbar-end .navbar-link::after,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown.is-active .navbar-link{background-color:#39acda;color:#fff}.navbar.is-primary .navbar-dropdown a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#4eb5de;color:#fff}}.navbar.is-link{background-color:#2e63b8;color:#fff}.navbar.is-link .navbar-brand>.navbar-item,.navbar.is-link .navbar-brand .navbar-link{color:#fff}.navbar.is-link .navbar-brand>a.navbar-item:focus,.navbar.is-link .navbar-brand>a.navbar-item:hover,.navbar.is-link .navbar-brand>a.navbar-item.is-active,.navbar.is-link .navbar-brand .navbar-link:focus,.navbar.is-link .navbar-brand .navbar-link:hover,.navbar.is-link .navbar-brand .navbar-link.is-active{background-color:#2958a4;color:#fff}.navbar.is-link .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-link .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-link .navbar-start>.navbar-item,.navbar.is-link .navbar-start .navbar-link,.navbar.is-link .navbar-end>.navbar-item,.navbar.is-link .navbar-end .navbar-link{color:#fff}.navbar.is-link .navbar-start>a.navbar-item:focus,.navbar.is-link .navbar-start>a.navbar-item:hover,.navbar.is-link .navbar-start>a.navbar-item.is-active,.navbar.is-link .navbar-start .navbar-link:focus,.navbar.is-link .navbar-start .navbar-link:hover,.navbar.is-link .navbar-start .navbar-link.is-active,.navbar.is-link .navbar-end>a.navbar-item:focus,.navbar.is-link .navbar-end>a.navbar-item:hover,.navbar.is-link .navbar-end>a.navbar-item.is-active,.navbar.is-link .navbar-end .navbar-link:focus,.navbar.is-link .navbar-end .navbar-link:hover,.navbar.is-link .navbar-end .navbar-link.is-active{background-color:#2958a4;color:#fff}.navbar.is-link .navbar-start .navbar-link::after,.navbar.is-link .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-link .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-link .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link{background-color:#2958a4;color:#fff}.navbar.is-link .navbar-dropdown a.navbar-item.is-active{background-color:#2e63b8;color:#fff}}.navbar.is-info{background-color:#209cee;color:#fff}.navbar.is-info .navbar-brand>.navbar-item,.navbar.is-info .navbar-brand .navbar-link{color:#fff}.navbar.is-info .navbar-brand>a.navbar-item:focus,.navbar.is-info .navbar-brand>a.navbar-item:hover,.navbar.is-info .navbar-brand>a.navbar-item.is-active,.navbar.is-info .navbar-brand .navbar-link:focus,.navbar.is-info .navbar-brand .navbar-link:hover,.navbar.is-info .navbar-brand .navbar-link.is-active{background-color:#1190e3;color:#fff}.navbar.is-info .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-info .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-info .navbar-start>.navbar-item,.navbar.is-info .navbar-start .navbar-link,.navbar.is-info .navbar-end>.navbar-item,.navbar.is-info .navbar-end .navbar-link{color:#fff}.navbar.is-info .navbar-start>a.navbar-item:focus,.navbar.is-info .navbar-start>a.navbar-item:hover,.navbar.is-info .navbar-start>a.navbar-item.is-active,.navbar.is-info .navbar-start .navbar-link:focus,.navbar.is-info .navbar-start .navbar-link:hover,.navbar.is-info .navbar-start .navbar-link.is-active,.navbar.is-info .navbar-end>a.navbar-item:focus,.navbar.is-info .navbar-end>a.navbar-item:hover,.navbar.is-info .navbar-end>a.navbar-item.is-active,.navbar.is-info .navbar-end .navbar-link:focus,.navbar.is-info .navbar-end .navbar-link:hover,.navbar.is-info .navbar-end .navbar-link.is-active{background-color:#1190e3;color:#fff}.navbar.is-info .navbar-start .navbar-link::after,.navbar.is-info .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-info .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-info .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link{background-color:#1190e3;color:#fff}.navbar.is-info .navbar-dropdown a.navbar-item.is-active{background-color:#209cee;color:#fff}}.navbar.is-success{background-color:#22c35b;color:#fff}.navbar.is-success .navbar-brand>.navbar-item,.navbar.is-success .navbar-brand .navbar-link{color:#fff}.navbar.is-success .navbar-brand>a.navbar-item:focus,.navbar.is-success .navbar-brand>a.navbar-item:hover,.navbar.is-success .navbar-brand>a.navbar-item.is-active,.navbar.is-success .navbar-brand .navbar-link:focus,.navbar.is-success .navbar-brand .navbar-link:hover,.navbar.is-success .navbar-brand .navbar-link.is-active{background-color:#1ead51;color:#fff}.navbar.is-success .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-success .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-success .navbar-start>.navbar-item,.navbar.is-success .navbar-start .navbar-link,.navbar.is-success .navbar-end>.navbar-item,.navbar.is-success .navbar-end .navbar-link{color:#fff}.navbar.is-success .navbar-start>a.navbar-item:focus,.navbar.is-success .navbar-start>a.navbar-item:hover,.navbar.is-success .navbar-start>a.navbar-item.is-active,.navbar.is-success .navbar-start .navbar-link:focus,.navbar.is-success .navbar-start .navbar-link:hover,.navbar.is-success .navbar-start .navbar-link.is-active,.navbar.is-success .navbar-end>a.navbar-item:focus,.navbar.is-success .navbar-end>a.navbar-item:hover,.navbar.is-success .navbar-end>a.navbar-item.is-active,.navbar.is-success .navbar-end .navbar-link:focus,.navbar.is-success .navbar-end .navbar-link:hover,.navbar.is-success .navbar-end .navbar-link.is-active{background-color:#1ead51;color:#fff}.navbar.is-success .navbar-start .navbar-link::after,.navbar.is-success .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-success .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-success .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link{background-color:#1ead51;color:#fff}.navbar.is-success .navbar-dropdown a.navbar-item.is-active{background-color:#22c35b;color:#fff}}.navbar.is-warning{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-brand>.navbar-item,.navbar.is-warning .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-brand>a.navbar-item:focus,.navbar.is-warning .navbar-brand>a.navbar-item:hover,.navbar.is-warning .navbar-brand>a.navbar-item.is-active,.navbar.is-warning .navbar-brand .navbar-link:focus,.navbar.is-warning .navbar-brand .navbar-link:hover,.navbar.is-warning .navbar-brand .navbar-link.is-active{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){.navbar.is-warning .navbar-start>.navbar-item,.navbar.is-warning .navbar-start .navbar-link,.navbar.is-warning .navbar-end>.navbar-item,.navbar.is-warning .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-start>a.navbar-item:focus,.navbar.is-warning .navbar-start>a.navbar-item:hover,.navbar.is-warning .navbar-start>a.navbar-item.is-active,.navbar.is-warning .navbar-start .navbar-link:focus,.navbar.is-warning .navbar-start .navbar-link:hover,.navbar.is-warning .navbar-start .navbar-link.is-active,.navbar.is-warning .navbar-end>a.navbar-item:focus,.navbar.is-warning .navbar-end>a.navbar-item:hover,.navbar.is-warning .navbar-end>a.navbar-item.is-active,.navbar.is-warning .navbar-end .navbar-link:focus,.navbar.is-warning .navbar-end .navbar-link:hover,.navbar.is-warning .navbar-end .navbar-link.is-active{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-start .navbar-link::after,.navbar.is-warning .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-dropdown a.navbar-item.is-active{background-color:#ffdd57;color:rgba(0,0,0,0.7)}}.navbar.is-danger{background-color:#da0b00;color:#fff}.navbar.is-danger .navbar-brand>.navbar-item,.navbar.is-danger .navbar-brand .navbar-link{color:#fff}.navbar.is-danger .navbar-brand>a.navbar-item:focus,.navbar.is-danger .navbar-brand>a.navbar-item:hover,.navbar.is-danger .navbar-brand>a.navbar-item.is-active,.navbar.is-danger .navbar-brand .navbar-link:focus,.navbar.is-danger .navbar-brand .navbar-link:hover,.navbar.is-danger .navbar-brand .navbar-link.is-active{background-color:#c10a00;color:#fff}.navbar.is-danger .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-danger .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-danger .navbar-start>.navbar-item,.navbar.is-danger .navbar-start .navbar-link,.navbar.is-danger .navbar-end>.navbar-item,.navbar.is-danger .navbar-end .navbar-link{color:#fff}.navbar.is-danger .navbar-start>a.navbar-item:focus,.navbar.is-danger .navbar-start>a.navbar-item:hover,.navbar.is-danger .navbar-start>a.navbar-item.is-active,.navbar.is-danger .navbar-start .navbar-link:focus,.navbar.is-danger .navbar-start .navbar-link:hover,.navbar.is-danger .navbar-start .navbar-link.is-active,.navbar.is-danger .navbar-end>a.navbar-item:focus,.navbar.is-danger .navbar-end>a.navbar-item:hover,.navbar.is-danger .navbar-end>a.navbar-item.is-active,.navbar.is-danger .navbar-end .navbar-link:focus,.navbar.is-danger .navbar-end .navbar-link:hover,.navbar.is-danger .navbar-end .navbar-link.is-active{background-color:#c10a00;color:#fff}.navbar.is-danger .navbar-start .navbar-link::after,.navbar.is-danger .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link{background-color:#c10a00;color:#fff}.navbar.is-danger .navbar-dropdown a.navbar-item.is-active{background-color:#da0b00;color:#fff}}.navbar>.container{align-items:stretch;display:flex;min-height:3.25rem;width:100%}.navbar.has-shadow{box-shadow:0 2px 0 0 #f5f5f5}.navbar.is-fixed-bottom,.navbar.is-fixed-top{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom{bottom:0}.navbar.is-fixed-bottom.has-shadow{box-shadow:0 -2px 0 0 #f5f5f5}.navbar.is-fixed-top{top:0}html.has-navbar-fixed-top,body.has-navbar-fixed-top{padding-top:3.25rem}html.has-navbar-fixed-bottom,body.has-navbar-fixed-bottom{padding-bottom:3.25rem}.navbar-brand,.navbar-tabs{align-items:stretch;display:flex;flex-shrink:0;min-height:3.25rem}.navbar-brand a.navbar-item:focus,.navbar-brand a.navbar-item:hover{background-color:transparent}.navbar-tabs{-webkit-overflow-scrolling:touch;max-width:100vw;overflow-x:auto;overflow-y:hidden}.navbar-burger{color:#4a4a4a;cursor:pointer;display:block;height:3.25rem;position:relative;width:3.25rem;margin-left:auto}.navbar-burger span{background-color:currentColor;display:block;height:1px;left:calc(50% - 8px);position:absolute;transform-origin:center;transition-duration:86ms;transition-property:background-color, opacity, transform;transition-timing-function:ease-out;width:16px}.navbar-burger span:nth-child(1){top:calc(50% - 6px)}.navbar-burger span:nth-child(2){top:calc(50% - 1px)}.navbar-burger span:nth-child(3){top:calc(50% + 4px)}.navbar-burger:hover{background-color:rgba(0,0,0,0.05)}.navbar-burger.is-active span:nth-child(1){transform:translateY(5px) rotate(45deg)}.navbar-burger.is-active span:nth-child(2){opacity:0}.navbar-burger.is-active span:nth-child(3){transform:translateY(-5px) rotate(-45deg)}.navbar-menu{display:none}.navbar-item,.navbar-link{color:#4a4a4a;display:block;line-height:1.5;padding:0.5rem 0.75rem;position:relative}.navbar-item .icon:only-child,.navbar-link .icon:only-child{margin-left:-0.25rem;margin-right:-0.25rem}a.navbar-item,.navbar-link{cursor:pointer}a.navbar-item:focus,a.navbar-item:focus-within,a.navbar-item:hover,a.navbar-item.is-active,.navbar-link:focus,.navbar-link:focus-within,.navbar-link:hover,.navbar-link.is-active{background-color:#fafafa;color:#2e63b8}.navbar-item{display:block;flex-grow:0;flex-shrink:0}.navbar-item img{max-height:1.75rem}.navbar-item.has-dropdown{padding:0}.navbar-item.is-expanded{flex-grow:1;flex-shrink:1}.navbar-item.is-tab{border-bottom:1px solid transparent;min-height:3.25rem;padding-bottom:calc(0.5rem - 1px)}.navbar-item.is-tab:focus,.navbar-item.is-tab:hover{background-color:rgba(0,0,0,0);border-bottom-color:#2e63b8}.navbar-item.is-tab.is-active{background-color:rgba(0,0,0,0);border-bottom-color:#2e63b8;border-bottom-style:solid;border-bottom-width:3px;color:#2e63b8;padding-bottom:calc(0.5rem - 3px)}.navbar-content{flex-grow:1;flex-shrink:1}.navbar-link:not(.is-arrowless){padding-right:2.5em}.navbar-link:not(.is-arrowless)::after{border-color:#2e63b8;margin-top:-0.375em;right:1.125em}.navbar-dropdown{font-size:0.875rem;padding-bottom:0.5rem;padding-top:0.5rem}.navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}.navbar-divider{background-color:#f5f5f5;border:none;display:none;height:2px;margin:0.5rem 0}@media screen and (max-width: 1055px){.navbar>.container{display:block}.navbar-brand .navbar-item,.navbar-tabs .navbar-item{align-items:center;display:flex}.navbar-link::after{display:none}.navbar-menu{background-color:#fff;box-shadow:0 8px 16px rgba(10,10,10,0.1);padding:0.5rem 0}.navbar-menu.is-active{display:block}.navbar.is-fixed-bottom-touch,.navbar.is-fixed-top-touch{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom-touch{bottom:0}.navbar.is-fixed-bottom-touch.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}.navbar.is-fixed-top-touch{top:0}.navbar.is-fixed-top .navbar-menu,.navbar.is-fixed-top-touch .navbar-menu{-webkit-overflow-scrolling:touch;max-height:calc(100vh - 3.25rem);overflow:auto}html.has-navbar-fixed-top-touch,body.has-navbar-fixed-top-touch{padding-top:3.25rem}html.has-navbar-fixed-bottom-touch,body.has-navbar-fixed-bottom-touch{padding-bottom:3.25rem}}@media screen and (min-width: 1056px){.navbar,.navbar-menu,.navbar-start,.navbar-end{align-items:stretch;display:flex}.navbar{min-height:3.25rem}.navbar.is-spaced{padding:1rem 2rem}.navbar.is-spaced .navbar-start,.navbar.is-spaced .navbar-end{align-items:center}.navbar.is-spaced a.navbar-item,.navbar.is-spaced .navbar-link{border-radius:4px}.navbar.is-transparent a.navbar-item:focus,.navbar.is-transparent a.navbar-item:hover,.navbar.is-transparent a.navbar-item.is-active,.navbar.is-transparent .navbar-link:focus,.navbar.is-transparent .navbar-link:hover,.navbar.is-transparent .navbar-link.is-active{background-color:transparent !important}.navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link{background-color:transparent !important}.navbar.is-transparent .navbar-dropdown a.navbar-item:focus,.navbar.is-transparent .navbar-dropdown a.navbar-item:hover{background-color:#f5f5f5;color:#0a0a0a}.navbar.is-transparent .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#2e63b8}.navbar-burger{display:none}.navbar-item,.navbar-link{align-items:center;display:flex}.navbar-item{display:flex}.navbar-item.has-dropdown{align-items:stretch}.navbar-item.has-dropdown-up .navbar-link::after{transform:rotate(135deg) translate(0.25em, -0.25em)}.navbar-item.has-dropdown-up .navbar-dropdown{border-bottom:2px solid #dbdbdb;border-radius:6px 6px 0 0;border-top:none;bottom:100%;box-shadow:0 -8px 8px rgba(10,10,10,0.1);top:auto}.navbar-item.is-active .navbar-dropdown,.navbar-item.is-hoverable:focus .navbar-dropdown,.navbar-item.is-hoverable:focus-within .navbar-dropdown,.navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar.is-spaced .navbar-item.is-active .navbar-dropdown,.navbar-item.is-active .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-hoverable:focus .navbar-dropdown,.navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-hoverable:focus-within .navbar-dropdown,.navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-hoverable:hover .navbar-dropdown,.navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed{opacity:1;pointer-events:auto;transform:translateY(0)}.navbar-menu{flex-grow:1;flex-shrink:0}.navbar-start{justify-content:flex-start;margin-right:auto}.navbar-end{justify-content:flex-end;margin-left:auto}.navbar-dropdown{background-color:#fff;border-bottom-left-radius:6px;border-bottom-right-radius:6px;border-top:2px solid #dbdbdb;box-shadow:0 8px 8px rgba(10,10,10,0.1);display:none;font-size:0.875rem;left:0;min-width:100%;position:absolute;top:100%;z-index:20}.navbar-dropdown .navbar-item{padding:0.375rem 1rem;white-space:nowrap}.navbar-dropdown a.navbar-item{padding-right:3rem}.navbar-dropdown a.navbar-item:focus,.navbar-dropdown a.navbar-item:hover{background-color:#f5f5f5;color:#0a0a0a}.navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#2e63b8}.navbar.is-spaced .navbar-dropdown,.navbar-dropdown.is-boxed{border-radius:6px;border-top:none;box-shadow:0 8px 8px rgba(10,10,10,0.1), 0 0 0 1px rgba(10,10,10,0.1);display:block;opacity:0;pointer-events:none;top:calc(100% + (-4px));transform:translateY(-5px);transition-duration:86ms;transition-property:opacity, transform}.navbar-dropdown.is-right{left:auto;right:0}.navbar-divider{display:block}.navbar>.container .navbar-brand,.container>.navbar .navbar-brand{margin-left:-.75rem}.navbar>.container .navbar-menu,.container>.navbar .navbar-menu{margin-right:-.75rem}.navbar.is-fixed-bottom-desktop,.navbar.is-fixed-top-desktop{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom-desktop{bottom:0}.navbar.is-fixed-bottom-desktop.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}.navbar.is-fixed-top-desktop{top:0}html.has-navbar-fixed-top-desktop,body.has-navbar-fixed-top-desktop{padding-top:3.25rem}html.has-navbar-fixed-bottom-desktop,body.has-navbar-fixed-bottom-desktop{padding-bottom:3.25rem}html.has-spaced-navbar-fixed-top,body.has-spaced-navbar-fixed-top{padding-top:5.25rem}html.has-spaced-navbar-fixed-bottom,body.has-spaced-navbar-fixed-bottom{padding-bottom:5.25rem}a.navbar-item.is-active,.navbar-link.is-active{color:#0a0a0a}a.navbar-item.is-active:not(:focus):not(:hover),.navbar-link.is-active:not(:focus):not(:hover){background-color:rgba(0,0,0,0)}.navbar-item.has-dropdown:focus .navbar-link,.navbar-item.has-dropdown:hover .navbar-link,.navbar-item.has-dropdown.is-active .navbar-link{background-color:#fafafa}}.hero.is-fullheight-with-navbar{min-height:calc(100vh - 3.25rem)}.pagination{font-size:1rem;margin:-.25rem}.pagination.is-small,#documenter .docs-sidebar form.docs-search>input.pagination{font-size:.75rem}.pagination.is-medium{font-size:1.25rem}.pagination.is-large{font-size:1.5rem}.pagination.is-rounded .pagination-previous,#documenter .docs-sidebar form.docs-search>input.pagination .pagination-previous,.pagination.is-rounded .pagination-next,#documenter .docs-sidebar form.docs-search>input.pagination .pagination-next{padding-left:1em;padding-right:1em;border-radius:290486px}.pagination.is-rounded .pagination-link,#documenter .docs-sidebar form.docs-search>input.pagination .pagination-link{border-radius:290486px}.pagination,.pagination-list{align-items:center;display:flex;justify-content:center;text-align:center}.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis{font-size:1em;justify-content:center;margin:.25rem;padding-left:.5em;padding-right:.5em;text-align:center}.pagination-previous,.pagination-next,.pagination-link{border-color:#dbdbdb;color:#363636;min-width:2.25em}.pagination-previous:hover,.pagination-next:hover,.pagination-link:hover{border-color:#b5b5b5;color:#363636}.pagination-previous:focus,.pagination-next:focus,.pagination-link:focus{border-color:#3c5dcd}.pagination-previous:active,.pagination-next:active,.pagination-link:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2)}.pagination-previous[disabled],.pagination-next[disabled],.pagination-link[disabled]{background-color:#dbdbdb;border-color:#dbdbdb;box-shadow:none;color:#6b6b6b;opacity:0.5}.pagination-previous,.pagination-next{padding-left:0.75em;padding-right:0.75em;white-space:nowrap}.pagination-link.is-current{background-color:#2e63b8;border-color:#2e63b8;color:#fff}.pagination-ellipsis{color:#b5b5b5;pointer-events:none}.pagination-list{flex-wrap:wrap}@media screen and (max-width: 768px){.pagination{flex-wrap:wrap}.pagination-previous,.pagination-next{flex-grow:1;flex-shrink:1}.pagination-list li{flex-grow:1;flex-shrink:1}}@media screen and (min-width: 769px),print{.pagination-list{flex-grow:1;flex-shrink:1;justify-content:flex-start;order:1}.pagination-previous{order:2}.pagination-next{order:3}.pagination{justify-content:space-between}.pagination.is-centered .pagination-previous{order:1}.pagination.is-centered .pagination-list{justify-content:center;order:2}.pagination.is-centered .pagination-next{order:3}.pagination.is-right .pagination-previous{order:1}.pagination.is-right .pagination-next{order:2}.pagination.is-right .pagination-list{justify-content:flex-end;order:3}}.panel{font-size:1rem}.panel:not(:last-child){margin-bottom:1.5rem}.panel-heading,.panel-tabs,.panel-block{border-bottom:1px solid #dbdbdb;border-left:1px solid #dbdbdb;border-right:1px solid #dbdbdb}.panel-heading:first-child,.panel-tabs:first-child,.panel-block:first-child{border-top:1px solid #dbdbdb}.panel-heading{background-color:#f5f5f5;border-radius:4px 4px 0 0;color:#222;font-size:1.25em;font-weight:300;line-height:1.25;padding:0.5em 0.75em}.panel-tabs{align-items:flex-end;display:flex;font-size:.875em;justify-content:center}.panel-tabs a{border-bottom:1px solid #dbdbdb;margin-bottom:-1px;padding:0.5em}.panel-tabs a.is-active{border-bottom-color:#4a4a4a;color:#363636}.panel-list a{color:#222}.panel-list a:hover{color:#2e63b8}.panel-block{align-items:center;color:#222;display:flex;justify-content:flex-start;padding:0.5em 0.75em}.panel-block input[type="checkbox"]{margin-right:0.75em}.panel-block>.control{flex-grow:1;flex-shrink:1;width:100%}.panel-block.is-wrapped{flex-wrap:wrap}.panel-block.is-active{border-left-color:#2e63b8;color:#363636}.panel-block.is-active .panel-icon{color:#2e63b8}a.panel-block,label.panel-block{cursor:pointer}a.panel-block:hover,label.panel-block:hover{background-color:#f5f5f5}.panel-icon{display:inline-block;font-size:14px;height:1em;line-height:1em;text-align:center;vertical-align:top;width:1em;color:#6b6b6b;margin-right:0.75em}.panel-icon .fa{font-size:inherit;line-height:inherit}.tabs{-webkit-overflow-scrolling:touch;align-items:stretch;display:flex;font-size:1rem;justify-content:space-between;overflow:hidden;overflow-x:auto;white-space:nowrap}.tabs a{align-items:center;border-bottom-color:#dbdbdb;border-bottom-style:solid;border-bottom-width:1px;color:#222;display:flex;justify-content:center;margin-bottom:-1px;padding:0.5em 1em;vertical-align:top}.tabs a:hover{border-bottom-color:#222;color:#222}.tabs li{display:block}.tabs li.is-active a{border-bottom-color:#2e63b8;color:#2e63b8}.tabs ul{align-items:center;border-bottom-color:#dbdbdb;border-bottom-style:solid;border-bottom-width:1px;display:flex;flex-grow:1;flex-shrink:0;justify-content:flex-start}.tabs ul.is-left{padding-right:0.75em}.tabs ul.is-center{flex:none;justify-content:center;padding-left:0.75em;padding-right:0.75em}.tabs ul.is-right{justify-content:flex-end;padding-left:0.75em}.tabs .icon:first-child{margin-right:0.5em}.tabs .icon:last-child{margin-left:0.5em}.tabs.is-centered ul{justify-content:center}.tabs.is-right ul{justify-content:flex-end}.tabs.is-boxed a{border:1px solid transparent;border-radius:4px 4px 0 0}.tabs.is-boxed a:hover{background-color:#f5f5f5;border-bottom-color:#dbdbdb}.tabs.is-boxed li.is-active a{background-color:#fff;border-color:#dbdbdb;border-bottom-color:rgba(0,0,0,0) !important}.tabs.is-fullwidth li{flex-grow:1;flex-shrink:0}.tabs.is-toggle a{border-color:#dbdbdb;border-style:solid;border-width:1px;margin-bottom:0;position:relative}.tabs.is-toggle a:hover{background-color:#f5f5f5;border-color:#b5b5b5;z-index:2}.tabs.is-toggle li+li{margin-left:-1px}.tabs.is-toggle li:first-child a{border-radius:4px 0 0 4px}.tabs.is-toggle li:last-child a{border-radius:0 4px 4px 0}.tabs.is-toggle li.is-active a{background-color:#2e63b8;border-color:#2e63b8;color:#fff;z-index:1}.tabs.is-toggle ul{border-bottom:none}.tabs.is-toggle.is-toggle-rounded li:first-child a{border-bottom-left-radius:290486px;border-top-left-radius:290486px;padding-left:1.25em}.tabs.is-toggle.is-toggle-rounded li:last-child a{border-bottom-right-radius:290486px;border-top-right-radius:290486px;padding-right:1.25em}.tabs.is-small,#documenter .docs-sidebar form.docs-search>input.tabs{font-size:.75rem}.tabs.is-medium{font-size:1.25rem}.tabs.is-large{font-size:1.5rem}.column{display:block;flex-basis:0;flex-grow:1;flex-shrink:1;padding:.75rem}.columns.is-mobile>.column.is-narrow{flex:none}.columns.is-mobile>.column.is-full{flex:none;width:100%}.columns.is-mobile>.column.is-three-quarters{flex:none;width:75%}.columns.is-mobile>.column.is-two-thirds{flex:none;width:66.6666%}.columns.is-mobile>.column.is-half{flex:none;width:50%}.columns.is-mobile>.column.is-one-third{flex:none;width:33.3333%}.columns.is-mobile>.column.is-one-quarter{flex:none;width:25%}.columns.is-mobile>.column.is-one-fifth{flex:none;width:20%}.columns.is-mobile>.column.is-two-fifths{flex:none;width:40%}.columns.is-mobile>.column.is-three-fifths{flex:none;width:60%}.columns.is-mobile>.column.is-four-fifths{flex:none;width:80%}.columns.is-mobile>.column.is-offset-three-quarters{margin-left:75%}.columns.is-mobile>.column.is-offset-two-thirds{margin-left:66.6666%}.columns.is-mobile>.column.is-offset-half{margin-left:50%}.columns.is-mobile>.column.is-offset-one-third{margin-left:33.3333%}.columns.is-mobile>.column.is-offset-one-quarter{margin-left:25%}.columns.is-mobile>.column.is-offset-one-fifth{margin-left:20%}.columns.is-mobile>.column.is-offset-two-fifths{margin-left:40%}.columns.is-mobile>.column.is-offset-three-fifths{margin-left:60%}.columns.is-mobile>.column.is-offset-four-fifths{margin-left:80%}.columns.is-mobile>.column.is-0{flex:none;width:0%}.columns.is-mobile>.column.is-offset-0{margin-left:0%}.columns.is-mobile>.column.is-1{flex:none;width:8.3333333333%}.columns.is-mobile>.column.is-offset-1{margin-left:8.3333333333%}.columns.is-mobile>.column.is-2{flex:none;width:16.6666666667%}.columns.is-mobile>.column.is-offset-2{margin-left:16.6666666667%}.columns.is-mobile>.column.is-3{flex:none;width:25%}.columns.is-mobile>.column.is-offset-3{margin-left:25%}.columns.is-mobile>.column.is-4{flex:none;width:33.3333333333%}.columns.is-mobile>.column.is-offset-4{margin-left:33.3333333333%}.columns.is-mobile>.column.is-5{flex:none;width:41.6666666667%}.columns.is-mobile>.column.is-offset-5{margin-left:41.6666666667%}.columns.is-mobile>.column.is-6{flex:none;width:50%}.columns.is-mobile>.column.is-offset-6{margin-left:50%}.columns.is-mobile>.column.is-7{flex:none;width:58.3333333333%}.columns.is-mobile>.column.is-offset-7{margin-left:58.3333333333%}.columns.is-mobile>.column.is-8{flex:none;width:66.6666666667%}.columns.is-mobile>.column.is-offset-8{margin-left:66.6666666667%}.columns.is-mobile>.column.is-9{flex:none;width:75%}.columns.is-mobile>.column.is-offset-9{margin-left:75%}.columns.is-mobile>.column.is-10{flex:none;width:83.3333333333%}.columns.is-mobile>.column.is-offset-10{margin-left:83.3333333333%}.columns.is-mobile>.column.is-11{flex:none;width:91.6666666667%}.columns.is-mobile>.column.is-offset-11{margin-left:91.6666666667%}.columns.is-mobile>.column.is-12{flex:none;width:100%}.columns.is-mobile>.column.is-offset-12{margin-left:100%}@media screen and (max-width: 768px){.column.is-narrow-mobile{flex:none}.column.is-full-mobile{flex:none;width:100%}.column.is-three-quarters-mobile{flex:none;width:75%}.column.is-two-thirds-mobile{flex:none;width:66.6666%}.column.is-half-mobile{flex:none;width:50%}.column.is-one-third-mobile{flex:none;width:33.3333%}.column.is-one-quarter-mobile{flex:none;width:25%}.column.is-one-fifth-mobile{flex:none;width:20%}.column.is-two-fifths-mobile{flex:none;width:40%}.column.is-three-fifths-mobile{flex:none;width:60%}.column.is-four-fifths-mobile{flex:none;width:80%}.column.is-offset-three-quarters-mobile{margin-left:75%}.column.is-offset-two-thirds-mobile{margin-left:66.6666%}.column.is-offset-half-mobile{margin-left:50%}.column.is-offset-one-third-mobile{margin-left:33.3333%}.column.is-offset-one-quarter-mobile{margin-left:25%}.column.is-offset-one-fifth-mobile{margin-left:20%}.column.is-offset-two-fifths-mobile{margin-left:40%}.column.is-offset-three-fifths-mobile{margin-left:60%}.column.is-offset-four-fifths-mobile{margin-left:80%}.column.is-0-mobile{flex:none;width:0%}.column.is-offset-0-mobile{margin-left:0%}.column.is-1-mobile{flex:none;width:8.3333333333%}.column.is-offset-1-mobile{margin-left:8.3333333333%}.column.is-2-mobile{flex:none;width:16.6666666667%}.column.is-offset-2-mobile{margin-left:16.6666666667%}.column.is-3-mobile{flex:none;width:25%}.column.is-offset-3-mobile{margin-left:25%}.column.is-4-mobile{flex:none;width:33.3333333333%}.column.is-offset-4-mobile{margin-left:33.3333333333%}.column.is-5-mobile{flex:none;width:41.6666666667%}.column.is-offset-5-mobile{margin-left:41.6666666667%}.column.is-6-mobile{flex:none;width:50%}.column.is-offset-6-mobile{margin-left:50%}.column.is-7-mobile{flex:none;width:58.3333333333%}.column.is-offset-7-mobile{margin-left:58.3333333333%}.column.is-8-mobile{flex:none;width:66.6666666667%}.column.is-offset-8-mobile{margin-left:66.6666666667%}.column.is-9-mobile{flex:none;width:75%}.column.is-offset-9-mobile{margin-left:75%}.column.is-10-mobile{flex:none;width:83.3333333333%}.column.is-offset-10-mobile{margin-left:83.3333333333%}.column.is-11-mobile{flex:none;width:91.6666666667%}.column.is-offset-11-mobile{margin-left:91.6666666667%}.column.is-12-mobile{flex:none;width:100%}.column.is-offset-12-mobile{margin-left:100%}}@media screen and (min-width: 769px),print{.column.is-narrow,.column.is-narrow-tablet{flex:none}.column.is-full,.column.is-full-tablet{flex:none;width:100%}.column.is-three-quarters,.column.is-three-quarters-tablet{flex:none;width:75%}.column.is-two-thirds,.column.is-two-thirds-tablet{flex:none;width:66.6666%}.column.is-half,.column.is-half-tablet{flex:none;width:50%}.column.is-one-third,.column.is-one-third-tablet{flex:none;width:33.3333%}.column.is-one-quarter,.column.is-one-quarter-tablet{flex:none;width:25%}.column.is-one-fifth,.column.is-one-fifth-tablet{flex:none;width:20%}.column.is-two-fifths,.column.is-two-fifths-tablet{flex:none;width:40%}.column.is-three-fifths,.column.is-three-fifths-tablet{flex:none;width:60%}.column.is-four-fifths,.column.is-four-fifths-tablet{flex:none;width:80%}.column.is-offset-three-quarters,.column.is-offset-three-quarters-tablet{margin-left:75%}.column.is-offset-two-thirds,.column.is-offset-two-thirds-tablet{margin-left:66.6666%}.column.is-offset-half,.column.is-offset-half-tablet{margin-left:50%}.column.is-offset-one-third,.column.is-offset-one-third-tablet{margin-left:33.3333%}.column.is-offset-one-quarter,.column.is-offset-one-quarter-tablet{margin-left:25%}.column.is-offset-one-fifth,.column.is-offset-one-fifth-tablet{margin-left:20%}.column.is-offset-two-fifths,.column.is-offset-two-fifths-tablet{margin-left:40%}.column.is-offset-three-fifths,.column.is-offset-three-fifths-tablet{margin-left:60%}.column.is-offset-four-fifths,.column.is-offset-four-fifths-tablet{margin-left:80%}.column.is-0,.column.is-0-tablet{flex:none;width:0%}.column.is-offset-0,.column.is-offset-0-tablet{margin-left:0%}.column.is-1,.column.is-1-tablet{flex:none;width:8.3333333333%}.column.is-offset-1,.column.is-offset-1-tablet{margin-left:8.3333333333%}.column.is-2,.column.is-2-tablet{flex:none;width:16.6666666667%}.column.is-offset-2,.column.is-offset-2-tablet{margin-left:16.6666666667%}.column.is-3,.column.is-3-tablet{flex:none;width:25%}.column.is-offset-3,.column.is-offset-3-tablet{margin-left:25%}.column.is-4,.column.is-4-tablet{flex:none;width:33.3333333333%}.column.is-offset-4,.column.is-offset-4-tablet{margin-left:33.3333333333%}.column.is-5,.column.is-5-tablet{flex:none;width:41.6666666667%}.column.is-offset-5,.column.is-offset-5-tablet{margin-left:41.6666666667%}.column.is-6,.column.is-6-tablet{flex:none;width:50%}.column.is-offset-6,.column.is-offset-6-tablet{margin-left:50%}.column.is-7,.column.is-7-tablet{flex:none;width:58.3333333333%}.column.is-offset-7,.column.is-offset-7-tablet{margin-left:58.3333333333%}.column.is-8,.column.is-8-tablet{flex:none;width:66.6666666667%}.column.is-offset-8,.column.is-offset-8-tablet{margin-left:66.6666666667%}.column.is-9,.column.is-9-tablet{flex:none;width:75%}.column.is-offset-9,.column.is-offset-9-tablet{margin-left:75%}.column.is-10,.column.is-10-tablet{flex:none;width:83.3333333333%}.column.is-offset-10,.column.is-offset-10-tablet{margin-left:83.3333333333%}.column.is-11,.column.is-11-tablet{flex:none;width:91.6666666667%}.column.is-offset-11,.column.is-offset-11-tablet{margin-left:91.6666666667%}.column.is-12,.column.is-12-tablet{flex:none;width:100%}.column.is-offset-12,.column.is-offset-12-tablet{margin-left:100%}}@media screen and (max-width: 1055px){.column.is-narrow-touch{flex:none}.column.is-full-touch{flex:none;width:100%}.column.is-three-quarters-touch{flex:none;width:75%}.column.is-two-thirds-touch{flex:none;width:66.6666%}.column.is-half-touch{flex:none;width:50%}.column.is-one-third-touch{flex:none;width:33.3333%}.column.is-one-quarter-touch{flex:none;width:25%}.column.is-one-fifth-touch{flex:none;width:20%}.column.is-two-fifths-touch{flex:none;width:40%}.column.is-three-fifths-touch{flex:none;width:60%}.column.is-four-fifths-touch{flex:none;width:80%}.column.is-offset-three-quarters-touch{margin-left:75%}.column.is-offset-two-thirds-touch{margin-left:66.6666%}.column.is-offset-half-touch{margin-left:50%}.column.is-offset-one-third-touch{margin-left:33.3333%}.column.is-offset-one-quarter-touch{margin-left:25%}.column.is-offset-one-fifth-touch{margin-left:20%}.column.is-offset-two-fifths-touch{margin-left:40%}.column.is-offset-three-fifths-touch{margin-left:60%}.column.is-offset-four-fifths-touch{margin-left:80%}.column.is-0-touch{flex:none;width:0%}.column.is-offset-0-touch{margin-left:0%}.column.is-1-touch{flex:none;width:8.3333333333%}.column.is-offset-1-touch{margin-left:8.3333333333%}.column.is-2-touch{flex:none;width:16.6666666667%}.column.is-offset-2-touch{margin-left:16.6666666667%}.column.is-3-touch{flex:none;width:25%}.column.is-offset-3-touch{margin-left:25%}.column.is-4-touch{flex:none;width:33.3333333333%}.column.is-offset-4-touch{margin-left:33.3333333333%}.column.is-5-touch{flex:none;width:41.6666666667%}.column.is-offset-5-touch{margin-left:41.6666666667%}.column.is-6-touch{flex:none;width:50%}.column.is-offset-6-touch{margin-left:50%}.column.is-7-touch{flex:none;width:58.3333333333%}.column.is-offset-7-touch{margin-left:58.3333333333%}.column.is-8-touch{flex:none;width:66.6666666667%}.column.is-offset-8-touch{margin-left:66.6666666667%}.column.is-9-touch{flex:none;width:75%}.column.is-offset-9-touch{margin-left:75%}.column.is-10-touch{flex:none;width:83.3333333333%}.column.is-offset-10-touch{margin-left:83.3333333333%}.column.is-11-touch{flex:none;width:91.6666666667%}.column.is-offset-11-touch{margin-left:91.6666666667%}.column.is-12-touch{flex:none;width:100%}.column.is-offset-12-touch{margin-left:100%}}@media screen and (min-width: 1056px){.column.is-narrow-desktop{flex:none}.column.is-full-desktop{flex:none;width:100%}.column.is-three-quarters-desktop{flex:none;width:75%}.column.is-two-thirds-desktop{flex:none;width:66.6666%}.column.is-half-desktop{flex:none;width:50%}.column.is-one-third-desktop{flex:none;width:33.3333%}.column.is-one-quarter-desktop{flex:none;width:25%}.column.is-one-fifth-desktop{flex:none;width:20%}.column.is-two-fifths-desktop{flex:none;width:40%}.column.is-three-fifths-desktop{flex:none;width:60%}.column.is-four-fifths-desktop{flex:none;width:80%}.column.is-offset-three-quarters-desktop{margin-left:75%}.column.is-offset-two-thirds-desktop{margin-left:66.6666%}.column.is-offset-half-desktop{margin-left:50%}.column.is-offset-one-third-desktop{margin-left:33.3333%}.column.is-offset-one-quarter-desktop{margin-left:25%}.column.is-offset-one-fifth-desktop{margin-left:20%}.column.is-offset-two-fifths-desktop{margin-left:40%}.column.is-offset-three-fifths-desktop{margin-left:60%}.column.is-offset-four-fifths-desktop{margin-left:80%}.column.is-0-desktop{flex:none;width:0%}.column.is-offset-0-desktop{margin-left:0%}.column.is-1-desktop{flex:none;width:8.3333333333%}.column.is-offset-1-desktop{margin-left:8.3333333333%}.column.is-2-desktop{flex:none;width:16.6666666667%}.column.is-offset-2-desktop{margin-left:16.6666666667%}.column.is-3-desktop{flex:none;width:25%}.column.is-offset-3-desktop{margin-left:25%}.column.is-4-desktop{flex:none;width:33.3333333333%}.column.is-offset-4-desktop{margin-left:33.3333333333%}.column.is-5-desktop{flex:none;width:41.6666666667%}.column.is-offset-5-desktop{margin-left:41.6666666667%}.column.is-6-desktop{flex:none;width:50%}.column.is-offset-6-desktop{margin-left:50%}.column.is-7-desktop{flex:none;width:58.3333333333%}.column.is-offset-7-desktop{margin-left:58.3333333333%}.column.is-8-desktop{flex:none;width:66.6666666667%}.column.is-offset-8-desktop{margin-left:66.6666666667%}.column.is-9-desktop{flex:none;width:75%}.column.is-offset-9-desktop{margin-left:75%}.column.is-10-desktop{flex:none;width:83.3333333333%}.column.is-offset-10-desktop{margin-left:83.3333333333%}.column.is-11-desktop{flex:none;width:91.6666666667%}.column.is-offset-11-desktop{margin-left:91.6666666667%}.column.is-12-desktop{flex:none;width:100%}.column.is-offset-12-desktop{margin-left:100%}}@media screen and (min-width: 1216px){.column.is-narrow-widescreen{flex:none}.column.is-full-widescreen{flex:none;width:100%}.column.is-three-quarters-widescreen{flex:none;width:75%}.column.is-two-thirds-widescreen{flex:none;width:66.6666%}.column.is-half-widescreen{flex:none;width:50%}.column.is-one-third-widescreen{flex:none;width:33.3333%}.column.is-one-quarter-widescreen{flex:none;width:25%}.column.is-one-fifth-widescreen{flex:none;width:20%}.column.is-two-fifths-widescreen{flex:none;width:40%}.column.is-three-fifths-widescreen{flex:none;width:60%}.column.is-four-fifths-widescreen{flex:none;width:80%}.column.is-offset-three-quarters-widescreen{margin-left:75%}.column.is-offset-two-thirds-widescreen{margin-left:66.6666%}.column.is-offset-half-widescreen{margin-left:50%}.column.is-offset-one-third-widescreen{margin-left:33.3333%}.column.is-offset-one-quarter-widescreen{margin-left:25%}.column.is-offset-one-fifth-widescreen{margin-left:20%}.column.is-offset-two-fifths-widescreen{margin-left:40%}.column.is-offset-three-fifths-widescreen{margin-left:60%}.column.is-offset-four-fifths-widescreen{margin-left:80%}.column.is-0-widescreen{flex:none;width:0%}.column.is-offset-0-widescreen{margin-left:0%}.column.is-1-widescreen{flex:none;width:8.3333333333%}.column.is-offset-1-widescreen{margin-left:8.3333333333%}.column.is-2-widescreen{flex:none;width:16.6666666667%}.column.is-offset-2-widescreen{margin-left:16.6666666667%}.column.is-3-widescreen{flex:none;width:25%}.column.is-offset-3-widescreen{margin-left:25%}.column.is-4-widescreen{flex:none;width:33.3333333333%}.column.is-offset-4-widescreen{margin-left:33.3333333333%}.column.is-5-widescreen{flex:none;width:41.6666666667%}.column.is-offset-5-widescreen{margin-left:41.6666666667%}.column.is-6-widescreen{flex:none;width:50%}.column.is-offset-6-widescreen{margin-left:50%}.column.is-7-widescreen{flex:none;width:58.3333333333%}.column.is-offset-7-widescreen{margin-left:58.3333333333%}.column.is-8-widescreen{flex:none;width:66.6666666667%}.column.is-offset-8-widescreen{margin-left:66.6666666667%}.column.is-9-widescreen{flex:none;width:75%}.column.is-offset-9-widescreen{margin-left:75%}.column.is-10-widescreen{flex:none;width:83.3333333333%}.column.is-offset-10-widescreen{margin-left:83.3333333333%}.column.is-11-widescreen{flex:none;width:91.6666666667%}.column.is-offset-11-widescreen{margin-left:91.6666666667%}.column.is-12-widescreen{flex:none;width:100%}.column.is-offset-12-widescreen{margin-left:100%}}@media screen and (min-width: 1408px){.column.is-narrow-fullhd{flex:none}.column.is-full-fullhd{flex:none;width:100%}.column.is-three-quarters-fullhd{flex:none;width:75%}.column.is-two-thirds-fullhd{flex:none;width:66.6666%}.column.is-half-fullhd{flex:none;width:50%}.column.is-one-third-fullhd{flex:none;width:33.3333%}.column.is-one-quarter-fullhd{flex:none;width:25%}.column.is-one-fifth-fullhd{flex:none;width:20%}.column.is-two-fifths-fullhd{flex:none;width:40%}.column.is-three-fifths-fullhd{flex:none;width:60%}.column.is-four-fifths-fullhd{flex:none;width:80%}.column.is-offset-three-quarters-fullhd{margin-left:75%}.column.is-offset-two-thirds-fullhd{margin-left:66.6666%}.column.is-offset-half-fullhd{margin-left:50%}.column.is-offset-one-third-fullhd{margin-left:33.3333%}.column.is-offset-one-quarter-fullhd{margin-left:25%}.column.is-offset-one-fifth-fullhd{margin-left:20%}.column.is-offset-two-fifths-fullhd{margin-left:40%}.column.is-offset-three-fifths-fullhd{margin-left:60%}.column.is-offset-four-fifths-fullhd{margin-left:80%}.column.is-0-fullhd{flex:none;width:0%}.column.is-offset-0-fullhd{margin-left:0%}.column.is-1-fullhd{flex:none;width:8.3333333333%}.column.is-offset-1-fullhd{margin-left:8.3333333333%}.column.is-2-fullhd{flex:none;width:16.6666666667%}.column.is-offset-2-fullhd{margin-left:16.6666666667%}.column.is-3-fullhd{flex:none;width:25%}.column.is-offset-3-fullhd{margin-left:25%}.column.is-4-fullhd{flex:none;width:33.3333333333%}.column.is-offset-4-fullhd{margin-left:33.3333333333%}.column.is-5-fullhd{flex:none;width:41.6666666667%}.column.is-offset-5-fullhd{margin-left:41.6666666667%}.column.is-6-fullhd{flex:none;width:50%}.column.is-offset-6-fullhd{margin-left:50%}.column.is-7-fullhd{flex:none;width:58.3333333333%}.column.is-offset-7-fullhd{margin-left:58.3333333333%}.column.is-8-fullhd{flex:none;width:66.6666666667%}.column.is-offset-8-fullhd{margin-left:66.6666666667%}.column.is-9-fullhd{flex:none;width:75%}.column.is-offset-9-fullhd{margin-left:75%}.column.is-10-fullhd{flex:none;width:83.3333333333%}.column.is-offset-10-fullhd{margin-left:83.3333333333%}.column.is-11-fullhd{flex:none;width:91.6666666667%}.column.is-offset-11-fullhd{margin-left:91.6666666667%}.column.is-12-fullhd{flex:none;width:100%}.column.is-offset-12-fullhd{margin-left:100%}}.columns{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}.columns:last-child{margin-bottom:-.75rem}.columns:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}.columns.is-centered{justify-content:center}.columns.is-gapless{margin-left:0;margin-right:0;margin-top:0}.columns.is-gapless>.column{margin:0;padding:0 !important}.columns.is-gapless:not(:last-child){margin-bottom:1.5rem}.columns.is-gapless:last-child{margin-bottom:0}.columns.is-mobile{display:flex}.columns.is-multiline{flex-wrap:wrap}.columns.is-vcentered{align-items:center}@media screen and (min-width: 769px),print{.columns:not(.is-desktop){display:flex}}@media screen and (min-width: 1056px){.columns.is-desktop{display:flex}}.columns.is-variable{--columnGap: 0.75rem;margin-left:calc(-1 * var(--columnGap));margin-right:calc(-1 * var(--columnGap))}.columns.is-variable .column{padding-left:var(--columnGap);padding-right:var(--columnGap)}.columns.is-variable.is-0{--columnGap: 0rem}@media screen and (max-width: 768px){.columns.is-variable.is-0-mobile{--columnGap: 0rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-0-tablet{--columnGap: 0rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-0-tablet-only{--columnGap: 0rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-0-touch{--columnGap: 0rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-0-desktop{--columnGap: 0rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-0-desktop-only{--columnGap: 0rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-0-widescreen{--columnGap: 0rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-0-widescreen-only{--columnGap: 0rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-0-fullhd{--columnGap: 0rem}}.columns.is-variable.is-1{--columnGap: .25rem}@media screen and (max-width: 768px){.columns.is-variable.is-1-mobile{--columnGap: .25rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-1-tablet{--columnGap: .25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-1-tablet-only{--columnGap: .25rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-1-touch{--columnGap: .25rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-1-desktop{--columnGap: .25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-1-desktop-only{--columnGap: .25rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-1-widescreen{--columnGap: .25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-1-widescreen-only{--columnGap: .25rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-1-fullhd{--columnGap: .25rem}}.columns.is-variable.is-2{--columnGap: .5rem}@media screen and (max-width: 768px){.columns.is-variable.is-2-mobile{--columnGap: .5rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-2-tablet{--columnGap: .5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-2-tablet-only{--columnGap: .5rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-2-touch{--columnGap: .5rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-2-desktop{--columnGap: .5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-2-desktop-only{--columnGap: .5rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-2-widescreen{--columnGap: .5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-2-widescreen-only{--columnGap: .5rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-2-fullhd{--columnGap: .5rem}}.columns.is-variable.is-3{--columnGap: .75rem}@media screen and (max-width: 768px){.columns.is-variable.is-3-mobile{--columnGap: .75rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-3-tablet{--columnGap: .75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-3-tablet-only{--columnGap: .75rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-3-touch{--columnGap: .75rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-3-desktop{--columnGap: .75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-3-desktop-only{--columnGap: .75rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-3-widescreen{--columnGap: .75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-3-widescreen-only{--columnGap: .75rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-3-fullhd{--columnGap: .75rem}}.columns.is-variable.is-4{--columnGap: 1rem}@media screen and (max-width: 768px){.columns.is-variable.is-4-mobile{--columnGap: 1rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-4-tablet{--columnGap: 1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-4-tablet-only{--columnGap: 1rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-4-touch{--columnGap: 1rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-4-desktop{--columnGap: 1rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-4-desktop-only{--columnGap: 1rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-4-widescreen{--columnGap: 1rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-4-widescreen-only{--columnGap: 1rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-4-fullhd{--columnGap: 1rem}}.columns.is-variable.is-5{--columnGap: 1.25rem}@media screen and (max-width: 768px){.columns.is-variable.is-5-mobile{--columnGap: 1.25rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-5-tablet{--columnGap: 1.25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-5-tablet-only{--columnGap: 1.25rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-5-touch{--columnGap: 1.25rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-5-desktop{--columnGap: 1.25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-5-desktop-only{--columnGap: 1.25rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-5-widescreen{--columnGap: 1.25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-5-widescreen-only{--columnGap: 1.25rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-5-fullhd{--columnGap: 1.25rem}}.columns.is-variable.is-6{--columnGap: 1.5rem}@media screen and (max-width: 768px){.columns.is-variable.is-6-mobile{--columnGap: 1.5rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-6-tablet{--columnGap: 1.5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-6-tablet-only{--columnGap: 1.5rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-6-touch{--columnGap: 1.5rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-6-desktop{--columnGap: 1.5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-6-desktop-only{--columnGap: 1.5rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-6-widescreen{--columnGap: 1.5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-6-widescreen-only{--columnGap: 1.5rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-6-fullhd{--columnGap: 1.5rem}}.columns.is-variable.is-7{--columnGap: 1.75rem}@media screen and (max-width: 768px){.columns.is-variable.is-7-mobile{--columnGap: 1.75rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-7-tablet{--columnGap: 1.75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-7-tablet-only{--columnGap: 1.75rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-7-touch{--columnGap: 1.75rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-7-desktop{--columnGap: 1.75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-7-desktop-only{--columnGap: 1.75rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-7-widescreen{--columnGap: 1.75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-7-widescreen-only{--columnGap: 1.75rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-7-fullhd{--columnGap: 1.75rem}}.columns.is-variable.is-8{--columnGap: 2rem}@media screen and (max-width: 768px){.columns.is-variable.is-8-mobile{--columnGap: 2rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-8-tablet{--columnGap: 2rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-8-tablet-only{--columnGap: 2rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-8-touch{--columnGap: 2rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-8-desktop{--columnGap: 2rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-8-desktop-only{--columnGap: 2rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-8-widescreen{--columnGap: 2rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-8-widescreen-only{--columnGap: 2rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-8-fullhd{--columnGap: 2rem}}.tile{align-items:stretch;display:block;flex-basis:0;flex-grow:1;flex-shrink:1;min-height:min-content}.tile.is-ancestor{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}.tile.is-ancestor:last-child{margin-bottom:-.75rem}.tile.is-ancestor:not(:last-child){margin-bottom:.75rem}.tile.is-child{margin:0 !important}.tile.is-parent{padding:.75rem}.tile.is-vertical{flex-direction:column}.tile.is-vertical>.tile.is-child:not(:last-child){margin-bottom:1.5rem !important}@media screen and (min-width: 769px),print{.tile:not(.is-child){display:flex}.tile.is-1{flex:none;width:8.3333333333%}.tile.is-2{flex:none;width:16.6666666667%}.tile.is-3{flex:none;width:25%}.tile.is-4{flex:none;width:33.3333333333%}.tile.is-5{flex:none;width:41.6666666667%}.tile.is-6{flex:none;width:50%}.tile.is-7{flex:none;width:58.3333333333%}.tile.is-8{flex:none;width:66.6666666667%}.tile.is-9{flex:none;width:75%}.tile.is-10{flex:none;width:83.3333333333%}.tile.is-11{flex:none;width:91.6666666667%}.tile.is-12{flex:none;width:100%}}.hero{align-items:stretch;display:flex;flex-direction:column;justify-content:space-between}.hero .navbar{background:none}.hero .tabs ul{border-bottom:none}.hero.is-white{background-color:#fff;color:#0a0a0a}.hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-white strong{color:inherit}.hero.is-white .title{color:#0a0a0a}.hero.is-white .subtitle{color:rgba(10,10,10,0.9)}.hero.is-white .subtitle a:not(.button),.hero.is-white .subtitle strong{color:#0a0a0a}@media screen and (max-width: 1055px){.hero.is-white .navbar-menu{background-color:#fff}}.hero.is-white .navbar-item,.hero.is-white .navbar-link{color:rgba(10,10,10,0.7)}.hero.is-white a.navbar-item:hover,.hero.is-white a.navbar-item.is-active,.hero.is-white .navbar-link:hover,.hero.is-white .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}.hero.is-white .tabs a{color:#0a0a0a;opacity:0.9}.hero.is-white .tabs a:hover{opacity:1}.hero.is-white .tabs li.is-active a{opacity:1}.hero.is-white .tabs.is-boxed a,.hero.is-white .tabs.is-toggle a{color:#0a0a0a}.hero.is-white .tabs.is-boxed a:hover,.hero.is-white .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-white .tabs.is-boxed li.is-active a,.hero.is-white .tabs.is-boxed li.is-active a:hover,.hero.is-white .tabs.is-toggle li.is-active a,.hero.is-white .tabs.is-toggle li.is-active a:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.hero.is-white.is-bold{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}@media screen and (max-width: 768px){.hero.is-white.is-bold .navbar-menu{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}}.hero.is-black{background-color:#0a0a0a;color:#fff}.hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-black strong{color:inherit}.hero.is-black .title{color:#fff}.hero.is-black .subtitle{color:rgba(255,255,255,0.9)}.hero.is-black .subtitle a:not(.button),.hero.is-black .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-black .navbar-menu{background-color:#0a0a0a}}.hero.is-black .navbar-item,.hero.is-black .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-black a.navbar-item:hover,.hero.is-black a.navbar-item.is-active,.hero.is-black .navbar-link:hover,.hero.is-black .navbar-link.is-active{background-color:#000;color:#fff}.hero.is-black .tabs a{color:#fff;opacity:0.9}.hero.is-black .tabs a:hover{opacity:1}.hero.is-black .tabs li.is-active a{opacity:1}.hero.is-black .tabs.is-boxed a,.hero.is-black .tabs.is-toggle a{color:#fff}.hero.is-black .tabs.is-boxed a:hover,.hero.is-black .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-black .tabs.is-boxed li.is-active a,.hero.is-black .tabs.is-boxed li.is-active a:hover,.hero.is-black .tabs.is-toggle li.is-active a,.hero.is-black .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}.hero.is-black.is-bold{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}@media screen and (max-width: 768px){.hero.is-black.is-bold .navbar-menu{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}}.hero.is-light{background-color:#f5f5f5;color:#363636}.hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-light strong{color:inherit}.hero.is-light .title{color:#363636}.hero.is-light .subtitle{color:rgba(54,54,54,0.9)}.hero.is-light .subtitle a:not(.button),.hero.is-light .subtitle strong{color:#363636}@media screen and (max-width: 1055px){.hero.is-light .navbar-menu{background-color:#f5f5f5}}.hero.is-light .navbar-item,.hero.is-light .navbar-link{color:rgba(54,54,54,0.7)}.hero.is-light a.navbar-item:hover,.hero.is-light a.navbar-item.is-active,.hero.is-light .navbar-link:hover,.hero.is-light .navbar-link.is-active{background-color:#e8e8e8;color:#363636}.hero.is-light .tabs a{color:#363636;opacity:0.9}.hero.is-light .tabs a:hover{opacity:1}.hero.is-light .tabs li.is-active a{opacity:1}.hero.is-light .tabs.is-boxed a,.hero.is-light .tabs.is-toggle a{color:#363636}.hero.is-light .tabs.is-boxed a:hover,.hero.is-light .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-light .tabs.is-boxed li.is-active a,.hero.is-light .tabs.is-boxed li.is-active a:hover,.hero.is-light .tabs.is-toggle li.is-active a,.hero.is-light .tabs.is-toggle li.is-active a:hover{background-color:#363636;border-color:#363636;color:#f5f5f5}.hero.is-light.is-bold{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}@media screen and (max-width: 768px){.hero.is-light.is-bold .navbar-menu{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}}.hero.is-dark,.content kbd.hero{background-color:#363636;color:#f5f5f5}.hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.content kbd.hero a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-dark strong,.content kbd.hero strong{color:inherit}.hero.is-dark .title,.content kbd.hero .title{color:#f5f5f5}.hero.is-dark .subtitle,.content kbd.hero .subtitle{color:rgba(245,245,245,0.9)}.hero.is-dark .subtitle a:not(.button),.content kbd.hero .subtitle a:not(.button),.hero.is-dark .subtitle strong,.content kbd.hero .subtitle strong{color:#f5f5f5}@media screen and (max-width: 1055px){.hero.is-dark .navbar-menu,.content kbd.hero .navbar-menu{background-color:#363636}}.hero.is-dark .navbar-item,.content kbd.hero .navbar-item,.hero.is-dark .navbar-link,.content kbd.hero .navbar-link{color:rgba(245,245,245,0.7)}.hero.is-dark a.navbar-item:hover,.content kbd.hero a.navbar-item:hover,.hero.is-dark a.navbar-item.is-active,.content kbd.hero a.navbar-item.is-active,.hero.is-dark .navbar-link:hover,.content kbd.hero .navbar-link:hover,.hero.is-dark .navbar-link.is-active,.content kbd.hero .navbar-link.is-active{background-color:#292929;color:#f5f5f5}.hero.is-dark .tabs a,.content kbd.hero .tabs a{color:#f5f5f5;opacity:0.9}.hero.is-dark .tabs a:hover,.content kbd.hero .tabs a:hover{opacity:1}.hero.is-dark .tabs li.is-active a,.content kbd.hero .tabs li.is-active a{opacity:1}.hero.is-dark .tabs.is-boxed a,.content kbd.hero .tabs.is-boxed a,.hero.is-dark .tabs.is-toggle a,.content kbd.hero .tabs.is-toggle a{color:#f5f5f5}.hero.is-dark .tabs.is-boxed a:hover,.content kbd.hero .tabs.is-boxed a:hover,.hero.is-dark .tabs.is-toggle a:hover,.content kbd.hero .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-dark .tabs.is-boxed li.is-active a,.content kbd.hero .tabs.is-boxed li.is-active a,.hero.is-dark .tabs.is-boxed li.is-active a:hover,.hero.is-dark .tabs.is-toggle li.is-active a,.content kbd.hero .tabs.is-toggle li.is-active a,.hero.is-dark .tabs.is-toggle li.is-active a:hover{background-color:#f5f5f5;border-color:#f5f5f5;color:#363636}.hero.is-dark.is-bold,.content kbd.hero.is-bold{background-image:linear-gradient(141deg, #1f191a 0%, #363636 71%, #46403f 100%)}@media screen and (max-width: 768px){.hero.is-dark.is-bold .navbar-menu,.content kbd.hero.is-bold .navbar-menu{background-image:linear-gradient(141deg, #1f191a 0%, #363636 71%, #46403f 100%)}}.hero.is-primary,.docstring>section>a.hero.docs-sourcelink{background-color:#4eb5de;color:#fff}.hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.docstring>section>a.hero.docs-sourcelink a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-primary strong,.docstring>section>a.hero.docs-sourcelink strong{color:inherit}.hero.is-primary .title,.docstring>section>a.hero.docs-sourcelink .title{color:#fff}.hero.is-primary .subtitle,.docstring>section>a.hero.docs-sourcelink .subtitle{color:rgba(255,255,255,0.9)}.hero.is-primary .subtitle a:not(.button),.docstring>section>a.hero.docs-sourcelink .subtitle a:not(.button),.hero.is-primary .subtitle strong,.docstring>section>a.hero.docs-sourcelink .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-primary .navbar-menu,.docstring>section>a.hero.docs-sourcelink .navbar-menu{background-color:#4eb5de}}.hero.is-primary .navbar-item,.docstring>section>a.hero.docs-sourcelink .navbar-item,.hero.is-primary .navbar-link,.docstring>section>a.hero.docs-sourcelink .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-primary a.navbar-item:hover,.docstring>section>a.hero.docs-sourcelink a.navbar-item:hover,.hero.is-primary a.navbar-item.is-active,.docstring>section>a.hero.docs-sourcelink a.navbar-item.is-active,.hero.is-primary .navbar-link:hover,.docstring>section>a.hero.docs-sourcelink .navbar-link:hover,.hero.is-primary .navbar-link.is-active,.docstring>section>a.hero.docs-sourcelink .navbar-link.is-active{background-color:#39acda;color:#fff}.hero.is-primary .tabs a,.docstring>section>a.hero.docs-sourcelink .tabs a{color:#fff;opacity:0.9}.hero.is-primary .tabs a:hover,.docstring>section>a.hero.docs-sourcelink .tabs a:hover{opacity:1}.hero.is-primary .tabs li.is-active a,.docstring>section>a.hero.docs-sourcelink .tabs li.is-active a{opacity:1}.hero.is-primary .tabs.is-boxed a,.docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a,.hero.is-primary .tabs.is-toggle a,.docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a{color:#fff}.hero.is-primary .tabs.is-boxed a:hover,.docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a:hover,.hero.is-primary .tabs.is-toggle a:hover,.docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-primary .tabs.is-boxed li.is-active a,.docstring>section>a.hero.docs-sourcelink .tabs.is-boxed li.is-active a,.hero.is-primary .tabs.is-boxed li.is-active a:hover,.hero.is-primary .tabs.is-toggle li.is-active a,.docstring>section>a.hero.docs-sourcelink .tabs.is-toggle li.is-active a,.hero.is-primary .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#4eb5de}.hero.is-primary.is-bold,.docstring>section>a.hero.is-bold.docs-sourcelink{background-image:linear-gradient(141deg, #1bc7de 0%, #4eb5de 71%, #5fa9e7 100%)}@media screen and (max-width: 768px){.hero.is-primary.is-bold .navbar-menu,.docstring>section>a.hero.is-bold.docs-sourcelink .navbar-menu{background-image:linear-gradient(141deg, #1bc7de 0%, #4eb5de 71%, #5fa9e7 100%)}}.hero.is-link{background-color:#2e63b8;color:#fff}.hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-link strong{color:inherit}.hero.is-link .title{color:#fff}.hero.is-link .subtitle{color:rgba(255,255,255,0.9)}.hero.is-link .subtitle a:not(.button),.hero.is-link .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-link .navbar-menu{background-color:#2e63b8}}.hero.is-link .navbar-item,.hero.is-link .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-link a.navbar-item:hover,.hero.is-link a.navbar-item.is-active,.hero.is-link .navbar-link:hover,.hero.is-link .navbar-link.is-active{background-color:#2958a4;color:#fff}.hero.is-link .tabs a{color:#fff;opacity:0.9}.hero.is-link .tabs a:hover{opacity:1}.hero.is-link .tabs li.is-active a{opacity:1}.hero.is-link .tabs.is-boxed a,.hero.is-link .tabs.is-toggle a{color:#fff}.hero.is-link .tabs.is-boxed a:hover,.hero.is-link .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-link .tabs.is-boxed li.is-active a,.hero.is-link .tabs.is-boxed li.is-active a:hover,.hero.is-link .tabs.is-toggle li.is-active a,.hero.is-link .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#2e63b8}.hero.is-link.is-bold{background-image:linear-gradient(141deg, #1b6098 0%, #2e63b8 71%, #2d51d2 100%)}@media screen and (max-width: 768px){.hero.is-link.is-bold .navbar-menu{background-image:linear-gradient(141deg, #1b6098 0%, #2e63b8 71%, #2d51d2 100%)}}.hero.is-info{background-color:#209cee;color:#fff}.hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-info strong{color:inherit}.hero.is-info .title{color:#fff}.hero.is-info .subtitle{color:rgba(255,255,255,0.9)}.hero.is-info .subtitle a:not(.button),.hero.is-info .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-info .navbar-menu{background-color:#209cee}}.hero.is-info .navbar-item,.hero.is-info .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-info a.navbar-item:hover,.hero.is-info a.navbar-item.is-active,.hero.is-info .navbar-link:hover,.hero.is-info .navbar-link.is-active{background-color:#1190e3;color:#fff}.hero.is-info .tabs a{color:#fff;opacity:0.9}.hero.is-info .tabs a:hover{opacity:1}.hero.is-info .tabs li.is-active a{opacity:1}.hero.is-info .tabs.is-boxed a,.hero.is-info .tabs.is-toggle a{color:#fff}.hero.is-info .tabs.is-boxed a:hover,.hero.is-info .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-info .tabs.is-boxed li.is-active a,.hero.is-info .tabs.is-boxed li.is-active a:hover,.hero.is-info .tabs.is-toggle li.is-active a,.hero.is-info .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#209cee}.hero.is-info.is-bold{background-image:linear-gradient(141deg, #05a6d6 0%, #209cee 71%, #3287f5 100%)}@media screen and (max-width: 768px){.hero.is-info.is-bold .navbar-menu{background-image:linear-gradient(141deg, #05a6d6 0%, #209cee 71%, #3287f5 100%)}}.hero.is-success{background-color:#22c35b;color:#fff}.hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-success strong{color:inherit}.hero.is-success .title{color:#fff}.hero.is-success .subtitle{color:rgba(255,255,255,0.9)}.hero.is-success .subtitle a:not(.button),.hero.is-success .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-success .navbar-menu{background-color:#22c35b}}.hero.is-success .navbar-item,.hero.is-success .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-success a.navbar-item:hover,.hero.is-success a.navbar-item.is-active,.hero.is-success .navbar-link:hover,.hero.is-success .navbar-link.is-active{background-color:#1ead51;color:#fff}.hero.is-success .tabs a{color:#fff;opacity:0.9}.hero.is-success .tabs a:hover{opacity:1}.hero.is-success .tabs li.is-active a{opacity:1}.hero.is-success .tabs.is-boxed a,.hero.is-success .tabs.is-toggle a{color:#fff}.hero.is-success .tabs.is-boxed a:hover,.hero.is-success .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-success .tabs.is-boxed li.is-active a,.hero.is-success .tabs.is-boxed li.is-active a:hover,.hero.is-success .tabs.is-toggle li.is-active a,.hero.is-success .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#22c35b}.hero.is-success.is-bold{background-image:linear-gradient(141deg, #12a02c 0%, #22c35b 71%, #1fdf83 100%)}@media screen and (max-width: 768px){.hero.is-success.is-bold .navbar-menu{background-image:linear-gradient(141deg, #12a02c 0%, #22c35b 71%, #1fdf83 100%)}}.hero.is-warning{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-warning strong{color:inherit}.hero.is-warning .title{color:rgba(0,0,0,0.7)}.hero.is-warning .subtitle{color:rgba(0,0,0,0.9)}.hero.is-warning .subtitle a:not(.button),.hero.is-warning .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){.hero.is-warning .navbar-menu{background-color:#ffdd57}}.hero.is-warning .navbar-item,.hero.is-warning .navbar-link{color:rgba(0,0,0,0.7)}.hero.is-warning a.navbar-item:hover,.hero.is-warning a.navbar-item.is-active,.hero.is-warning .navbar-link:hover,.hero.is-warning .navbar-link.is-active{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.hero.is-warning .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}.hero.is-warning .tabs a:hover{opacity:1}.hero.is-warning .tabs li.is-active a{opacity:1}.hero.is-warning .tabs.is-boxed a,.hero.is-warning .tabs.is-toggle a{color:rgba(0,0,0,0.7)}.hero.is-warning .tabs.is-boxed a:hover,.hero.is-warning .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-warning .tabs.is-boxed li.is-active a,.hero.is-warning .tabs.is-boxed li.is-active a:hover,.hero.is-warning .tabs.is-toggle li.is-active a,.hero.is-warning .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#ffdd57}.hero.is-warning.is-bold{background-image:linear-gradient(141deg, #ffae24 0%, #ffdd57 71%, #fffa71 100%)}@media screen and (max-width: 768px){.hero.is-warning.is-bold .navbar-menu{background-image:linear-gradient(141deg, #ffae24 0%, #ffdd57 71%, #fffa71 100%)}}.hero.is-danger{background-color:#da0b00;color:#fff}.hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-danger strong{color:inherit}.hero.is-danger .title{color:#fff}.hero.is-danger .subtitle{color:rgba(255,255,255,0.9)}.hero.is-danger .subtitle a:not(.button),.hero.is-danger .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-danger .navbar-menu{background-color:#da0b00}}.hero.is-danger .navbar-item,.hero.is-danger .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-danger a.navbar-item:hover,.hero.is-danger a.navbar-item.is-active,.hero.is-danger .navbar-link:hover,.hero.is-danger .navbar-link.is-active{background-color:#c10a00;color:#fff}.hero.is-danger .tabs a{color:#fff;opacity:0.9}.hero.is-danger .tabs a:hover{opacity:1}.hero.is-danger .tabs li.is-active a{opacity:1}.hero.is-danger .tabs.is-boxed a,.hero.is-danger .tabs.is-toggle a{color:#fff}.hero.is-danger .tabs.is-boxed a:hover,.hero.is-danger .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-danger .tabs.is-boxed li.is-active a,.hero.is-danger .tabs.is-boxed li.is-active a:hover,.hero.is-danger .tabs.is-toggle li.is-active a,.hero.is-danger .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#da0b00}.hero.is-danger.is-bold{background-image:linear-gradient(141deg, #a70013 0%, #da0b00 71%, #f43500 100%)}@media screen and (max-width: 768px){.hero.is-danger.is-bold .navbar-menu{background-image:linear-gradient(141deg, #a70013 0%, #da0b00 71%, #f43500 100%)}}.hero.is-small .hero-body,#documenter .docs-sidebar form.docs-search>input.hero .hero-body{padding-bottom:1.5rem;padding-top:1.5rem}@media screen and (min-width: 769px),print{.hero.is-medium .hero-body{padding-bottom:9rem;padding-top:9rem}}@media screen and (min-width: 769px),print{.hero.is-large .hero-body{padding-bottom:18rem;padding-top:18rem}}.hero.is-halfheight .hero-body,.hero.is-fullheight .hero-body,.hero.is-fullheight-with-navbar .hero-body{align-items:center;display:flex}.hero.is-halfheight .hero-body>.container,.hero.is-fullheight .hero-body>.container,.hero.is-fullheight-with-navbar .hero-body>.container{flex-grow:1;flex-shrink:1}.hero.is-halfheight{min-height:50vh}.hero.is-fullheight{min-height:100vh}.hero-video{overflow:hidden}.hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;transform:translate3d(-50%, -50%, 0)}.hero-video.is-transparent{opacity:0.3}@media screen and (max-width: 768px){.hero-video{display:none}}.hero-buttons{margin-top:1.5rem}@media screen and (max-width: 768px){.hero-buttons .button{display:flex}.hero-buttons .button:not(:last-child){margin-bottom:0.75rem}}@media screen and (min-width: 769px),print{.hero-buttons{display:flex;justify-content:center}.hero-buttons .button:not(:last-child){margin-right:1.5rem}}.hero-head,.hero-foot{flex-grow:0;flex-shrink:0}.hero-body{flex-grow:1;flex-shrink:0;padding:3rem 1.5rem}.section{padding:3rem 1.5rem}@media screen and (min-width: 1056px){.section.is-medium{padding:9rem 1.5rem}.section.is-large{padding:18rem 1.5rem}}.footer{background-color:#fafafa;padding:3rem 1.5rem 6rem}h1 .docs-heading-anchor,h1 .docs-heading-anchor:hover,h1 .docs-heading-anchor:visited,h2 .docs-heading-anchor,h2 .docs-heading-anchor:hover,h2 .docs-heading-anchor:visited,h3 .docs-heading-anchor,h3 .docs-heading-anchor:hover,h3 .docs-heading-anchor:visited,h4 .docs-heading-anchor,h4 .docs-heading-anchor:hover,h4 .docs-heading-anchor:visited,h5 .docs-heading-anchor,h5 .docs-heading-anchor:hover,h5 .docs-heading-anchor:visited,h6 .docs-heading-anchor,h6 .docs-heading-anchor:hover,h6 .docs-heading-anchor:visited{color:#222}h1 .docs-heading-anchor-permalink,h2 .docs-heading-anchor-permalink,h3 .docs-heading-anchor-permalink,h4 .docs-heading-anchor-permalink,h5 .docs-heading-anchor-permalink,h6 .docs-heading-anchor-permalink{visibility:hidden;vertical-align:middle;margin-left:0.5em;font-size:0.7rem}h1 .docs-heading-anchor-permalink::before,h2 .docs-heading-anchor-permalink::before,h3 .docs-heading-anchor-permalink::before,h4 .docs-heading-anchor-permalink::before,h5 .docs-heading-anchor-permalink::before,h6 .docs-heading-anchor-permalink::before{font-family:"Font Awesome 5 Free";font-weight:900;content:"\f0c1"}h1:hover .docs-heading-anchor-permalink,h2:hover .docs-heading-anchor-permalink,h3:hover .docs-heading-anchor-permalink,h4:hover .docs-heading-anchor-permalink,h5:hover .docs-heading-anchor-permalink,h6:hover .docs-heading-anchor-permalink{visibility:visible}.docs-dark-only{display:none !important}pre{position:relative;overflow:hidden}pre code,pre code.hljs{padding:0 .75rem !important;overflow:auto;display:block}pre code:first-of-type,pre code.hljs:first-of-type{padding-top:0.5rem !important}pre code:last-of-type,pre code.hljs:last-of-type{padding-bottom:0.5rem !important}pre .copy-button{opacity:0.2;transition:opacity 0.2s;position:absolute;right:0em;top:0em;padding:0.5em;width:2.5em;height:2.5em;background:transparent;border:none;font-family:"Font Awesome 5 Free";color:#222;cursor:pointer;text-align:center}pre .copy-button:focus,pre .copy-button:hover{opacity:1;background:rgba(34,34,34,0.1);color:#2e63b8}pre .copy-button.success{color:#259a12;opacity:1}pre .copy-button.error{color:#cb3c33;opacity:1}pre:hover .copy-button{opacity:1}.admonition{background-color:#b5b5b5;border-style:solid;border-width:1px;border-color:#363636;border-radius:4px;font-size:1rem}.admonition strong{color:currentColor}.admonition.is-small,#documenter .docs-sidebar form.docs-search>input.admonition{font-size:.75rem}.admonition.is-medium{font-size:1.25rem}.admonition.is-large{font-size:1.5rem}.admonition.is-default{background-color:#b5b5b5;border-color:#363636}.admonition.is-default>.admonition-header{background-color:#363636;color:#fff}.admonition.is-default>.admonition-body{color:#fff}.admonition.is-info{background-color:#def0fc;border-color:#209cee}.admonition.is-info>.admonition-header{background-color:#209cee;color:#fff}.admonition.is-info>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-success{background-color:#bdf4d1;border-color:#22c35b}.admonition.is-success>.admonition-header{background-color:#22c35b;color:#fff}.admonition.is-success>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-warning{background-color:#fff3c5;border-color:#ffdd57}.admonition.is-warning>.admonition-header{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.admonition.is-warning>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-danger{background-color:#ffaba7;border-color:#da0b00}.admonition.is-danger>.admonition-header{background-color:#da0b00;color:#fff}.admonition.is-danger>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-compat{background-color:#bdeff5;border-color:#1db5c9}.admonition.is-compat>.admonition-header{background-color:#1db5c9;color:#fff}.admonition.is-compat>.admonition-body{color:rgba(0,0,0,0.7)}.admonition-header{color:#fff;background-color:#363636;align-items:center;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.5rem .75rem;position:relative}.admonition-header:before{font-family:"Font Awesome 5 Free";font-weight:900;margin-right:.75rem;content:"\f06a"}.admonition-body{color:#222;padding:0.5rem .75rem}.admonition-body pre{background-color:#f5f5f5}.admonition-body code{background-color:rgba(0,0,0,0.05)}.docstring{margin-bottom:1em;background-color:rgba(0,0,0,0);border:1px solid #dbdbdb;box-shadow:2px 2px 3px rgba(10,10,10,0.1);max-width:100%}.docstring>header{display:flex;flex-grow:1;align-items:stretch;padding:0.5rem .75rem;background-color:#f5f5f5;box-shadow:0 1px 2px rgba(10,10,10,0.1);box-shadow:none;border-bottom:1px solid #dbdbdb}.docstring>header code{background-color:transparent}.docstring>header .docstring-binding{margin-right:0.3em}.docstring>header .docstring-category{margin-left:0.3em}.docstring>section{position:relative;padding:.75rem .75rem;border-bottom:1px solid #dbdbdb}.docstring>section:last-child{border-bottom:none}.docstring>section>a.docs-sourcelink{transition:opacity 0.3s;opacity:0;position:absolute;right:.375rem;bottom:.375rem}.docstring>section>a.docs-sourcelink:focus{opacity:1 !important}.docstring:hover>section>a.docs-sourcelink{opacity:0.2}.docstring:focus-within>section>a.docs-sourcelink{opacity:0.2}.docstring>section:hover a.docs-sourcelink{opacity:1}.documenter-example-output{background-color:#fff}.outdated-warning-overlay{position:fixed;top:0;left:0;right:0;box-shadow:0 0 10px rgba(0,0,0,0.3);z-index:999;background-color:#ffaba7;color:rgba(0,0,0,0.7);border-bottom:3px solid #da0b00;padding:10px 35px;text-align:center;font-size:15px}.outdated-warning-overlay .outdated-warning-closer{position:absolute;top:calc(50% - 10px);right:18px;cursor:pointer;width:12px}.outdated-warning-overlay a{color:#2e63b8}.outdated-warning-overlay a:hover{color:#363636}.content pre{border:1px solid #dbdbdb}.content code{font-weight:inherit}.content a code{color:#2e63b8}.content h1 code,.content h2 code,.content h3 code,.content h4 code,.content h5 code,.content h6 code{color:#222}.content table{display:block;width:initial;max-width:100%;overflow-x:auto}.content blockquote>ul:first-child,.content blockquote>ol:first-child,.content .admonition-body>ul:first-child,.content .admonition-body>ol:first-child{margin-top:0}pre,code{font-variant-ligatures:no-contextual}.breadcrumb a.is-disabled{cursor:default;pointer-events:none}.breadcrumb a.is-disabled,.breadcrumb a.is-disabled:hover{color:#222}.hljs{background:initial !important}.katex .katex-mathml{top:0;right:0}.katex-display,mjx-container,.MathJax_Display{margin:0.5em 0 !important}html{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto}li.no-marker{list-style:none}#documenter .docs-main>article{overflow-wrap:break-word}#documenter .docs-main>article .math-container{overflow-x:auto;overflow-y:hidden}@media screen and (min-width: 1056px){#documenter .docs-main{max-width:52rem;margin-left:20rem;padding-right:1rem}}@media screen and (max-width: 1055px){#documenter .docs-main{width:100%}#documenter .docs-main>article{max-width:52rem;margin-left:auto;margin-right:auto;margin-bottom:1rem;padding:0 1rem}#documenter .docs-main>header,#documenter .docs-main>nav{max-width:100%;width:100%;margin:0}}#documenter .docs-main header.docs-navbar{background-color:#fff;border-bottom:1px solid #dbdbdb;z-index:2;min-height:4rem;margin-bottom:1rem;display:flex}#documenter .docs-main header.docs-navbar .breadcrumb{flex-grow:1}#documenter .docs-main header.docs-navbar .docs-right{display:flex;white-space:nowrap}#documenter .docs-main header.docs-navbar .docs-right .docs-icon,#documenter .docs-main header.docs-navbar .docs-right .docs-label,#documenter .docs-main header.docs-navbar .docs-right .docs-sidebar-button{display:inline-block}#documenter .docs-main header.docs-navbar .docs-right .docs-label{padding:0;margin-left:0.3em}#documenter .docs-main header.docs-navbar .docs-right .docs-settings-button{margin:auto 0 auto 1rem}#documenter .docs-main header.docs-navbar .docs-right .docs-sidebar-button{font-size:1.5rem;margin:auto 0 auto 1rem}#documenter .docs-main header.docs-navbar>*{margin:auto 0}@media screen and (max-width: 1055px){#documenter .docs-main header.docs-navbar{position:sticky;top:0;padding:0 1rem;transition-property:top, box-shadow;-webkit-transition-property:top, box-shadow;transition-duration:0.3s;-webkit-transition-duration:0.3s}#documenter .docs-main header.docs-navbar.headroom--not-top{box-shadow:.2rem 0rem .4rem #bbb;transition-duration:0.7s;-webkit-transition-duration:0.7s}#documenter .docs-main header.docs-navbar.headroom--unpinned.headroom--not-top.headroom--not-bottom{top:-4.5rem;transition-duration:0.7s;-webkit-transition-duration:0.7s}}#documenter .docs-main section.footnotes{border-top:1px solid #dbdbdb}#documenter .docs-main section.footnotes li .tag:first-child,#documenter .docs-main section.footnotes li .docstring>section>a.docs-sourcelink:first-child,#documenter .docs-main section.footnotes li .content kbd:first-child,.content #documenter .docs-main section.footnotes li kbd:first-child{margin-right:1em;margin-bottom:0.4em}#documenter .docs-main .docs-footer{display:flex;flex-wrap:wrap;margin-left:0;margin-right:0;border-top:1px solid #dbdbdb;padding-top:1rem;padding-bottom:1rem}@media screen and (max-width: 1055px){#documenter .docs-main .docs-footer{padding-left:1rem;padding-right:1rem}}#documenter .docs-main .docs-footer .docs-footer-nextpage,#documenter .docs-main .docs-footer .docs-footer-prevpage{flex-grow:1}#documenter .docs-main .docs-footer .docs-footer-nextpage{text-align:right}#documenter .docs-main .docs-footer .flexbox-break{flex-basis:100%;height:0}#documenter .docs-main .docs-footer .footer-message{font-size:0.8em;margin:0.5em auto 0 auto;text-align:center}#documenter .docs-sidebar{display:flex;flex-direction:column;color:#0a0a0a;background-color:#f5f5f5;border-right:1px solid #dbdbdb;padding:0;flex:0 0 18rem;z-index:5;font-size:1rem;position:fixed;left:-18rem;width:18rem;height:100%;transition:left 0.3s}#documenter .docs-sidebar.visible{left:0;box-shadow:.4rem 0rem .8rem #bbb}@media screen and (min-width: 1056px){#documenter .docs-sidebar.visible{box-shadow:none}}@media screen and (min-width: 1056px){#documenter .docs-sidebar{left:0;top:0}}#documenter .docs-sidebar .docs-logo{margin-top:1rem;padding:0 1rem}#documenter .docs-sidebar .docs-logo>img{max-height:6rem;margin:auto}#documenter .docs-sidebar .docs-package-name{flex-shrink:0;font-size:1.5rem;font-weight:700;text-align:center;white-space:nowrap;overflow:hidden;padding:0.5rem 0}#documenter .docs-sidebar .docs-package-name .docs-autofit{max-width:16.2rem}#documenter .docs-sidebar .docs-package-name a,#documenter .docs-sidebar .docs-package-name a:hover{color:#0a0a0a}#documenter .docs-sidebar .docs-version-selector{border-top:1px solid #dbdbdb;display:none;padding:0.5rem}#documenter .docs-sidebar .docs-version-selector.visible{display:flex}#documenter .docs-sidebar ul.docs-menu{flex-grow:1;user-select:none;border-top:1px solid #dbdbdb;padding-bottom:1.5rem}#documenter .docs-sidebar ul.docs-menu>li>.tocitem{font-weight:bold}#documenter .docs-sidebar ul.docs-menu>li li{font-size:.95rem;margin-left:1em;border-left:1px solid #dbdbdb}#documenter .docs-sidebar ul.docs-menu input.collapse-toggle{display:none}#documenter .docs-sidebar ul.docs-menu ul.collapsed{display:none}#documenter .docs-sidebar ul.docs-menu input:checked~ul.collapsed{display:block}#documenter .docs-sidebar ul.docs-menu label.tocitem{display:flex}#documenter .docs-sidebar ul.docs-menu label.tocitem .docs-label{flex-grow:2}#documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-size:.75rem;margin-left:1rem;margin-top:auto;margin-bottom:auto}#documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron::before{font-family:"Font Awesome 5 Free";font-weight:900;content:"\f054"}#documenter .docs-sidebar ul.docs-menu input:checked~label.tocitem .docs-chevron::before{content:"\f078"}#documenter .docs-sidebar ul.docs-menu .tocitem{display:block;padding:0.5rem 0.5rem}#documenter .docs-sidebar ul.docs-menu .tocitem,#documenter .docs-sidebar ul.docs-menu .tocitem:hover{color:#0a0a0a;background:#f5f5f5}#documenter .docs-sidebar ul.docs-menu a.tocitem:hover,#documenter .docs-sidebar ul.docs-menu label.tocitem:hover{color:#0a0a0a;background-color:#ebebeb}#documenter .docs-sidebar ul.docs-menu li.is-active{border-top:1px solid #dbdbdb;border-bottom:1px solid #dbdbdb;background-color:#fff}#documenter .docs-sidebar ul.docs-menu li.is-active .tocitem,#documenter .docs-sidebar ul.docs-menu li.is-active .tocitem:hover{background-color:#fff;color:#0a0a0a}#documenter .docs-sidebar ul.docs-menu li.is-active ul.internal .tocitem:hover{background-color:#ebebeb;color:#0a0a0a}#documenter .docs-sidebar ul.docs-menu>li.is-active:first-child{border-top:none}#documenter .docs-sidebar ul.docs-menu ul.internal{margin:0 0.5rem 0.5rem;border-top:1px solid #dbdbdb}#documenter .docs-sidebar ul.docs-menu ul.internal li{font-size:.85rem;border-left:none;margin-left:0;margin-top:0.5rem}#documenter .docs-sidebar ul.docs-menu ul.internal .tocitem{width:100%;padding:0}#documenter .docs-sidebar ul.docs-menu ul.internal .tocitem::before{content:"⚬";margin-right:0.4em}#documenter .docs-sidebar form.docs-search{margin:auto;margin-top:0.5rem;margin-bottom:0.5rem}#documenter .docs-sidebar form.docs-search>input{width:14.4rem}@media screen and (min-width: 1056px){#documenter .docs-sidebar ul.docs-menu{overflow-y:auto;-webkit-overflow-scroll:touch}#documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar{width:.3rem;background:none}#documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#e0e0e0}#documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb:hover{background:#ccc}}@media screen and (max-width: 1055px){#documenter .docs-sidebar{overflow-y:auto;-webkit-overflow-scroll:touch}#documenter .docs-sidebar::-webkit-scrollbar{width:.3rem;background:none}#documenter .docs-sidebar::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#e0e0e0}#documenter .docs-sidebar::-webkit-scrollbar-thumb:hover{background:#ccc}}#documenter .docs-main #documenter-search-info{margin-bottom:1rem}#documenter .docs-main #documenter-search-results{list-style-type:circle;list-style-position:outside}#documenter .docs-main #documenter-search-results li{margin-left:2rem}#documenter .docs-main #documenter-search-results .docs-highlight{background-color:yellow}.ansi span.sgr1{font-weight:bolder}.ansi span.sgr2{font-weight:lighter}.ansi span.sgr3{font-style:italic}.ansi span.sgr4{text-decoration:underline}.ansi span.sgr7{color:#fff;background-color:#222}.ansi span.sgr8{color:transparent}.ansi span.sgr8 span{color:transparent}.ansi span.sgr9{text-decoration:line-through}.ansi span.sgr30{color:#242424}.ansi span.sgr31{color:#a7201f}.ansi span.sgr32{color:#066f00}.ansi span.sgr33{color:#856b00}.ansi span.sgr34{color:#2149b0}.ansi span.sgr35{color:#7d4498}.ansi span.sgr36{color:#007989}.ansi span.sgr37{color:gray}.ansi span.sgr40{background-color:#242424}.ansi span.sgr41{background-color:#a7201f}.ansi span.sgr42{background-color:#066f00}.ansi span.sgr43{background-color:#856b00}.ansi span.sgr44{background-color:#2149b0}.ansi span.sgr45{background-color:#7d4498}.ansi span.sgr46{background-color:#007989}.ansi span.sgr47{background-color:gray}.ansi span.sgr90{color:#616161}.ansi span.sgr91{color:#cb3c33}.ansi span.sgr92{color:#0e8300}.ansi span.sgr93{color:#a98800}.ansi span.sgr94{color:#3c5dcd}.ansi span.sgr95{color:#9256af}.ansi span.sgr96{color:#008fa3}.ansi span.sgr97{color:#f5f5f5}.ansi span.sgr100{background-color:#616161}.ansi span.sgr101{background-color:#cb3c33}.ansi span.sgr102{background-color:#0e8300}.ansi span.sgr103{background-color:#a98800}.ansi span.sgr104{background-color:#3c5dcd}.ansi span.sgr105{background-color:#9256af}.ansi span.sgr106{background-color:#008fa3}.ansi span.sgr107{background-color:#f5f5f5}code.language-julia-repl>span.hljs-meta{color:#066f00;font-weight:bolder}/*! +.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis,.file-cta,.file-name,.select select,.textarea,.input,#documenter .docs-sidebar form.docs-search>input,.button{-moz-appearance:none;-webkit-appearance:none;align-items:center;border:1px solid transparent;border-radius:4px;box-shadow:none;display:inline-flex;font-size:1rem;height:2.5em;justify-content:flex-start;line-height:1.5;padding-bottom:calc(0.5em - 1px);padding-left:calc(0.75em - 1px);padding-right:calc(0.75em - 1px);padding-top:calc(0.5em - 1px);position:relative;vertical-align:top}.pagination-previous:focus,.pagination-next:focus,.pagination-link:focus,.pagination-ellipsis:focus,.file-cta:focus,.file-name:focus,.select select:focus,.textarea:focus,.input:focus,#documenter .docs-sidebar form.docs-search>input:focus,.button:focus,.is-focused.pagination-previous,.is-focused.pagination-next,.is-focused.pagination-link,.is-focused.pagination-ellipsis,.is-focused.file-cta,.is-focused.file-name,.select select.is-focused,.is-focused.textarea,.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-focused.button,.pagination-previous:active,.pagination-next:active,.pagination-link:active,.pagination-ellipsis:active,.file-cta:active,.file-name:active,.select select:active,.textarea:active,.input:active,#documenter .docs-sidebar form.docs-search>input:active,.button:active,.is-active.pagination-previous,.is-active.pagination-next,.is-active.pagination-link,.is-active.pagination-ellipsis,.is-active.file-cta,.is-active.file-name,.select select.is-active,.is-active.textarea,.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active,.is-active.button{outline:none}.pagination-previous[disabled],.pagination-next[disabled],.pagination-link[disabled],.pagination-ellipsis[disabled],.file-cta[disabled],.file-name[disabled],.select select[disabled],.textarea[disabled],.input[disabled],#documenter .docs-sidebar form.docs-search>input[disabled],.button[disabled],fieldset[disabled] .pagination-previous,fieldset[disabled] .pagination-next,fieldset[disabled] .pagination-link,fieldset[disabled] .pagination-ellipsis,fieldset[disabled] .file-cta,fieldset[disabled] .file-name,fieldset[disabled] .select select,.select fieldset[disabled] select,fieldset[disabled] .textarea,fieldset[disabled] .input,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input,fieldset[disabled] .button{cursor:not-allowed}.tabs,.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis,.breadcrumb,.file,.button,.is-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.navbar-link:not(.is-arrowless)::after,.select:not(.is-multiple):not(.is-loading)::after{border:3px solid rgba(0,0,0,0);border-radius:2px;border-right:0;border-top:0;content:" ";display:block;height:0.625em;margin-top:-0.4375em;pointer-events:none;position:absolute;top:50%;transform:rotate(-45deg);transform-origin:center;width:0.625em}.admonition:not(:last-child),.tabs:not(:last-child),.pagination:not(:last-child),.message:not(:last-child),.level:not(:last-child),.breadcrumb:not(:last-child),.block:not(:last-child),.title:not(:last-child),.subtitle:not(:last-child),.table-container:not(:last-child),.table:not(:last-child),.progress:not(:last-child),.notification:not(:last-child),.content:not(:last-child),.box:not(:last-child){margin-bottom:1.5rem}.modal-close,.delete{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-moz-appearance:none;-webkit-appearance:none;background-color:rgba(10,10,10,0.2);border:none;border-radius:9999px;cursor:pointer;pointer-events:auto;display:inline-block;flex-grow:0;flex-shrink:0;font-size:0;height:20px;max-height:20px;max-width:20px;min-height:20px;min-width:20px;outline:none;position:relative;vertical-align:top;width:20px}.modal-close::before,.delete::before,.modal-close::after,.delete::after{background-color:#fff;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}.modal-close::before,.delete::before{height:2px;width:50%}.modal-close::after,.delete::after{height:50%;width:2px}.modal-close:hover,.delete:hover,.modal-close:focus,.delete:focus{background-color:rgba(10,10,10,0.3)}.modal-close:active,.delete:active{background-color:rgba(10,10,10,0.4)}.is-small.modal-close,#documenter .docs-sidebar form.docs-search>input.modal-close,.is-small.delete,#documenter .docs-sidebar form.docs-search>input.delete{height:16px;max-height:16px;max-width:16px;min-height:16px;min-width:16px;width:16px}.is-medium.modal-close,.is-medium.delete{height:24px;max-height:24px;max-width:24px;min-height:24px;min-width:24px;width:24px}.is-large.modal-close,.is-large.delete{height:32px;max-height:32px;max-width:32px;min-height:32px;min-width:32px;width:32px}.control.is-loading::after,.select.is-loading::after,.loader,.button.is-loading::after{animation:spinAround 500ms infinite linear;border:2px solid #dbdbdb;border-radius:9999px;border-right-color:transparent;border-top-color:transparent;content:"";display:block;height:1em;position:relative;width:1em}.hero-video,.modal-background,.modal,.image.is-square img,#documenter .docs-sidebar .docs-logo>img.is-square img,.image.is-square .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,.image.is-1by1 img,#documenter .docs-sidebar .docs-logo>img.is-1by1 img,.image.is-1by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,.image.is-5by4 img,#documenter .docs-sidebar .docs-logo>img.is-5by4 img,.image.is-5by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,.image.is-4by3 img,#documenter .docs-sidebar .docs-logo>img.is-4by3 img,.image.is-4by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,.image.is-3by2 img,#documenter .docs-sidebar .docs-logo>img.is-3by2 img,.image.is-3by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,.image.is-5by3 img,#documenter .docs-sidebar .docs-logo>img.is-5by3 img,.image.is-5by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,.image.is-16by9 img,#documenter .docs-sidebar .docs-logo>img.is-16by9 img,.image.is-16by9 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,.image.is-2by1 img,#documenter .docs-sidebar .docs-logo>img.is-2by1 img,.image.is-2by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,.image.is-3by1 img,#documenter .docs-sidebar .docs-logo>img.is-3by1 img,.image.is-3by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,.image.is-4by5 img,#documenter .docs-sidebar .docs-logo>img.is-4by5 img,.image.is-4by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,.image.is-3by4 img,#documenter .docs-sidebar .docs-logo>img.is-3by4 img,.image.is-3by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,.image.is-2by3 img,#documenter .docs-sidebar .docs-logo>img.is-2by3 img,.image.is-2by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,.image.is-3by5 img,#documenter .docs-sidebar .docs-logo>img.is-3by5 img,.image.is-3by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,.image.is-9by16 img,#documenter .docs-sidebar .docs-logo>img.is-9by16 img,.image.is-9by16 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,.image.is-1by2 img,#documenter .docs-sidebar .docs-logo>img.is-1by2 img,.image.is-1by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,.image.is-1by3 img,#documenter .docs-sidebar .docs-logo>img.is-1by3 img,.image.is-1by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio,.is-overlay{bottom:0;left:0;position:absolute;right:0;top:0}.navbar-burger{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0}.has-text-white{color:#fff !important}a.has-text-white:hover,a.has-text-white:focus{color:#e6e6e6 !important}.has-background-white{background-color:#fff !important}.has-text-black{color:#0a0a0a !important}a.has-text-black:hover,a.has-text-black:focus{color:#000 !important}.has-background-black{background-color:#0a0a0a !important}.has-text-light{color:#f5f5f5 !important}a.has-text-light:hover,a.has-text-light:focus{color:#dbdbdb !important}.has-background-light{background-color:#f5f5f5 !important}.has-text-dark{color:#363636 !important}a.has-text-dark:hover,a.has-text-dark:focus{color:#1c1c1c !important}.has-background-dark{background-color:#363636 !important}.has-text-primary{color:#4eb5de !important}a.has-text-primary:hover,a.has-text-primary:focus{color:#27a1d2 !important}.has-background-primary{background-color:#4eb5de !important}.has-text-primary-light{color:#eef8fc !important}a.has-text-primary-light:hover,a.has-text-primary-light:focus{color:#c3e6f4 !important}.has-background-primary-light{background-color:#eef8fc !important}.has-text-primary-dark{color:#1a6d8e !important}a.has-text-primary-dark:hover,a.has-text-primary-dark:focus{color:#228eb9 !important}.has-background-primary-dark{background-color:#1a6d8e !important}.has-text-link{color:#2e63b8 !important}a.has-text-link:hover,a.has-text-link:focus{color:#244d8f !important}.has-background-link{background-color:#2e63b8 !important}.has-text-link-light{color:#eff3fb !important}a.has-text-link-light:hover,a.has-text-link-light:focus{color:#c6d6f1 !important}.has-background-link-light{background-color:#eff3fb !important}.has-text-link-dark{color:#3169c4 !important}a.has-text-link-dark:hover,a.has-text-link-dark:focus{color:#5485d4 !important}.has-background-link-dark{background-color:#3169c4 !important}.has-text-info{color:#209cee !important}a.has-text-info:hover,a.has-text-info:focus{color:#1081cb !important}.has-background-info{background-color:#209cee !important}.has-text-info-light{color:#ecf7fe !important}a.has-text-info-light:hover,a.has-text-info-light:focus{color:#bde2fa !important}.has-background-info-light{background-color:#ecf7fe !important}.has-text-info-dark{color:#0e72b4 !important}a.has-text-info-dark:hover,a.has-text-info-dark:focus{color:#1190e3 !important}.has-background-info-dark{background-color:#0e72b4 !important}.has-text-success{color:#22c35b !important}a.has-text-success:hover,a.has-text-success:focus{color:#1a9847 !important}.has-background-success{background-color:#22c35b !important}.has-text-success-light{color:#eefcf3 !important}a.has-text-success-light:hover,a.has-text-success-light:focus{color:#c2f4d4 !important}.has-background-success-light{background-color:#eefcf3 !important}.has-text-success-dark{color:#198f43 !important}a.has-text-success-dark:hover,a.has-text-success-dark:focus{color:#21bb57 !important}.has-background-success-dark{background-color:#198f43 !important}.has-text-warning{color:#ffdd57 !important}a.has-text-warning:hover,a.has-text-warning:focus{color:#ffd324 !important}.has-background-warning{background-color:#ffdd57 !important}.has-text-warning-light{color:#fffbeb !important}a.has-text-warning-light:hover,a.has-text-warning-light:focus{color:#fff1b8 !important}.has-background-warning-light{background-color:#fffbeb !important}.has-text-warning-dark{color:#947600 !important}a.has-text-warning-dark:hover,a.has-text-warning-dark:focus{color:#c79f00 !important}.has-background-warning-dark{background-color:#947600 !important}.has-text-danger{color:#da0b00 !important}a.has-text-danger:hover,a.has-text-danger:focus{color:#a70800 !important}.has-background-danger{background-color:#da0b00 !important}.has-text-danger-light{color:#ffeceb !important}a.has-text-danger-light:hover,a.has-text-danger-light:focus{color:#ffbbb8 !important}.has-background-danger-light{background-color:#ffeceb !important}.has-text-danger-dark{color:#f50c00 !important}a.has-text-danger-dark:hover,a.has-text-danger-dark:focus{color:#ff3429 !important}.has-background-danger-dark{background-color:#f50c00 !important}.has-text-black-bis{color:#121212 !important}.has-background-black-bis{background-color:#121212 !important}.has-text-black-ter{color:#242424 !important}.has-background-black-ter{background-color:#242424 !important}.has-text-grey-darker{color:#363636 !important}.has-background-grey-darker{background-color:#363636 !important}.has-text-grey-dark{color:#4a4a4a !important}.has-background-grey-dark{background-color:#4a4a4a !important}.has-text-grey{color:#6b6b6b !important}.has-background-grey{background-color:#6b6b6b !important}.has-text-grey-light{color:#b5b5b5 !important}.has-background-grey-light{background-color:#b5b5b5 !important}.has-text-grey-lighter{color:#dbdbdb !important}.has-background-grey-lighter{background-color:#dbdbdb !important}.has-text-white-ter{color:#f5f5f5 !important}.has-background-white-ter{background-color:#f5f5f5 !important}.has-text-white-bis{color:#fafafa !important}.has-background-white-bis{background-color:#fafafa !important}.is-flex-direction-row{flex-direction:row !important}.is-flex-direction-row-reverse{flex-direction:row-reverse !important}.is-flex-direction-column{flex-direction:column !important}.is-flex-direction-column-reverse{flex-direction:column-reverse !important}.is-flex-wrap-nowrap{flex-wrap:nowrap !important}.is-flex-wrap-wrap{flex-wrap:wrap !important}.is-flex-wrap-wrap-reverse{flex-wrap:wrap-reverse !important}.is-justify-content-flex-start{justify-content:flex-start !important}.is-justify-content-flex-end{justify-content:flex-end !important}.is-justify-content-center{justify-content:center !important}.is-justify-content-space-between{justify-content:space-between !important}.is-justify-content-space-around{justify-content:space-around !important}.is-justify-content-space-evenly{justify-content:space-evenly !important}.is-justify-content-start{justify-content:start !important}.is-justify-content-end{justify-content:end !important}.is-justify-content-left{justify-content:left !important}.is-justify-content-right{justify-content:right !important}.is-align-content-flex-start{align-content:flex-start !important}.is-align-content-flex-end{align-content:flex-end !important}.is-align-content-center{align-content:center !important}.is-align-content-space-between{align-content:space-between !important}.is-align-content-space-around{align-content:space-around !important}.is-align-content-space-evenly{align-content:space-evenly !important}.is-align-content-stretch{align-content:stretch !important}.is-align-content-start{align-content:start !important}.is-align-content-end{align-content:end !important}.is-align-content-baseline{align-content:baseline !important}.is-align-items-stretch{align-items:stretch !important}.is-align-items-flex-start{align-items:flex-start !important}.is-align-items-flex-end{align-items:flex-end !important}.is-align-items-center{align-items:center !important}.is-align-items-baseline{align-items:baseline !important}.is-align-items-start{align-items:start !important}.is-align-items-end{align-items:end !important}.is-align-items-self-start{align-items:self-start !important}.is-align-items-self-end{align-items:self-end !important}.is-align-self-auto{align-self:auto !important}.is-align-self-flex-start{align-self:flex-start !important}.is-align-self-flex-end{align-self:flex-end !important}.is-align-self-center{align-self:center !important}.is-align-self-baseline{align-self:baseline !important}.is-align-self-stretch{align-self:stretch !important}.is-flex-grow-0{flex-grow:0 !important}.is-flex-grow-1{flex-grow:1 !important}.is-flex-grow-2{flex-grow:2 !important}.is-flex-grow-3{flex-grow:3 !important}.is-flex-grow-4{flex-grow:4 !important}.is-flex-grow-5{flex-grow:5 !important}.is-flex-shrink-0{flex-shrink:0 !important}.is-flex-shrink-1{flex-shrink:1 !important}.is-flex-shrink-2{flex-shrink:2 !important}.is-flex-shrink-3{flex-shrink:3 !important}.is-flex-shrink-4{flex-shrink:4 !important}.is-flex-shrink-5{flex-shrink:5 !important}.is-clearfix::after{clear:both;content:" ";display:table}.is-pulled-left{float:left !important}.is-pulled-right{float:right !important}.is-radiusless{border-radius:0 !important}.is-shadowless{box-shadow:none !important}.is-clickable{cursor:pointer !important;pointer-events:all !important}.is-clipped{overflow:hidden !important}.is-relative{position:relative !important}.is-marginless{margin:0 !important}.is-paddingless{padding:0 !important}.m-0{margin:0 !important}.mt-0{margin-top:0 !important}.mr-0{margin-right:0 !important}.mb-0{margin-bottom:0 !important}.ml-0{margin-left:0 !important}.mx-0{margin-left:0 !important;margin-right:0 !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.m-1{margin:.25rem !important}.mt-1{margin-top:.25rem !important}.mr-1{margin-right:.25rem !important}.mb-1{margin-bottom:.25rem !important}.ml-1{margin-left:.25rem !important}.mx-1{margin-left:.25rem !important;margin-right:.25rem !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.m-2{margin:.5rem !important}.mt-2{margin-top:.5rem !important}.mr-2{margin-right:.5rem !important}.mb-2{margin-bottom:.5rem !important}.ml-2{margin-left:.5rem !important}.mx-2{margin-left:.5rem !important;margin-right:.5rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.m-3{margin:.75rem !important}.mt-3{margin-top:.75rem !important}.mr-3{margin-right:.75rem !important}.mb-3{margin-bottom:.75rem !important}.ml-3{margin-left:.75rem !important}.mx-3{margin-left:.75rem !important;margin-right:.75rem !important}.my-3{margin-top:.75rem !important;margin-bottom:.75rem !important}.m-4{margin:1rem !important}.mt-4{margin-top:1rem !important}.mr-4{margin-right:1rem !important}.mb-4{margin-bottom:1rem !important}.ml-4{margin-left:1rem !important}.mx-4{margin-left:1rem !important;margin-right:1rem !important}.my-4{margin-top:1rem !important;margin-bottom:1rem !important}.m-5{margin:1.5rem !important}.mt-5{margin-top:1.5rem !important}.mr-5{margin-right:1.5rem !important}.mb-5{margin-bottom:1.5rem !important}.ml-5{margin-left:1.5rem !important}.mx-5{margin-left:1.5rem !important;margin-right:1.5rem !important}.my-5{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.m-6{margin:3rem !important}.mt-6{margin-top:3rem !important}.mr-6{margin-right:3rem !important}.mb-6{margin-bottom:3rem !important}.ml-6{margin-left:3rem !important}.mx-6{margin-left:3rem !important;margin-right:3rem !important}.my-6{margin-top:3rem !important;margin-bottom:3rem !important}.m-auto{margin:auto !important}.mt-auto{margin-top:auto !important}.mr-auto{margin-right:auto !important}.mb-auto{margin-bottom:auto !important}.ml-auto{margin-left:auto !important}.mx-auto{margin-left:auto !important;margin-right:auto !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.p-0{padding:0 !important}.pt-0{padding-top:0 !important}.pr-0{padding-right:0 !important}.pb-0{padding-bottom:0 !important}.pl-0{padding-left:0 !important}.px-0{padding-left:0 !important;padding-right:0 !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.p-1{padding:.25rem !important}.pt-1{padding-top:.25rem !important}.pr-1{padding-right:.25rem !important}.pb-1{padding-bottom:.25rem !important}.pl-1{padding-left:.25rem !important}.px-1{padding-left:.25rem !important;padding-right:.25rem !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.p-2{padding:.5rem !important}.pt-2{padding-top:.5rem !important}.pr-2{padding-right:.5rem !important}.pb-2{padding-bottom:.5rem !important}.pl-2{padding-left:.5rem !important}.px-2{padding-left:.5rem !important;padding-right:.5rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.p-3{padding:.75rem !important}.pt-3{padding-top:.75rem !important}.pr-3{padding-right:.75rem !important}.pb-3{padding-bottom:.75rem !important}.pl-3{padding-left:.75rem !important}.px-3{padding-left:.75rem !important;padding-right:.75rem !important}.py-3{padding-top:.75rem !important;padding-bottom:.75rem !important}.p-4{padding:1rem !important}.pt-4{padding-top:1rem !important}.pr-4{padding-right:1rem !important}.pb-4{padding-bottom:1rem !important}.pl-4{padding-left:1rem !important}.px-4{padding-left:1rem !important;padding-right:1rem !important}.py-4{padding-top:1rem !important;padding-bottom:1rem !important}.p-5{padding:1.5rem !important}.pt-5{padding-top:1.5rem !important}.pr-5{padding-right:1.5rem !important}.pb-5{padding-bottom:1.5rem !important}.pl-5{padding-left:1.5rem !important}.px-5{padding-left:1.5rem !important;padding-right:1.5rem !important}.py-5{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.p-6{padding:3rem !important}.pt-6{padding-top:3rem !important}.pr-6{padding-right:3rem !important}.pb-6{padding-bottom:3rem !important}.pl-6{padding-left:3rem !important}.px-6{padding-left:3rem !important;padding-right:3rem !important}.py-6{padding-top:3rem !important;padding-bottom:3rem !important}.p-auto{padding:auto !important}.pt-auto{padding-top:auto !important}.pr-auto{padding-right:auto !important}.pb-auto{padding-bottom:auto !important}.pl-auto{padding-left:auto !important}.px-auto{padding-left:auto !important;padding-right:auto !important}.py-auto{padding-top:auto !important;padding-bottom:auto !important}.is-size-1{font-size:3rem !important}.is-size-2{font-size:2.5rem !important}.is-size-3{font-size:2rem !important}.is-size-4{font-size:1.5rem !important}.is-size-5{font-size:1.25rem !important}.is-size-6{font-size:1rem !important}.is-size-7,.docstring>section>a.docs-sourcelink{font-size:.75rem !important}@media screen and (max-width: 768px){.is-size-1-mobile{font-size:3rem !important}.is-size-2-mobile{font-size:2.5rem !important}.is-size-3-mobile{font-size:2rem !important}.is-size-4-mobile{font-size:1.5rem !important}.is-size-5-mobile{font-size:1.25rem !important}.is-size-6-mobile{font-size:1rem !important}.is-size-7-mobile{font-size:.75rem !important}}@media screen and (min-width: 769px),print{.is-size-1-tablet{font-size:3rem !important}.is-size-2-tablet{font-size:2.5rem !important}.is-size-3-tablet{font-size:2rem !important}.is-size-4-tablet{font-size:1.5rem !important}.is-size-5-tablet{font-size:1.25rem !important}.is-size-6-tablet{font-size:1rem !important}.is-size-7-tablet{font-size:.75rem !important}}@media screen and (max-width: 1055px){.is-size-1-touch{font-size:3rem !important}.is-size-2-touch{font-size:2.5rem !important}.is-size-3-touch{font-size:2rem !important}.is-size-4-touch{font-size:1.5rem !important}.is-size-5-touch{font-size:1.25rem !important}.is-size-6-touch{font-size:1rem !important}.is-size-7-touch{font-size:.75rem !important}}@media screen and (min-width: 1056px){.is-size-1-desktop{font-size:3rem !important}.is-size-2-desktop{font-size:2.5rem !important}.is-size-3-desktop{font-size:2rem !important}.is-size-4-desktop{font-size:1.5rem !important}.is-size-5-desktop{font-size:1.25rem !important}.is-size-6-desktop{font-size:1rem !important}.is-size-7-desktop{font-size:.75rem !important}}@media screen and (min-width: 1216px){.is-size-1-widescreen{font-size:3rem !important}.is-size-2-widescreen{font-size:2.5rem !important}.is-size-3-widescreen{font-size:2rem !important}.is-size-4-widescreen{font-size:1.5rem !important}.is-size-5-widescreen{font-size:1.25rem !important}.is-size-6-widescreen{font-size:1rem !important}.is-size-7-widescreen{font-size:.75rem !important}}@media screen and (min-width: 1408px){.is-size-1-fullhd{font-size:3rem !important}.is-size-2-fullhd{font-size:2.5rem !important}.is-size-3-fullhd{font-size:2rem !important}.is-size-4-fullhd{font-size:1.5rem !important}.is-size-5-fullhd{font-size:1.25rem !important}.is-size-6-fullhd{font-size:1rem !important}.is-size-7-fullhd{font-size:.75rem !important}}.has-text-centered{text-align:center !important}.has-text-justified{text-align:justify !important}.has-text-left{text-align:left !important}.has-text-right{text-align:right !important}@media screen and (max-width: 768px){.has-text-centered-mobile{text-align:center !important}}@media screen and (min-width: 769px),print{.has-text-centered-tablet{text-align:center !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-centered-tablet-only{text-align:center !important}}@media screen and (max-width: 1055px){.has-text-centered-touch{text-align:center !important}}@media screen and (min-width: 1056px){.has-text-centered-desktop{text-align:center !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-centered-desktop-only{text-align:center !important}}@media screen and (min-width: 1216px){.has-text-centered-widescreen{text-align:center !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-centered-widescreen-only{text-align:center !important}}@media screen and (min-width: 1408px){.has-text-centered-fullhd{text-align:center !important}}@media screen and (max-width: 768px){.has-text-justified-mobile{text-align:justify !important}}@media screen and (min-width: 769px),print{.has-text-justified-tablet{text-align:justify !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-justified-tablet-only{text-align:justify !important}}@media screen and (max-width: 1055px){.has-text-justified-touch{text-align:justify !important}}@media screen and (min-width: 1056px){.has-text-justified-desktop{text-align:justify !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-justified-desktop-only{text-align:justify !important}}@media screen and (min-width: 1216px){.has-text-justified-widescreen{text-align:justify !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-justified-widescreen-only{text-align:justify !important}}@media screen and (min-width: 1408px){.has-text-justified-fullhd{text-align:justify !important}}@media screen and (max-width: 768px){.has-text-left-mobile{text-align:left !important}}@media screen and (min-width: 769px),print{.has-text-left-tablet{text-align:left !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-left-tablet-only{text-align:left !important}}@media screen and (max-width: 1055px){.has-text-left-touch{text-align:left !important}}@media screen and (min-width: 1056px){.has-text-left-desktop{text-align:left !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-left-desktop-only{text-align:left !important}}@media screen and (min-width: 1216px){.has-text-left-widescreen{text-align:left !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-left-widescreen-only{text-align:left !important}}@media screen and (min-width: 1408px){.has-text-left-fullhd{text-align:left !important}}@media screen and (max-width: 768px){.has-text-right-mobile{text-align:right !important}}@media screen and (min-width: 769px),print{.has-text-right-tablet{text-align:right !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.has-text-right-tablet-only{text-align:right !important}}@media screen and (max-width: 1055px){.has-text-right-touch{text-align:right !important}}@media screen and (min-width: 1056px){.has-text-right-desktop{text-align:right !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.has-text-right-desktop-only{text-align:right !important}}@media screen and (min-width: 1216px){.has-text-right-widescreen{text-align:right !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.has-text-right-widescreen-only{text-align:right !important}}@media screen and (min-width: 1408px){.has-text-right-fullhd{text-align:right !important}}.is-capitalized{text-transform:capitalize !important}.is-lowercase{text-transform:lowercase !important}.is-uppercase{text-transform:uppercase !important}.is-italic{font-style:italic !important}.is-underlined{text-decoration:underline !important}.has-text-weight-light{font-weight:300 !important}.has-text-weight-normal{font-weight:400 !important}.has-text-weight-medium{font-weight:500 !important}.has-text-weight-semibold{font-weight:600 !important}.has-text-weight-bold{font-weight:700 !important}.is-family-primary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-secondary{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-sans-serif{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif !important}.is-family-monospace{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-family-code{font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace !important}.is-block{display:block !important}@media screen and (max-width: 768px){.is-block-mobile{display:block !important}}@media screen and (min-width: 769px),print{.is-block-tablet{display:block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-block-tablet-only{display:block !important}}@media screen and (max-width: 1055px){.is-block-touch{display:block !important}}@media screen and (min-width: 1056px){.is-block-desktop{display:block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-block-desktop-only{display:block !important}}@media screen and (min-width: 1216px){.is-block-widescreen{display:block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-block-widescreen-only{display:block !important}}@media screen and (min-width: 1408px){.is-block-fullhd{display:block !important}}.is-flex{display:flex !important}@media screen and (max-width: 768px){.is-flex-mobile{display:flex !important}}@media screen and (min-width: 769px),print{.is-flex-tablet{display:flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-flex-tablet-only{display:flex !important}}@media screen and (max-width: 1055px){.is-flex-touch{display:flex !important}}@media screen and (min-width: 1056px){.is-flex-desktop{display:flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-flex-desktop-only{display:flex !important}}@media screen and (min-width: 1216px){.is-flex-widescreen{display:flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-flex-widescreen-only{display:flex !important}}@media screen and (min-width: 1408px){.is-flex-fullhd{display:flex !important}}.is-inline{display:inline !important}@media screen and (max-width: 768px){.is-inline-mobile{display:inline !important}}@media screen and (min-width: 769px),print{.is-inline-tablet{display:inline !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-tablet-only{display:inline !important}}@media screen and (max-width: 1055px){.is-inline-touch{display:inline !important}}@media screen and (min-width: 1056px){.is-inline-desktop{display:inline !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-desktop-only{display:inline !important}}@media screen and (min-width: 1216px){.is-inline-widescreen{display:inline !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-widescreen-only{display:inline !important}}@media screen and (min-width: 1408px){.is-inline-fullhd{display:inline !important}}.is-inline-block{display:inline-block !important}@media screen and (max-width: 768px){.is-inline-block-mobile{display:inline-block !important}}@media screen and (min-width: 769px),print{.is-inline-block-tablet{display:inline-block !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-block-tablet-only{display:inline-block !important}}@media screen and (max-width: 1055px){.is-inline-block-touch{display:inline-block !important}}@media screen and (min-width: 1056px){.is-inline-block-desktop{display:inline-block !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-block-desktop-only{display:inline-block !important}}@media screen and (min-width: 1216px){.is-inline-block-widescreen{display:inline-block !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-block-widescreen-only{display:inline-block !important}}@media screen and (min-width: 1408px){.is-inline-block-fullhd{display:inline-block !important}}.is-inline-flex{display:inline-flex !important}@media screen and (max-width: 768px){.is-inline-flex-mobile{display:inline-flex !important}}@media screen and (min-width: 769px),print{.is-inline-flex-tablet{display:inline-flex !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-inline-flex-tablet-only{display:inline-flex !important}}@media screen and (max-width: 1055px){.is-inline-flex-touch{display:inline-flex !important}}@media screen and (min-width: 1056px){.is-inline-flex-desktop{display:inline-flex !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-inline-flex-desktop-only{display:inline-flex !important}}@media screen and (min-width: 1216px){.is-inline-flex-widescreen{display:inline-flex !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-inline-flex-widescreen-only{display:inline-flex !important}}@media screen and (min-width: 1408px){.is-inline-flex-fullhd{display:inline-flex !important}}.is-hidden{display:none !important}.is-sr-only{border:none !important;clip:rect(0, 0, 0, 0) !important;height:0.01em !important;overflow:hidden !important;padding:0 !important;position:absolute !important;white-space:nowrap !important;width:0.01em !important}@media screen and (max-width: 768px){.is-hidden-mobile{display:none !important}}@media screen and (min-width: 769px),print{.is-hidden-tablet{display:none !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-hidden-tablet-only{display:none !important}}@media screen and (max-width: 1055px){.is-hidden-touch{display:none !important}}@media screen and (min-width: 1056px){.is-hidden-desktop{display:none !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-hidden-desktop-only{display:none !important}}@media screen and (min-width: 1216px){.is-hidden-widescreen{display:none !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-hidden-widescreen-only{display:none !important}}@media screen and (min-width: 1408px){.is-hidden-fullhd{display:none !important}}.is-invisible{visibility:hidden !important}@media screen and (max-width: 768px){.is-invisible-mobile{visibility:hidden !important}}@media screen and (min-width: 769px),print{.is-invisible-tablet{visibility:hidden !important}}@media screen and (min-width: 769px) and (max-width: 1055px){.is-invisible-tablet-only{visibility:hidden !important}}@media screen and (max-width: 1055px){.is-invisible-touch{visibility:hidden !important}}@media screen and (min-width: 1056px){.is-invisible-desktop{visibility:hidden !important}}@media screen and (min-width: 1056px) and (max-width: 1215px){.is-invisible-desktop-only{visibility:hidden !important}}@media screen and (min-width: 1216px){.is-invisible-widescreen{visibility:hidden !important}}@media screen and (min-width: 1216px) and (max-width: 1407px){.is-invisible-widescreen-only{visibility:hidden !important}}@media screen and (min-width: 1408px){.is-invisible-fullhd{visibility:hidden !important}}/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:inherit}html{background-color:#fff;font-size:16px;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;min-width:300px;overflow-x:auto;overflow-y:scroll;text-rendering:optimizeLegibility;text-size-adjust:100%}article,aside,figure,footer,header,hgroup,section{display:block}body,button,input,optgroup,select,textarea{font-family:"Lato Medium",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue","Helvetica","Arial",sans-serif}code,pre{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}body{color:#222;font-size:1em;font-weight:400;line-height:1.5}a{color:#2e63b8;cursor:pointer;text-decoration:none}a strong{color:currentColor}a:hover{color:#363636}code{background-color:rgba(0,0,0,0.05);color:#000;font-size:.875em;font-weight:normal;padding:.1em}hr{background-color:#f5f5f5;border:none;display:block;height:2px;margin:1.5rem 0}img{height:auto;max-width:100%}input[type="checkbox"],input[type="radio"]{vertical-align:baseline}small{font-size:.875em}span{font-style:inherit;font-weight:inherit}strong{color:#222;font-weight:700}fieldset{border:none}pre{-webkit-overflow-scrolling:touch;background-color:#f5f5f5;color:#222;font-size:.875em;overflow-x:auto;padding:1.25rem 1.5rem;white-space:pre;word-wrap:normal}pre code{background-color:transparent;color:currentColor;font-size:1em;padding:0}table td,table th{vertical-align:top}table td:not([align]),table th:not([align]){text-align:inherit}table th{color:#222}@keyframes spinAround{from{transform:rotate(0deg)}to{transform:rotate(359deg)}}.box{background-color:#fff;border-radius:6px;box-shadow:#bbb;color:#222;display:block;padding:1.25rem}a.box:hover,a.box:focus{box-shadow:0 0.5em 1em -0.125em rgba(10,10,10,0.1),0 0 0 1px #2e63b8}a.box:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2),0 0 0 1px #2e63b8}.button{background-color:#fff;border-color:#dbdbdb;border-width:1px;color:#222;cursor:pointer;justify-content:center;padding-bottom:calc(0.5em - 1px);padding-left:1em;padding-right:1em;padding-top:calc(0.5em - 1px);text-align:center;white-space:nowrap}.button strong{color:inherit}.button .icon,.button .icon.is-small,.button #documenter .docs-sidebar form.docs-search>input.icon,#documenter .docs-sidebar .button form.docs-search>input.icon,.button .icon.is-medium,.button .icon.is-large{height:1.5em;width:1.5em}.button .icon:first-child:not(:last-child){margin-left:calc(-0.5em - 1px);margin-right:.25em}.button .icon:last-child:not(:first-child){margin-left:.25em;margin-right:calc(-0.5em - 1px)}.button .icon:first-child:last-child{margin-left:calc(-0.5em - 1px);margin-right:calc(-0.5em - 1px)}.button:hover,.button.is-hovered{border-color:#b5b5b5;color:#363636}.button:focus,.button.is-focused{border-color:#3c5dcd;color:#363636}.button:focus:not(:active),.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.button:active,.button.is-active{border-color:#4a4a4a;color:#363636}.button.is-text{background-color:transparent;border-color:transparent;color:#222;text-decoration:underline}.button.is-text:hover,.button.is-text.is-hovered,.button.is-text:focus,.button.is-text.is-focused{background-color:#f5f5f5;color:#222}.button.is-text:active,.button.is-text.is-active{background-color:#e8e8e8;color:#222}.button.is-text[disabled],fieldset[disabled] .button.is-text{background-color:transparent;border-color:transparent;box-shadow:none}.button.is-ghost{background:none;border-color:rgba(0,0,0,0);color:#2e63b8;text-decoration:none}.button.is-ghost:hover,.button.is-ghost.is-hovered{color:#2e63b8;text-decoration:underline}.button.is-white{background-color:#fff;border-color:transparent;color:#0a0a0a}.button.is-white:hover,.button.is-white.is-hovered{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}.button.is-white:focus,.button.is-white.is-focused{border-color:transparent;color:#0a0a0a}.button.is-white:focus:not(:active),.button.is-white.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}.button.is-white:active,.button.is-white.is-active{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}.button.is-white[disabled],fieldset[disabled] .button.is-white{background-color:#fff;border-color:#fff;box-shadow:none}.button.is-white.is-inverted{background-color:#0a0a0a;color:#fff}.button.is-white.is-inverted:hover,.button.is-white.is-inverted.is-hovered{background-color:#000}.button.is-white.is-inverted[disabled],fieldset[disabled] .button.is-white.is-inverted{background-color:#0a0a0a;border-color:transparent;box-shadow:none;color:#fff}.button.is-white.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-white.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-white.is-outlined:hover,.button.is-white.is-outlined.is-hovered,.button.is-white.is-outlined:focus,.button.is-white.is-outlined.is-focused{background-color:#fff;border-color:#fff;color:#0a0a0a}.button.is-white.is-outlined.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-white.is-outlined.is-loading:hover::after,.button.is-white.is-outlined.is-loading.is-hovered::after,.button.is-white.is-outlined.is-loading:focus::after,.button.is-white.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-white.is-outlined[disabled],fieldset[disabled] .button.is-white.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}.button.is-white.is-inverted.is-outlined:hover,.button.is-white.is-inverted.is-outlined.is-hovered,.button.is-white.is-inverted.is-outlined:focus,.button.is-white.is-inverted.is-outlined.is-focused{background-color:#0a0a0a;color:#fff}.button.is-white.is-inverted.is-outlined.is-loading:hover::after,.button.is-white.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-white.is-inverted.is-outlined.is-loading:focus::after,.button.is-white.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-white.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-white.is-inverted.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}.button.is-black{background-color:#0a0a0a;border-color:transparent;color:#fff}.button.is-black:hover,.button.is-black.is-hovered{background-color:#040404;border-color:transparent;color:#fff}.button.is-black:focus,.button.is-black.is-focused{border-color:transparent;color:#fff}.button.is-black:focus:not(:active),.button.is-black.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}.button.is-black:active,.button.is-black.is-active{background-color:#000;border-color:transparent;color:#fff}.button.is-black[disabled],fieldset[disabled] .button.is-black{background-color:#0a0a0a;border-color:#0a0a0a;box-shadow:none}.button.is-black.is-inverted{background-color:#fff;color:#0a0a0a}.button.is-black.is-inverted:hover,.button.is-black.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-black.is-inverted[disabled],fieldset[disabled] .button.is-black.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#0a0a0a}.button.is-black.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;color:#0a0a0a}.button.is-black.is-outlined:hover,.button.is-black.is-outlined.is-hovered,.button.is-black.is-outlined:focus,.button.is-black.is-outlined.is-focused{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.button.is-black.is-outlined.is-loading::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-black.is-outlined.is-loading:hover::after,.button.is-black.is-outlined.is-loading.is-hovered::after,.button.is-black.is-outlined.is-loading:focus::after,.button.is-black.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-black.is-outlined[disabled],fieldset[disabled] .button.is-black.is-outlined{background-color:transparent;border-color:#0a0a0a;box-shadow:none;color:#0a0a0a}.button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-black.is-inverted.is-outlined:hover,.button.is-black.is-inverted.is-outlined.is-hovered,.button.is-black.is-inverted.is-outlined:focus,.button.is-black.is-inverted.is-outlined.is-focused{background-color:#fff;color:#0a0a0a}.button.is-black.is-inverted.is-outlined.is-loading:hover::after,.button.is-black.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-black.is-inverted.is-outlined.is-loading:focus::after,.button.is-black.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #0a0a0a #0a0a0a !important}.button.is-black.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-black.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-light{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light:hover,.button.is-light.is-hovered{background-color:#eee;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light:focus,.button.is-light.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light:focus:not(:active),.button.is-light.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}.button.is-light:active,.button.is-light.is-active{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-light[disabled],fieldset[disabled] .button.is-light{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none}.button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);color:#f5f5f5}.button.is-light.is-inverted:hover,.button.is-light.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}.button.is-light.is-inverted[disabled],fieldset[disabled] .button.is-light.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#f5f5f5}.button.is-light.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;color:#f5f5f5}.button.is-light.is-outlined:hover,.button.is-light.is-outlined.is-hovered,.button.is-light.is-outlined:focus,.button.is-light.is-outlined.is-focused{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,0.7)}.button.is-light.is-outlined.is-loading::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}.button.is-light.is-outlined.is-loading:hover::after,.button.is-light.is-outlined.is-loading.is-hovered::after,.button.is-light.is-outlined.is-loading:focus::after,.button.is-light.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-light.is-outlined[disabled],fieldset[disabled] .button.is-light.is-outlined{background-color:transparent;border-color:#f5f5f5;box-shadow:none;color:#f5f5f5}.button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}.button.is-light.is-inverted.is-outlined:hover,.button.is-light.is-inverted.is-outlined.is-hovered,.button.is-light.is-inverted.is-outlined:focus,.button.is-light.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#f5f5f5}.button.is-light.is-inverted.is-outlined.is-loading:hover::after,.button.is-light.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-light.is-inverted.is-outlined.is-loading:focus::after,.button.is-light.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #f5f5f5 #f5f5f5 !important}.button.is-light.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-light.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}.button.is-dark,.content kbd.button{background-color:#363636;border-color:transparent;color:#fff}.button.is-dark:hover,.content kbd.button:hover,.button.is-dark.is-hovered,.content kbd.button.is-hovered{background-color:#2f2f2f;border-color:transparent;color:#fff}.button.is-dark:focus,.content kbd.button:focus,.button.is-dark.is-focused,.content kbd.button.is-focused{border-color:transparent;color:#fff}.button.is-dark:focus:not(:active),.content kbd.button:focus:not(:active),.button.is-dark.is-focused:not(:active),.content kbd.button.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(54,54,54,0.25)}.button.is-dark:active,.content kbd.button:active,.button.is-dark.is-active,.content kbd.button.is-active{background-color:#292929;border-color:transparent;color:#fff}.button.is-dark[disabled],.content kbd.button[disabled],fieldset[disabled] .button.is-dark,fieldset[disabled] .content kbd.button,.content fieldset[disabled] kbd.button{background-color:#363636;border-color:#363636;box-shadow:none}.button.is-dark.is-inverted,.content kbd.button.is-inverted{background-color:#fff;color:#363636}.button.is-dark.is-inverted:hover,.content kbd.button.is-inverted:hover,.button.is-dark.is-inverted.is-hovered,.content kbd.button.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-dark.is-inverted[disabled],.content kbd.button.is-inverted[disabled],fieldset[disabled] .button.is-dark.is-inverted,fieldset[disabled] .content kbd.button.is-inverted,.content fieldset[disabled] kbd.button.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#363636}.button.is-dark.is-loading::after,.content kbd.button.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-dark.is-outlined,.content kbd.button.is-outlined{background-color:transparent;border-color:#363636;color:#363636}.button.is-dark.is-outlined:hover,.content kbd.button.is-outlined:hover,.button.is-dark.is-outlined.is-hovered,.content kbd.button.is-outlined.is-hovered,.button.is-dark.is-outlined:focus,.content kbd.button.is-outlined:focus,.button.is-dark.is-outlined.is-focused,.content kbd.button.is-outlined.is-focused{background-color:#363636;border-color:#363636;color:#fff}.button.is-dark.is-outlined.is-loading::after,.content kbd.button.is-outlined.is-loading::after{border-color:transparent transparent #363636 #363636 !important}.button.is-dark.is-outlined.is-loading:hover::after,.content kbd.button.is-outlined.is-loading:hover::after,.button.is-dark.is-outlined.is-loading.is-hovered::after,.content kbd.button.is-outlined.is-loading.is-hovered::after,.button.is-dark.is-outlined.is-loading:focus::after,.content kbd.button.is-outlined.is-loading:focus::after,.button.is-dark.is-outlined.is-loading.is-focused::after,.content kbd.button.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-dark.is-outlined[disabled],.content kbd.button.is-outlined[disabled],fieldset[disabled] .button.is-dark.is-outlined,fieldset[disabled] .content kbd.button.is-outlined,.content fieldset[disabled] kbd.button.is-outlined{background-color:transparent;border-color:#363636;box-shadow:none;color:#363636}.button.is-dark.is-inverted.is-outlined,.content kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-dark.is-inverted.is-outlined:hover,.content kbd.button.is-inverted.is-outlined:hover,.button.is-dark.is-inverted.is-outlined.is-hovered,.content kbd.button.is-inverted.is-outlined.is-hovered,.button.is-dark.is-inverted.is-outlined:focus,.content kbd.button.is-inverted.is-outlined:focus,.button.is-dark.is-inverted.is-outlined.is-focused,.content kbd.button.is-inverted.is-outlined.is-focused{background-color:#fff;color:#363636}.button.is-dark.is-inverted.is-outlined.is-loading:hover::after,.content kbd.button.is-inverted.is-outlined.is-loading:hover::after,.button.is-dark.is-inverted.is-outlined.is-loading.is-hovered::after,.content kbd.button.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-dark.is-inverted.is-outlined.is-loading:focus::after,.content kbd.button.is-inverted.is-outlined.is-loading:focus::after,.button.is-dark.is-inverted.is-outlined.is-loading.is-focused::after,.content kbd.button.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #363636 #363636 !important}.button.is-dark.is-inverted.is-outlined[disabled],.content kbd.button.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-dark.is-inverted.is-outlined,fieldset[disabled] .content kbd.button.is-inverted.is-outlined,.content fieldset[disabled] kbd.button.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-primary,.docstring>section>a.button.docs-sourcelink{background-color:#4eb5de;border-color:transparent;color:#fff}.button.is-primary:hover,.docstring>section>a.button.docs-sourcelink:hover,.button.is-primary.is-hovered,.docstring>section>a.button.is-hovered.docs-sourcelink{background-color:#43b1dc;border-color:transparent;color:#fff}.button.is-primary:focus,.docstring>section>a.button.docs-sourcelink:focus,.button.is-primary.is-focused,.docstring>section>a.button.is-focused.docs-sourcelink{border-color:transparent;color:#fff}.button.is-primary:focus:not(:active),.docstring>section>a.button.docs-sourcelink:focus:not(:active),.button.is-primary.is-focused:not(:active),.docstring>section>a.button.is-focused.docs-sourcelink:not(:active){box-shadow:0 0 0 0.125em rgba(78,181,222,0.25)}.button.is-primary:active,.docstring>section>a.button.docs-sourcelink:active,.button.is-primary.is-active,.docstring>section>a.button.is-active.docs-sourcelink{background-color:#39acda;border-color:transparent;color:#fff}.button.is-primary[disabled],.docstring>section>a.button.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary,fieldset[disabled] .docstring>section>a.button.docs-sourcelink{background-color:#4eb5de;border-color:#4eb5de;box-shadow:none}.button.is-primary.is-inverted,.docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;color:#4eb5de}.button.is-primary.is-inverted:hover,.docstring>section>a.button.is-inverted.docs-sourcelink:hover,.button.is-primary.is-inverted.is-hovered,.docstring>section>a.button.is-inverted.is-hovered.docs-sourcelink{background-color:#f2f2f2}.button.is-primary.is-inverted[disabled],.docstring>section>a.button.is-inverted.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary.is-inverted,fieldset[disabled] .docstring>section>a.button.is-inverted.docs-sourcelink{background-color:#fff;border-color:transparent;box-shadow:none;color:#4eb5de}.button.is-primary.is-loading::after,.docstring>section>a.button.is-loading.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}.button.is-primary.is-outlined,.docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#4eb5de;color:#4eb5de}.button.is-primary.is-outlined:hover,.docstring>section>a.button.is-outlined.docs-sourcelink:hover,.button.is-primary.is-outlined.is-hovered,.docstring>section>a.button.is-outlined.is-hovered.docs-sourcelink,.button.is-primary.is-outlined:focus,.docstring>section>a.button.is-outlined.docs-sourcelink:focus,.button.is-primary.is-outlined.is-focused,.docstring>section>a.button.is-outlined.is-focused.docs-sourcelink{background-color:#4eb5de;border-color:#4eb5de;color:#fff}.button.is-primary.is-outlined.is-loading::after,.docstring>section>a.button.is-outlined.is-loading.docs-sourcelink::after{border-color:transparent transparent #4eb5de #4eb5de !important}.button.is-primary.is-outlined.is-loading:hover::after,.docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:hover::after,.button.is-primary.is-outlined.is-loading.is-hovered::after,.docstring>section>a.button.is-outlined.is-loading.is-hovered.docs-sourcelink::after,.button.is-primary.is-outlined.is-loading:focus::after,.docstring>section>a.button.is-outlined.is-loading.docs-sourcelink:focus::after,.button.is-primary.is-outlined.is-loading.is-focused::after,.docstring>section>a.button.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #fff #fff !important}.button.is-primary.is-outlined[disabled],.docstring>section>a.button.is-outlined.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary.is-outlined,fieldset[disabled] .docstring>section>a.button.is-outlined.docs-sourcelink{background-color:transparent;border-color:#4eb5de;box-shadow:none;color:#4eb5de}.button.is-primary.is-inverted.is-outlined,.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;color:#fff}.button.is-primary.is-inverted.is-outlined:hover,.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:hover,.button.is-primary.is-inverted.is-outlined.is-hovered,.docstring>section>a.button.is-inverted.is-outlined.is-hovered.docs-sourcelink,.button.is-primary.is-inverted.is-outlined:focus,.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink:focus,.button.is-primary.is-inverted.is-outlined.is-focused,.docstring>section>a.button.is-inverted.is-outlined.is-focused.docs-sourcelink{background-color:#fff;color:#4eb5de}.button.is-primary.is-inverted.is-outlined.is-loading:hover::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:hover::after,.button.is-primary.is-inverted.is-outlined.is-loading.is-hovered::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.is-hovered.docs-sourcelink::after,.button.is-primary.is-inverted.is-outlined.is-loading:focus::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.docs-sourcelink:focus::after,.button.is-primary.is-inverted.is-outlined.is-loading.is-focused::after,.docstring>section>a.button.is-inverted.is-outlined.is-loading.is-focused.docs-sourcelink::after{border-color:transparent transparent #4eb5de #4eb5de !important}.button.is-primary.is-inverted.is-outlined[disabled],.docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink[disabled],fieldset[disabled] .button.is-primary.is-inverted.is-outlined,fieldset[disabled] .docstring>section>a.button.is-inverted.is-outlined.docs-sourcelink{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-primary.is-light,.docstring>section>a.button.is-light.docs-sourcelink{background-color:#eef8fc;color:#1a6d8e}.button.is-primary.is-light:hover,.docstring>section>a.button.is-light.docs-sourcelink:hover,.button.is-primary.is-light.is-hovered,.docstring>section>a.button.is-light.is-hovered.docs-sourcelink{background-color:#e3f3fa;border-color:transparent;color:#1a6d8e}.button.is-primary.is-light:active,.docstring>section>a.button.is-light.docs-sourcelink:active,.button.is-primary.is-light.is-active,.docstring>section>a.button.is-light.is-active.docs-sourcelink{background-color:#d8eff8;border-color:transparent;color:#1a6d8e}.button.is-link{background-color:#2e63b8;border-color:transparent;color:#fff}.button.is-link:hover,.button.is-link.is-hovered{background-color:#2b5eae;border-color:transparent;color:#fff}.button.is-link:focus,.button.is-link.is-focused{border-color:transparent;color:#fff}.button.is-link:focus:not(:active),.button.is-link.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.button.is-link:active,.button.is-link.is-active{background-color:#2958a4;border-color:transparent;color:#fff}.button.is-link[disabled],fieldset[disabled] .button.is-link{background-color:#2e63b8;border-color:#2e63b8;box-shadow:none}.button.is-link.is-inverted{background-color:#fff;color:#2e63b8}.button.is-link.is-inverted:hover,.button.is-link.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-link.is-inverted[disabled],fieldset[disabled] .button.is-link.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#2e63b8}.button.is-link.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-link.is-outlined{background-color:transparent;border-color:#2e63b8;color:#2e63b8}.button.is-link.is-outlined:hover,.button.is-link.is-outlined.is-hovered,.button.is-link.is-outlined:focus,.button.is-link.is-outlined.is-focused{background-color:#2e63b8;border-color:#2e63b8;color:#fff}.button.is-link.is-outlined.is-loading::after{border-color:transparent transparent #2e63b8 #2e63b8 !important}.button.is-link.is-outlined.is-loading:hover::after,.button.is-link.is-outlined.is-loading.is-hovered::after,.button.is-link.is-outlined.is-loading:focus::after,.button.is-link.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-link.is-outlined[disabled],fieldset[disabled] .button.is-link.is-outlined{background-color:transparent;border-color:#2e63b8;box-shadow:none;color:#2e63b8}.button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-link.is-inverted.is-outlined:hover,.button.is-link.is-inverted.is-outlined.is-hovered,.button.is-link.is-inverted.is-outlined:focus,.button.is-link.is-inverted.is-outlined.is-focused{background-color:#fff;color:#2e63b8}.button.is-link.is-inverted.is-outlined.is-loading:hover::after,.button.is-link.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-link.is-inverted.is-outlined.is-loading:focus::after,.button.is-link.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #2e63b8 #2e63b8 !important}.button.is-link.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-link.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-link.is-light{background-color:#eff3fb;color:#3169c4}.button.is-link.is-light:hover,.button.is-link.is-light.is-hovered{background-color:#e4ecf8;border-color:transparent;color:#3169c4}.button.is-link.is-light:active,.button.is-link.is-light.is-active{background-color:#dae5f6;border-color:transparent;color:#3169c4}.button.is-info{background-color:#209cee;border-color:transparent;color:#fff}.button.is-info:hover,.button.is-info.is-hovered{background-color:#1497ed;border-color:transparent;color:#fff}.button.is-info:focus,.button.is-info.is-focused{border-color:transparent;color:#fff}.button.is-info:focus:not(:active),.button.is-info.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(32,156,238,0.25)}.button.is-info:active,.button.is-info.is-active{background-color:#1190e3;border-color:transparent;color:#fff}.button.is-info[disabled],fieldset[disabled] .button.is-info{background-color:#209cee;border-color:#209cee;box-shadow:none}.button.is-info.is-inverted{background-color:#fff;color:#209cee}.button.is-info.is-inverted:hover,.button.is-info.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-info.is-inverted[disabled],fieldset[disabled] .button.is-info.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#209cee}.button.is-info.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-info.is-outlined{background-color:transparent;border-color:#209cee;color:#209cee}.button.is-info.is-outlined:hover,.button.is-info.is-outlined.is-hovered,.button.is-info.is-outlined:focus,.button.is-info.is-outlined.is-focused{background-color:#209cee;border-color:#209cee;color:#fff}.button.is-info.is-outlined.is-loading::after{border-color:transparent transparent #209cee #209cee !important}.button.is-info.is-outlined.is-loading:hover::after,.button.is-info.is-outlined.is-loading.is-hovered::after,.button.is-info.is-outlined.is-loading:focus::after,.button.is-info.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-info.is-outlined[disabled],fieldset[disabled] .button.is-info.is-outlined{background-color:transparent;border-color:#209cee;box-shadow:none;color:#209cee}.button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-info.is-inverted.is-outlined:hover,.button.is-info.is-inverted.is-outlined.is-hovered,.button.is-info.is-inverted.is-outlined:focus,.button.is-info.is-inverted.is-outlined.is-focused{background-color:#fff;color:#209cee}.button.is-info.is-inverted.is-outlined.is-loading:hover::after,.button.is-info.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-info.is-inverted.is-outlined.is-loading:focus::after,.button.is-info.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #209cee #209cee !important}.button.is-info.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-info.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-info.is-light{background-color:#ecf7fe;color:#0e72b4}.button.is-info.is-light:hover,.button.is-info.is-light.is-hovered{background-color:#e0f1fd;border-color:transparent;color:#0e72b4}.button.is-info.is-light:active,.button.is-info.is-light.is-active{background-color:#d4ecfc;border-color:transparent;color:#0e72b4}.button.is-success{background-color:#22c35b;border-color:transparent;color:#fff}.button.is-success:hover,.button.is-success.is-hovered{background-color:#20b856;border-color:transparent;color:#fff}.button.is-success:focus,.button.is-success.is-focused{border-color:transparent;color:#fff}.button.is-success:focus:not(:active),.button.is-success.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(34,195,91,0.25)}.button.is-success:active,.button.is-success.is-active{background-color:#1ead51;border-color:transparent;color:#fff}.button.is-success[disabled],fieldset[disabled] .button.is-success{background-color:#22c35b;border-color:#22c35b;box-shadow:none}.button.is-success.is-inverted{background-color:#fff;color:#22c35b}.button.is-success.is-inverted:hover,.button.is-success.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-success.is-inverted[disabled],fieldset[disabled] .button.is-success.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#22c35b}.button.is-success.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-success.is-outlined{background-color:transparent;border-color:#22c35b;color:#22c35b}.button.is-success.is-outlined:hover,.button.is-success.is-outlined.is-hovered,.button.is-success.is-outlined:focus,.button.is-success.is-outlined.is-focused{background-color:#22c35b;border-color:#22c35b;color:#fff}.button.is-success.is-outlined.is-loading::after{border-color:transparent transparent #22c35b #22c35b !important}.button.is-success.is-outlined.is-loading:hover::after,.button.is-success.is-outlined.is-loading.is-hovered::after,.button.is-success.is-outlined.is-loading:focus::after,.button.is-success.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-success.is-outlined[disabled],fieldset[disabled] .button.is-success.is-outlined{background-color:transparent;border-color:#22c35b;box-shadow:none;color:#22c35b}.button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-success.is-inverted.is-outlined:hover,.button.is-success.is-inverted.is-outlined.is-hovered,.button.is-success.is-inverted.is-outlined:focus,.button.is-success.is-inverted.is-outlined.is-focused{background-color:#fff;color:#22c35b}.button.is-success.is-inverted.is-outlined.is-loading:hover::after,.button.is-success.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-success.is-inverted.is-outlined.is-loading:focus::after,.button.is-success.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #22c35b #22c35b !important}.button.is-success.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-success.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-success.is-light{background-color:#eefcf3;color:#198f43}.button.is-success.is-light:hover,.button.is-success.is-light.is-hovered{background-color:#e3faeb;border-color:transparent;color:#198f43}.button.is-success.is-light:active,.button.is-success.is-light.is-active{background-color:#d8f8e3;border-color:transparent;color:#198f43}.button.is-warning{background-color:#ffdd57;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning:hover,.button.is-warning.is-hovered{background-color:#ffda4a;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning:focus,.button.is-warning.is-focused{border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning:focus:not(:active),.button.is-warning.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(255,221,87,0.25)}.button.is-warning:active,.button.is-warning.is-active{background-color:#ffd83e;border-color:transparent;color:rgba(0,0,0,0.7)}.button.is-warning[disabled],fieldset[disabled] .button.is-warning{background-color:#ffdd57;border-color:#ffdd57;box-shadow:none}.button.is-warning.is-inverted{background-color:rgba(0,0,0,0.7);color:#ffdd57}.button.is-warning.is-inverted:hover,.button.is-warning.is-inverted.is-hovered{background-color:rgba(0,0,0,0.7)}.button.is-warning.is-inverted[disabled],fieldset[disabled] .button.is-warning.is-inverted{background-color:rgba(0,0,0,0.7);border-color:transparent;box-shadow:none;color:#ffdd57}.button.is-warning.is-loading::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-warning.is-outlined{background-color:transparent;border-color:#ffdd57;color:#ffdd57}.button.is-warning.is-outlined:hover,.button.is-warning.is-outlined.is-hovered,.button.is-warning.is-outlined:focus,.button.is-warning.is-outlined.is-focused{background-color:#ffdd57;border-color:#ffdd57;color:rgba(0,0,0,0.7)}.button.is-warning.is-outlined.is-loading::after{border-color:transparent transparent #ffdd57 #ffdd57 !important}.button.is-warning.is-outlined.is-loading:hover::after,.button.is-warning.is-outlined.is-loading.is-hovered::after,.button.is-warning.is-outlined.is-loading:focus::after,.button.is-warning.is-outlined.is-loading.is-focused::after{border-color:transparent transparent rgba(0,0,0,0.7) rgba(0,0,0,0.7) !important}.button.is-warning.is-outlined[disabled],fieldset[disabled] .button.is-warning.is-outlined{background-color:transparent;border-color:#ffdd57;box-shadow:none;color:#ffdd57}.button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);color:rgba(0,0,0,0.7)}.button.is-warning.is-inverted.is-outlined:hover,.button.is-warning.is-inverted.is-outlined.is-hovered,.button.is-warning.is-inverted.is-outlined:focus,.button.is-warning.is-inverted.is-outlined.is-focused{background-color:rgba(0,0,0,0.7);color:#ffdd57}.button.is-warning.is-inverted.is-outlined.is-loading:hover::after,.button.is-warning.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-warning.is-inverted.is-outlined.is-loading:focus::after,.button.is-warning.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #ffdd57 #ffdd57 !important}.button.is-warning.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-warning.is-inverted.is-outlined{background-color:transparent;border-color:rgba(0,0,0,0.7);box-shadow:none;color:rgba(0,0,0,0.7)}.button.is-warning.is-light{background-color:#fffbeb;color:#947600}.button.is-warning.is-light:hover,.button.is-warning.is-light.is-hovered{background-color:#fff8de;border-color:transparent;color:#947600}.button.is-warning.is-light:active,.button.is-warning.is-light.is-active{background-color:#fff6d1;border-color:transparent;color:#947600}.button.is-danger{background-color:#da0b00;border-color:transparent;color:#fff}.button.is-danger:hover,.button.is-danger.is-hovered{background-color:#cd0a00;border-color:transparent;color:#fff}.button.is-danger:focus,.button.is-danger.is-focused{border-color:transparent;color:#fff}.button.is-danger:focus:not(:active),.button.is-danger.is-focused:not(:active){box-shadow:0 0 0 0.125em rgba(218,11,0,0.25)}.button.is-danger:active,.button.is-danger.is-active{background-color:#c10a00;border-color:transparent;color:#fff}.button.is-danger[disabled],fieldset[disabled] .button.is-danger{background-color:#da0b00;border-color:#da0b00;box-shadow:none}.button.is-danger.is-inverted{background-color:#fff;color:#da0b00}.button.is-danger.is-inverted:hover,.button.is-danger.is-inverted.is-hovered{background-color:#f2f2f2}.button.is-danger.is-inverted[disabled],fieldset[disabled] .button.is-danger.is-inverted{background-color:#fff;border-color:transparent;box-shadow:none;color:#da0b00}.button.is-danger.is-loading::after{border-color:transparent transparent #fff #fff !important}.button.is-danger.is-outlined{background-color:transparent;border-color:#da0b00;color:#da0b00}.button.is-danger.is-outlined:hover,.button.is-danger.is-outlined.is-hovered,.button.is-danger.is-outlined:focus,.button.is-danger.is-outlined.is-focused{background-color:#da0b00;border-color:#da0b00;color:#fff}.button.is-danger.is-outlined.is-loading::after{border-color:transparent transparent #da0b00 #da0b00 !important}.button.is-danger.is-outlined.is-loading:hover::after,.button.is-danger.is-outlined.is-loading.is-hovered::after,.button.is-danger.is-outlined.is-loading:focus::after,.button.is-danger.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #fff #fff !important}.button.is-danger.is-outlined[disabled],fieldset[disabled] .button.is-danger.is-outlined{background-color:transparent;border-color:#da0b00;box-shadow:none;color:#da0b00}.button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;color:#fff}.button.is-danger.is-inverted.is-outlined:hover,.button.is-danger.is-inverted.is-outlined.is-hovered,.button.is-danger.is-inverted.is-outlined:focus,.button.is-danger.is-inverted.is-outlined.is-focused{background-color:#fff;color:#da0b00}.button.is-danger.is-inverted.is-outlined.is-loading:hover::after,.button.is-danger.is-inverted.is-outlined.is-loading.is-hovered::after,.button.is-danger.is-inverted.is-outlined.is-loading:focus::after,.button.is-danger.is-inverted.is-outlined.is-loading.is-focused::after{border-color:transparent transparent #da0b00 #da0b00 !important}.button.is-danger.is-inverted.is-outlined[disabled],fieldset[disabled] .button.is-danger.is-inverted.is-outlined{background-color:transparent;border-color:#fff;box-shadow:none;color:#fff}.button.is-danger.is-light{background-color:#ffeceb;color:#f50c00}.button.is-danger.is-light:hover,.button.is-danger.is-light.is-hovered{background-color:#ffe0de;border-color:transparent;color:#f50c00}.button.is-danger.is-light:active,.button.is-danger.is-light.is-active{background-color:#ffd3d1;border-color:transparent;color:#f50c00}.button.is-small,#documenter .docs-sidebar form.docs-search>input.button{font-size:.75rem}.button.is-small:not(.is-rounded),#documenter .docs-sidebar form.docs-search>input.button:not(.is-rounded){border-radius:2px}.button.is-normal{font-size:1rem}.button.is-medium{font-size:1.25rem}.button.is-large{font-size:1.5rem}.button[disabled],fieldset[disabled] .button{background-color:#fff;border-color:#dbdbdb;box-shadow:none;opacity:.5}.button.is-fullwidth{display:flex;width:100%}.button.is-loading{color:transparent !important;pointer-events:none}.button.is-loading::after{position:absolute;left:calc(50% - (1em * 0.5));top:calc(50% - (1em * 0.5));position:absolute !important}.button.is-static{background-color:#f5f5f5;border-color:#dbdbdb;color:#6b6b6b;box-shadow:none;pointer-events:none}.button.is-rounded,#documenter .docs-sidebar form.docs-search>input.button{border-radius:9999px;padding-left:calc(1em + 0.25em);padding-right:calc(1em + 0.25em)}.buttons{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}.buttons .button{margin-bottom:0.5rem}.buttons .button:not(:last-child):not(.is-fullwidth){margin-right:.5rem}.buttons:last-child{margin-bottom:-0.5rem}.buttons:not(:last-child){margin-bottom:1rem}.buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large){font-size:.75rem}.buttons.are-small .button:not(.is-normal):not(.is-medium):not(.is-large):not(.is-rounded){border-radius:2px}.buttons.are-medium .button:not(.is-small):not(.is-normal):not(.is-large){font-size:1.25rem}.buttons.are-large .button:not(.is-small):not(.is-normal):not(.is-medium){font-size:1.5rem}.buttons.has-addons .button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.buttons.has-addons .button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.buttons.has-addons .button:last-child{margin-right:0}.buttons.has-addons .button:hover,.buttons.has-addons .button.is-hovered{z-index:2}.buttons.has-addons .button:focus,.buttons.has-addons .button.is-focused,.buttons.has-addons .button:active,.buttons.has-addons .button.is-active,.buttons.has-addons .button.is-selected{z-index:3}.buttons.has-addons .button:focus:hover,.buttons.has-addons .button.is-focused:hover,.buttons.has-addons .button:active:hover,.buttons.has-addons .button.is-active:hover,.buttons.has-addons .button.is-selected:hover{z-index:4}.buttons.has-addons .button.is-expanded{flex-grow:1;flex-shrink:1}.buttons.is-centered{justify-content:center}.buttons.is-centered:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}.buttons.is-right{justify-content:flex-end}.buttons.is-right:not(.has-addons) .button:not(.is-fullwidth){margin-left:0.25rem;margin-right:0.25rem}@media screen and (max-width: 768px){.button.is-responsive.is-small,#documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.5625rem}.button.is-responsive,.button.is-responsive.is-normal{font-size:.65625rem}.button.is-responsive.is-medium{font-size:.75rem}.button.is-responsive.is-large{font-size:1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.button.is-responsive.is-small,#documenter .docs-sidebar form.docs-search>input.is-responsive{font-size:.65625rem}.button.is-responsive,.button.is-responsive.is-normal{font-size:.75rem}.button.is-responsive.is-medium{font-size:1rem}.button.is-responsive.is-large{font-size:1.25rem}}.container{flex-grow:1;margin:0 auto;position:relative;width:auto}.container.is-fluid{max-width:none !important;padding-left:32px;padding-right:32px;width:100%}@media screen and (min-width: 1056px){.container{max-width:992px}}@media screen and (max-width: 1215px){.container.is-widescreen:not(.is-max-desktop){max-width:1152px}}@media screen and (max-width: 1407px){.container.is-fullhd:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}@media screen and (min-width: 1216px){.container:not(.is-max-desktop){max-width:1152px}}@media screen and (min-width: 1408px){.container:not(.is-max-desktop):not(.is-max-widescreen){max-width:1344px}}.content li+li{margin-top:0.25em}.content p:not(:last-child),.content dl:not(:last-child),.content ol:not(:last-child),.content ul:not(:last-child),.content blockquote:not(:last-child),.content pre:not(:last-child),.content table:not(:last-child){margin-bottom:1em}.content h1,.content h2,.content h3,.content h4,.content h5,.content h6{color:#222;font-weight:600;line-height:1.125}.content h1{font-size:2em;margin-bottom:0.5em}.content h1:not(:first-child){margin-top:1em}.content h2{font-size:1.75em;margin-bottom:0.5714em}.content h2:not(:first-child){margin-top:1.1428em}.content h3{font-size:1.5em;margin-bottom:0.6666em}.content h3:not(:first-child){margin-top:1.3333em}.content h4{font-size:1.25em;margin-bottom:0.8em}.content h5{font-size:1.125em;margin-bottom:0.8888em}.content h6{font-size:1em;margin-bottom:1em}.content blockquote{background-color:#f5f5f5;border-left:5px solid #dbdbdb;padding:1.25em 1.5em}.content ol{list-style-position:outside;margin-left:2em;margin-top:1em}.content ol:not([type]){list-style-type:decimal}.content ol.is-lower-alpha:not([type]){list-style-type:lower-alpha}.content ol.is-lower-roman:not([type]){list-style-type:lower-roman}.content ol.is-upper-alpha:not([type]){list-style-type:upper-alpha}.content ol.is-upper-roman:not([type]){list-style-type:upper-roman}.content ul{list-style:disc outside;margin-left:2em;margin-top:1em}.content ul ul{list-style-type:circle;margin-top:0.5em}.content ul ul ul{list-style-type:square}.content dd{margin-left:2em}.content figure{margin-left:2em;margin-right:2em;text-align:center}.content figure:not(:first-child){margin-top:2em}.content figure:not(:last-child){margin-bottom:2em}.content figure img{display:inline-block}.content figure figcaption{font-style:italic}.content pre{-webkit-overflow-scrolling:touch;overflow-x:auto;padding:0;white-space:pre;word-wrap:normal}.content sup,.content sub{font-size:75%}.content table{width:100%}.content table td,.content table th{border:1px solid #dbdbdb;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}.content table th{color:#222}.content table th:not([align]){text-align:inherit}.content table thead td,.content table thead th{border-width:0 0 2px;color:#222}.content table tfoot td,.content table tfoot th{border-width:2px 0 0;color:#222}.content table tbody tr:last-child td,.content table tbody tr:last-child th{border-bottom-width:0}.content .tabs li+li{margin-top:0}.content.is-small,#documenter .docs-sidebar form.docs-search>input.content{font-size:.75rem}.content.is-normal{font-size:1rem}.content.is-medium{font-size:1.25rem}.content.is-large{font-size:1.5rem}.icon{align-items:center;display:inline-flex;justify-content:center;height:1.5rem;width:1.5rem}.icon.is-small,#documenter .docs-sidebar form.docs-search>input.icon{height:1rem;width:1rem}.icon.is-medium{height:2rem;width:2rem}.icon.is-large{height:3rem;width:3rem}.icon-text{align-items:flex-start;color:inherit;display:inline-flex;flex-wrap:wrap;line-height:1.5rem;vertical-align:top}.icon-text .icon{flex-grow:0;flex-shrink:0}.icon-text .icon:not(:last-child){margin-right:.25em}.icon-text .icon:not(:first-child){margin-left:.25em}div.icon-text{display:flex}.image,#documenter .docs-sidebar .docs-logo>img{display:block;position:relative}.image img,#documenter .docs-sidebar .docs-logo>img img{display:block;height:auto;width:100%}.image img.is-rounded,#documenter .docs-sidebar .docs-logo>img img.is-rounded{border-radius:9999px}.image.is-fullwidth,#documenter .docs-sidebar .docs-logo>img.is-fullwidth{width:100%}.image.is-square img,#documenter .docs-sidebar .docs-logo>img.is-square img,.image.is-square .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-square .has-ratio,.image.is-1by1 img,#documenter .docs-sidebar .docs-logo>img.is-1by1 img,.image.is-1by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by1 .has-ratio,.image.is-5by4 img,#documenter .docs-sidebar .docs-logo>img.is-5by4 img,.image.is-5by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by4 .has-ratio,.image.is-4by3 img,#documenter .docs-sidebar .docs-logo>img.is-4by3 img,.image.is-4by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by3 .has-ratio,.image.is-3by2 img,#documenter .docs-sidebar .docs-logo>img.is-3by2 img,.image.is-3by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by2 .has-ratio,.image.is-5by3 img,#documenter .docs-sidebar .docs-logo>img.is-5by3 img,.image.is-5by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-5by3 .has-ratio,.image.is-16by9 img,#documenter .docs-sidebar .docs-logo>img.is-16by9 img,.image.is-16by9 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-16by9 .has-ratio,.image.is-2by1 img,#documenter .docs-sidebar .docs-logo>img.is-2by1 img,.image.is-2by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by1 .has-ratio,.image.is-3by1 img,#documenter .docs-sidebar .docs-logo>img.is-3by1 img,.image.is-3by1 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by1 .has-ratio,.image.is-4by5 img,#documenter .docs-sidebar .docs-logo>img.is-4by5 img,.image.is-4by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-4by5 .has-ratio,.image.is-3by4 img,#documenter .docs-sidebar .docs-logo>img.is-3by4 img,.image.is-3by4 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by4 .has-ratio,.image.is-2by3 img,#documenter .docs-sidebar .docs-logo>img.is-2by3 img,.image.is-2by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-2by3 .has-ratio,.image.is-3by5 img,#documenter .docs-sidebar .docs-logo>img.is-3by5 img,.image.is-3by5 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-3by5 .has-ratio,.image.is-9by16 img,#documenter .docs-sidebar .docs-logo>img.is-9by16 img,.image.is-9by16 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-9by16 .has-ratio,.image.is-1by2 img,#documenter .docs-sidebar .docs-logo>img.is-1by2 img,.image.is-1by2 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by2 .has-ratio,.image.is-1by3 img,#documenter .docs-sidebar .docs-logo>img.is-1by3 img,.image.is-1by3 .has-ratio,#documenter .docs-sidebar .docs-logo>img.is-1by3 .has-ratio{height:100%;width:100%}.image.is-square,#documenter .docs-sidebar .docs-logo>img.is-square,.image.is-1by1,#documenter .docs-sidebar .docs-logo>img.is-1by1{padding-top:100%}.image.is-5by4,#documenter .docs-sidebar .docs-logo>img.is-5by4{padding-top:80%}.image.is-4by3,#documenter .docs-sidebar .docs-logo>img.is-4by3{padding-top:75%}.image.is-3by2,#documenter .docs-sidebar .docs-logo>img.is-3by2{padding-top:66.6666%}.image.is-5by3,#documenter .docs-sidebar .docs-logo>img.is-5by3{padding-top:60%}.image.is-16by9,#documenter .docs-sidebar .docs-logo>img.is-16by9{padding-top:56.25%}.image.is-2by1,#documenter .docs-sidebar .docs-logo>img.is-2by1{padding-top:50%}.image.is-3by1,#documenter .docs-sidebar .docs-logo>img.is-3by1{padding-top:33.3333%}.image.is-4by5,#documenter .docs-sidebar .docs-logo>img.is-4by5{padding-top:125%}.image.is-3by4,#documenter .docs-sidebar .docs-logo>img.is-3by4{padding-top:133.3333%}.image.is-2by3,#documenter .docs-sidebar .docs-logo>img.is-2by3{padding-top:150%}.image.is-3by5,#documenter .docs-sidebar .docs-logo>img.is-3by5{padding-top:166.6666%}.image.is-9by16,#documenter .docs-sidebar .docs-logo>img.is-9by16{padding-top:177.7777%}.image.is-1by2,#documenter .docs-sidebar .docs-logo>img.is-1by2{padding-top:200%}.image.is-1by3,#documenter .docs-sidebar .docs-logo>img.is-1by3{padding-top:300%}.image.is-16x16,#documenter .docs-sidebar .docs-logo>img.is-16x16{height:16px;width:16px}.image.is-24x24,#documenter .docs-sidebar .docs-logo>img.is-24x24{height:24px;width:24px}.image.is-32x32,#documenter .docs-sidebar .docs-logo>img.is-32x32{height:32px;width:32px}.image.is-48x48,#documenter .docs-sidebar .docs-logo>img.is-48x48{height:48px;width:48px}.image.is-64x64,#documenter .docs-sidebar .docs-logo>img.is-64x64{height:64px;width:64px}.image.is-96x96,#documenter .docs-sidebar .docs-logo>img.is-96x96{height:96px;width:96px}.image.is-128x128,#documenter .docs-sidebar .docs-logo>img.is-128x128{height:128px;width:128px}.notification{background-color:#f5f5f5;border-radius:4px;position:relative;padding:1.25rem 2.5rem 1.25rem 1.5rem}.notification a:not(.button):not(.dropdown-item){color:currentColor;text-decoration:underline}.notification strong{color:currentColor}.notification code,.notification pre{background:#fff}.notification pre code{background:transparent}.notification>.delete{right:.5rem;position:absolute;top:0.5rem}.notification .title,.notification .subtitle,.notification .content{color:currentColor}.notification.is-white{background-color:#fff;color:#0a0a0a}.notification.is-black{background-color:#0a0a0a;color:#fff}.notification.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.notification.is-dark,.content kbd.notification{background-color:#363636;color:#fff}.notification.is-primary,.docstring>section>a.notification.docs-sourcelink{background-color:#4eb5de;color:#fff}.notification.is-primary.is-light,.docstring>section>a.notification.is-light.docs-sourcelink{background-color:#eef8fc;color:#1a6d8e}.notification.is-link{background-color:#2e63b8;color:#fff}.notification.is-link.is-light{background-color:#eff3fb;color:#3169c4}.notification.is-info{background-color:#209cee;color:#fff}.notification.is-info.is-light{background-color:#ecf7fe;color:#0e72b4}.notification.is-success{background-color:#22c35b;color:#fff}.notification.is-success.is-light{background-color:#eefcf3;color:#198f43}.notification.is-warning{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.notification.is-warning.is-light{background-color:#fffbeb;color:#947600}.notification.is-danger{background-color:#da0b00;color:#fff}.notification.is-danger.is-light{background-color:#ffeceb;color:#f50c00}.progress{-moz-appearance:none;-webkit-appearance:none;border:none;border-radius:9999px;display:block;height:1rem;overflow:hidden;padding:0;width:100%}.progress::-webkit-progress-bar{background-color:#ededed}.progress::-webkit-progress-value{background-color:#222}.progress::-moz-progress-bar{background-color:#222}.progress::-ms-fill{background-color:#222;border:none}.progress.is-white::-webkit-progress-value{background-color:#fff}.progress.is-white::-moz-progress-bar{background-color:#fff}.progress.is-white::-ms-fill{background-color:#fff}.progress.is-white:indeterminate{background-image:linear-gradient(to right, #fff 30%, #ededed 30%)}.progress.is-black::-webkit-progress-value{background-color:#0a0a0a}.progress.is-black::-moz-progress-bar{background-color:#0a0a0a}.progress.is-black::-ms-fill{background-color:#0a0a0a}.progress.is-black:indeterminate{background-image:linear-gradient(to right, #0a0a0a 30%, #ededed 30%)}.progress.is-light::-webkit-progress-value{background-color:#f5f5f5}.progress.is-light::-moz-progress-bar{background-color:#f5f5f5}.progress.is-light::-ms-fill{background-color:#f5f5f5}.progress.is-light:indeterminate{background-image:linear-gradient(to right, #f5f5f5 30%, #ededed 30%)}.progress.is-dark::-webkit-progress-value,.content kbd.progress::-webkit-progress-value{background-color:#363636}.progress.is-dark::-moz-progress-bar,.content kbd.progress::-moz-progress-bar{background-color:#363636}.progress.is-dark::-ms-fill,.content kbd.progress::-ms-fill{background-color:#363636}.progress.is-dark:indeterminate,.content kbd.progress:indeterminate{background-image:linear-gradient(to right, #363636 30%, #ededed 30%)}.progress.is-primary::-webkit-progress-value,.docstring>section>a.progress.docs-sourcelink::-webkit-progress-value{background-color:#4eb5de}.progress.is-primary::-moz-progress-bar,.docstring>section>a.progress.docs-sourcelink::-moz-progress-bar{background-color:#4eb5de}.progress.is-primary::-ms-fill,.docstring>section>a.progress.docs-sourcelink::-ms-fill{background-color:#4eb5de}.progress.is-primary:indeterminate,.docstring>section>a.progress.docs-sourcelink:indeterminate{background-image:linear-gradient(to right, #4eb5de 30%, #ededed 30%)}.progress.is-link::-webkit-progress-value{background-color:#2e63b8}.progress.is-link::-moz-progress-bar{background-color:#2e63b8}.progress.is-link::-ms-fill{background-color:#2e63b8}.progress.is-link:indeterminate{background-image:linear-gradient(to right, #2e63b8 30%, #ededed 30%)}.progress.is-info::-webkit-progress-value{background-color:#209cee}.progress.is-info::-moz-progress-bar{background-color:#209cee}.progress.is-info::-ms-fill{background-color:#209cee}.progress.is-info:indeterminate{background-image:linear-gradient(to right, #209cee 30%, #ededed 30%)}.progress.is-success::-webkit-progress-value{background-color:#22c35b}.progress.is-success::-moz-progress-bar{background-color:#22c35b}.progress.is-success::-ms-fill{background-color:#22c35b}.progress.is-success:indeterminate{background-image:linear-gradient(to right, #22c35b 30%, #ededed 30%)}.progress.is-warning::-webkit-progress-value{background-color:#ffdd57}.progress.is-warning::-moz-progress-bar{background-color:#ffdd57}.progress.is-warning::-ms-fill{background-color:#ffdd57}.progress.is-warning:indeterminate{background-image:linear-gradient(to right, #ffdd57 30%, #ededed 30%)}.progress.is-danger::-webkit-progress-value{background-color:#da0b00}.progress.is-danger::-moz-progress-bar{background-color:#da0b00}.progress.is-danger::-ms-fill{background-color:#da0b00}.progress.is-danger:indeterminate{background-image:linear-gradient(to right, #da0b00 30%, #ededed 30%)}.progress:indeterminate{animation-duration:1.5s;animation-iteration-count:infinite;animation-name:moveIndeterminate;animation-timing-function:linear;background-color:#ededed;background-image:linear-gradient(to right, #222 30%, #ededed 30%);background-position:top left;background-repeat:no-repeat;background-size:150% 150%}.progress:indeterminate::-webkit-progress-bar{background-color:transparent}.progress:indeterminate::-moz-progress-bar{background-color:transparent}.progress:indeterminate::-ms-fill{animation-name:none}.progress.is-small,#documenter .docs-sidebar form.docs-search>input.progress{height:.75rem}.progress.is-medium{height:1.25rem}.progress.is-large{height:1.5rem}@keyframes moveIndeterminate{from{background-position:200% 0}to{background-position:-200% 0}}.table{background-color:#fff;color:#222}.table td,.table th{border:1px solid #dbdbdb;border-width:0 0 1px;padding:0.5em 0.75em;vertical-align:top}.table td.is-white,.table th.is-white{background-color:#fff;border-color:#fff;color:#0a0a0a}.table td.is-black,.table th.is-black{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.table td.is-light,.table th.is-light{background-color:#f5f5f5;border-color:#f5f5f5;color:rgba(0,0,0,0.7)}.table td.is-dark,.table th.is-dark{background-color:#363636;border-color:#363636;color:#fff}.table td.is-primary,.table th.is-primary{background-color:#4eb5de;border-color:#4eb5de;color:#fff}.table td.is-link,.table th.is-link{background-color:#2e63b8;border-color:#2e63b8;color:#fff}.table td.is-info,.table th.is-info{background-color:#209cee;border-color:#209cee;color:#fff}.table td.is-success,.table th.is-success{background-color:#22c35b;border-color:#22c35b;color:#fff}.table td.is-warning,.table th.is-warning{background-color:#ffdd57;border-color:#ffdd57;color:rgba(0,0,0,0.7)}.table td.is-danger,.table th.is-danger{background-color:#da0b00;border-color:#da0b00;color:#fff}.table td.is-narrow,.table th.is-narrow{white-space:nowrap;width:1%}.table td.is-selected,.table th.is-selected{background-color:#4eb5de;color:#fff}.table td.is-selected a,.table td.is-selected strong,.table th.is-selected a,.table th.is-selected strong{color:currentColor}.table td.is-vcentered,.table th.is-vcentered{vertical-align:middle}.table th{color:#222}.table th:not([align]){text-align:left}.table tr.is-selected{background-color:#4eb5de;color:#fff}.table tr.is-selected a,.table tr.is-selected strong{color:currentColor}.table tr.is-selected td,.table tr.is-selected th{border-color:#fff;color:currentColor}.table thead{background-color:rgba(0,0,0,0)}.table thead td,.table thead th{border-width:0 0 2px;color:#222}.table tfoot{background-color:rgba(0,0,0,0)}.table tfoot td,.table tfoot th{border-width:2px 0 0;color:#222}.table tbody{background-color:rgba(0,0,0,0)}.table tbody tr:last-child td,.table tbody tr:last-child th{border-bottom-width:0}.table.is-bordered td,.table.is-bordered th{border-width:1px}.table.is-bordered tr:last-child td,.table.is-bordered tr:last-child th{border-bottom-width:1px}.table.is-fullwidth{width:100%}.table.is-hoverable tbody tr:not(.is-selected):hover{background-color:#fafafa}.table.is-hoverable.is-striped tbody tr:not(.is-selected):hover{background-color:#fafafa}.table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even){background-color:#f5f5f5}.table.is-narrow td,.table.is-narrow th{padding:0.25em 0.5em}.table.is-striped tbody tr:not(.is-selected):nth-child(even){background-color:#fafafa}.table-container{-webkit-overflow-scrolling:touch;overflow:auto;overflow-y:hidden;max-width:100%}.tags{align-items:center;display:flex;flex-wrap:wrap;justify-content:flex-start}.tags .tag,.tags .content kbd,.content .tags kbd,.tags .docstring>section>a.docs-sourcelink{margin-bottom:0.5rem}.tags .tag:not(:last-child),.tags .content kbd:not(:last-child),.content .tags kbd:not(:last-child),.tags .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:.5rem}.tags:last-child{margin-bottom:-0.5rem}.tags:not(:last-child){margin-bottom:1rem}.tags.are-medium .tag:not(.is-normal):not(.is-large),.tags.are-medium .content kbd:not(.is-normal):not(.is-large),.content .tags.are-medium kbd:not(.is-normal):not(.is-large),.tags.are-medium .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-large){font-size:1rem}.tags.are-large .tag:not(.is-normal):not(.is-medium),.tags.are-large .content kbd:not(.is-normal):not(.is-medium),.content .tags.are-large kbd:not(.is-normal):not(.is-medium),.tags.are-large .docstring>section>a.docs-sourcelink:not(.is-normal):not(.is-medium){font-size:1.25rem}.tags.is-centered{justify-content:center}.tags.is-centered .tag,.tags.is-centered .content kbd,.content .tags.is-centered kbd,.tags.is-centered .docstring>section>a.docs-sourcelink{margin-right:0.25rem;margin-left:0.25rem}.tags.is-right{justify-content:flex-end}.tags.is-right .tag:not(:first-child),.tags.is-right .content kbd:not(:first-child),.content .tags.is-right kbd:not(:first-child),.tags.is-right .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0.5rem}.tags.is-right .tag:not(:last-child),.tags.is-right .content kbd:not(:last-child),.content .tags.is-right kbd:not(:last-child),.tags.is-right .docstring>section>a.docs-sourcelink:not(:last-child){margin-right:0}.tags.has-addons .tag,.tags.has-addons .content kbd,.content .tags.has-addons kbd,.tags.has-addons .docstring>section>a.docs-sourcelink{margin-right:0}.tags.has-addons .tag:not(:first-child),.tags.has-addons .content kbd:not(:first-child),.content .tags.has-addons kbd:not(:first-child),.tags.has-addons .docstring>section>a.docs-sourcelink:not(:first-child){margin-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.tags.has-addons .tag:not(:last-child),.tags.has-addons .content kbd:not(:last-child),.content .tags.has-addons kbd:not(:last-child),.tags.has-addons .docstring>section>a.docs-sourcelink:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.tag:not(body),.content kbd:not(body),.docstring>section>a.docs-sourcelink:not(body){align-items:center;background-color:#f5f5f5;border-radius:4px;color:#222;display:inline-flex;font-size:.75rem;height:2em;justify-content:center;line-height:1.5;padding-left:0.75em;padding-right:0.75em;white-space:nowrap}.tag:not(body) .delete,.content kbd:not(body) .delete,.docstring>section>a.docs-sourcelink:not(body) .delete{margin-left:.25rem;margin-right:-.375rem}.tag.is-white:not(body),.content kbd.is-white:not(body),.docstring>section>a.docs-sourcelink.is-white:not(body){background-color:#fff;color:#0a0a0a}.tag.is-black:not(body),.content kbd.is-black:not(body),.docstring>section>a.docs-sourcelink.is-black:not(body){background-color:#0a0a0a;color:#fff}.tag.is-light:not(body),.content kbd.is-light:not(body),.docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.tag.is-dark:not(body),.content kbd:not(body),.docstring>section>a.docs-sourcelink.is-dark:not(body),.content .docstring>section>kbd:not(body){background-color:#363636;color:#fff}.tag.is-primary:not(body),.content kbd.is-primary:not(body),.docstring>section>a.docs-sourcelink:not(body){background-color:#4eb5de;color:#fff}.tag.is-primary.is-light:not(body),.content kbd.is-primary.is-light:not(body),.docstring>section>a.docs-sourcelink.is-light:not(body){background-color:#eef8fc;color:#1a6d8e}.tag.is-link:not(body),.content kbd.is-link:not(body),.docstring>section>a.docs-sourcelink.is-link:not(body){background-color:#2e63b8;color:#fff}.tag.is-link.is-light:not(body),.content kbd.is-link.is-light:not(body),.docstring>section>a.docs-sourcelink.is-link.is-light:not(body){background-color:#eff3fb;color:#3169c4}.tag.is-info:not(body),.content kbd.is-info:not(body),.docstring>section>a.docs-sourcelink.is-info:not(body){background-color:#209cee;color:#fff}.tag.is-info.is-light:not(body),.content kbd.is-info.is-light:not(body),.docstring>section>a.docs-sourcelink.is-info.is-light:not(body){background-color:#ecf7fe;color:#0e72b4}.tag.is-success:not(body),.content kbd.is-success:not(body),.docstring>section>a.docs-sourcelink.is-success:not(body){background-color:#22c35b;color:#fff}.tag.is-success.is-light:not(body),.content kbd.is-success.is-light:not(body),.docstring>section>a.docs-sourcelink.is-success.is-light:not(body){background-color:#eefcf3;color:#198f43}.tag.is-warning:not(body),.content kbd.is-warning:not(body),.docstring>section>a.docs-sourcelink.is-warning:not(body){background-color:#ffdd57;color:rgba(0,0,0,0.7)}.tag.is-warning.is-light:not(body),.content kbd.is-warning.is-light:not(body),.docstring>section>a.docs-sourcelink.is-warning.is-light:not(body){background-color:#fffbeb;color:#947600}.tag.is-danger:not(body),.content kbd.is-danger:not(body),.docstring>section>a.docs-sourcelink.is-danger:not(body){background-color:#da0b00;color:#fff}.tag.is-danger.is-light:not(body),.content kbd.is-danger.is-light:not(body),.docstring>section>a.docs-sourcelink.is-danger.is-light:not(body){background-color:#ffeceb;color:#f50c00}.tag.is-normal:not(body),.content kbd.is-normal:not(body),.docstring>section>a.docs-sourcelink.is-normal:not(body){font-size:.75rem}.tag.is-medium:not(body),.content kbd.is-medium:not(body),.docstring>section>a.docs-sourcelink.is-medium:not(body){font-size:1rem}.tag.is-large:not(body),.content kbd.is-large:not(body),.docstring>section>a.docs-sourcelink.is-large:not(body){font-size:1.25rem}.tag:not(body) .icon:first-child:not(:last-child),.content kbd:not(body) .icon:first-child:not(:last-child),.docstring>section>a.docs-sourcelink:not(body) .icon:first-child:not(:last-child){margin-left:-.375em;margin-right:.1875em}.tag:not(body) .icon:last-child:not(:first-child),.content kbd:not(body) .icon:last-child:not(:first-child),.docstring>section>a.docs-sourcelink:not(body) .icon:last-child:not(:first-child){margin-left:.1875em;margin-right:-.375em}.tag:not(body) .icon:first-child:last-child,.content kbd:not(body) .icon:first-child:last-child,.docstring>section>a.docs-sourcelink:not(body) .icon:first-child:last-child{margin-left:-.375em;margin-right:-.375em}.tag.is-delete:not(body),.content kbd.is-delete:not(body),.docstring>section>a.docs-sourcelink.is-delete:not(body){margin-left:1px;padding:0;position:relative;width:2em}.tag.is-delete:not(body)::before,.content kbd.is-delete:not(body)::before,.docstring>section>a.docs-sourcelink.is-delete:not(body)::before,.tag.is-delete:not(body)::after,.content kbd.is-delete:not(body)::after,.docstring>section>a.docs-sourcelink.is-delete:not(body)::after{background-color:currentColor;content:"";display:block;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%) rotate(45deg);transform-origin:center center}.tag.is-delete:not(body)::before,.content kbd.is-delete:not(body)::before,.docstring>section>a.docs-sourcelink.is-delete:not(body)::before{height:1px;width:50%}.tag.is-delete:not(body)::after,.content kbd.is-delete:not(body)::after,.docstring>section>a.docs-sourcelink.is-delete:not(body)::after{height:50%;width:1px}.tag.is-delete:not(body):hover,.content kbd.is-delete:not(body):hover,.docstring>section>a.docs-sourcelink.is-delete:not(body):hover,.tag.is-delete:not(body):focus,.content kbd.is-delete:not(body):focus,.docstring>section>a.docs-sourcelink.is-delete:not(body):focus{background-color:#e8e8e8}.tag.is-delete:not(body):active,.content kbd.is-delete:not(body):active,.docstring>section>a.docs-sourcelink.is-delete:not(body):active{background-color:#dbdbdb}.tag.is-rounded:not(body),#documenter .docs-sidebar form.docs-search>input:not(body),.content kbd.is-rounded:not(body),#documenter .docs-sidebar .content form.docs-search>input:not(body),.docstring>section>a.docs-sourcelink.is-rounded:not(body){border-radius:9999px}a.tag:hover,.docstring>section>a.docs-sourcelink:hover{text-decoration:underline}.title,.subtitle{word-break:break-word}.title em,.title span,.subtitle em,.subtitle span{font-weight:inherit}.title sub,.subtitle sub{font-size:.75em}.title sup,.subtitle sup{font-size:.75em}.title .tag,.title .content kbd,.content .title kbd,.title .docstring>section>a.docs-sourcelink,.subtitle .tag,.subtitle .content kbd,.content .subtitle kbd,.subtitle .docstring>section>a.docs-sourcelink{vertical-align:middle}.title{color:#222;font-size:2rem;font-weight:600;line-height:1.125}.title strong{color:inherit;font-weight:inherit}.title:not(.is-spaced)+.subtitle{margin-top:-1.25rem}.title.is-1{font-size:3rem}.title.is-2{font-size:2.5rem}.title.is-3{font-size:2rem}.title.is-4{font-size:1.5rem}.title.is-5{font-size:1.25rem}.title.is-6{font-size:1rem}.title.is-7{font-size:.75rem}.subtitle{color:#222;font-size:1.25rem;font-weight:400;line-height:1.25}.subtitle strong{color:#222;font-weight:600}.subtitle:not(.is-spaced)+.title{margin-top:-1.25rem}.subtitle.is-1{font-size:3rem}.subtitle.is-2{font-size:2.5rem}.subtitle.is-3{font-size:2rem}.subtitle.is-4{font-size:1.5rem}.subtitle.is-5{font-size:1.25rem}.subtitle.is-6{font-size:1rem}.subtitle.is-7{font-size:.75rem}.heading{display:block;font-size:11px;letter-spacing:1px;margin-bottom:5px;text-transform:uppercase}.number{align-items:center;background-color:#f5f5f5;border-radius:9999px;display:inline-flex;font-size:1.25rem;height:2em;justify-content:center;margin-right:1.5rem;min-width:2.5em;padding:0.25rem 0.5rem;text-align:center;vertical-align:top}.select select,.textarea,.input,#documenter .docs-sidebar form.docs-search>input{background-color:#fff;border-color:#dbdbdb;border-radius:4px;color:#222}.select select::-moz-placeholder,.textarea::-moz-placeholder,.input::-moz-placeholder,#documenter .docs-sidebar form.docs-search>input::-moz-placeholder{color:#707070}.select select::-webkit-input-placeholder,.textarea::-webkit-input-placeholder,.input::-webkit-input-placeholder,#documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder{color:#707070}.select select:-moz-placeholder,.textarea:-moz-placeholder,.input:-moz-placeholder,#documenter .docs-sidebar form.docs-search>input:-moz-placeholder{color:#707070}.select select:-ms-input-placeholder,.textarea:-ms-input-placeholder,.input:-ms-input-placeholder,#documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder{color:#707070}.select select:hover,.textarea:hover,.input:hover,#documenter .docs-sidebar form.docs-search>input:hover,.select select.is-hovered,.is-hovered.textarea,.is-hovered.input,#documenter .docs-sidebar form.docs-search>input.is-hovered{border-color:#b5b5b5}.select select:focus,.textarea:focus,.input:focus,#documenter .docs-sidebar form.docs-search>input:focus,.select select.is-focused,.is-focused.textarea,.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.select select:active,.textarea:active,.input:active,#documenter .docs-sidebar form.docs-search>input:active,.select select.is-active,.is-active.textarea,.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{border-color:#2e63b8;box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.select select[disabled],.textarea[disabled],.input[disabled],#documenter .docs-sidebar form.docs-search>input[disabled],fieldset[disabled] .select select,.select fieldset[disabled] select,fieldset[disabled] .textarea,fieldset[disabled] .input,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input{background-color:#f5f5f5;border-color:#f5f5f5;box-shadow:none;color:#6b6b6b}.select select[disabled]::-moz-placeholder,.textarea[disabled]::-moz-placeholder,.input[disabled]::-moz-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]::-moz-placeholder,fieldset[disabled] .select select::-moz-placeholder,.select fieldset[disabled] select::-moz-placeholder,fieldset[disabled] .textarea::-moz-placeholder,fieldset[disabled] .input::-moz-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input::-moz-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input::-moz-placeholder{color:rgba(107,107,107,0.3)}.select select[disabled]::-webkit-input-placeholder,.textarea[disabled]::-webkit-input-placeholder,.input[disabled]::-webkit-input-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]::-webkit-input-placeholder,fieldset[disabled] .select select::-webkit-input-placeholder,.select fieldset[disabled] select::-webkit-input-placeholder,fieldset[disabled] .textarea::-webkit-input-placeholder,fieldset[disabled] .input::-webkit-input-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input::-webkit-input-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input::-webkit-input-placeholder{color:rgba(107,107,107,0.3)}.select select[disabled]:-moz-placeholder,.textarea[disabled]:-moz-placeholder,.input[disabled]:-moz-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]:-moz-placeholder,fieldset[disabled] .select select:-moz-placeholder,.select fieldset[disabled] select:-moz-placeholder,fieldset[disabled] .textarea:-moz-placeholder,fieldset[disabled] .input:-moz-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input:-moz-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input:-moz-placeholder{color:rgba(107,107,107,0.3)}.select select[disabled]:-ms-input-placeholder,.textarea[disabled]:-ms-input-placeholder,.input[disabled]:-ms-input-placeholder,#documenter .docs-sidebar form.docs-search>input[disabled]:-ms-input-placeholder,fieldset[disabled] .select select:-ms-input-placeholder,.select fieldset[disabled] select:-ms-input-placeholder,fieldset[disabled] .textarea:-ms-input-placeholder,fieldset[disabled] .input:-ms-input-placeholder,fieldset[disabled] #documenter .docs-sidebar form.docs-search>input:-ms-input-placeholder,#documenter .docs-sidebar fieldset[disabled] form.docs-search>input:-ms-input-placeholder{color:rgba(107,107,107,0.3)}.textarea,.input,#documenter .docs-sidebar form.docs-search>input{box-shadow:inset 0 0.0625em 0.125em rgba(10,10,10,0.05);max-width:100%;width:100%}.textarea[readonly],.input[readonly],#documenter .docs-sidebar form.docs-search>input[readonly]{box-shadow:none}.is-white.textarea,.is-white.input,#documenter .docs-sidebar form.docs-search>input.is-white{border-color:#fff}.is-white.textarea:focus,.is-white.input:focus,#documenter .docs-sidebar form.docs-search>input.is-white:focus,.is-white.is-focused.textarea,.is-white.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-white.textarea:active,.is-white.input:active,#documenter .docs-sidebar form.docs-search>input.is-white:active,.is-white.is-active.textarea,.is-white.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}.is-black.textarea,.is-black.input,#documenter .docs-sidebar form.docs-search>input.is-black{border-color:#0a0a0a}.is-black.textarea:focus,.is-black.input:focus,#documenter .docs-sidebar form.docs-search>input.is-black:focus,.is-black.is-focused.textarea,.is-black.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-black.textarea:active,.is-black.input:active,#documenter .docs-sidebar form.docs-search>input.is-black:active,.is-black.is-active.textarea,.is-black.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}.is-light.textarea,.is-light.input,#documenter .docs-sidebar form.docs-search>input.is-light{border-color:#f5f5f5}.is-light.textarea:focus,.is-light.input:focus,#documenter .docs-sidebar form.docs-search>input.is-light:focus,.is-light.is-focused.textarea,.is-light.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-light.textarea:active,.is-light.input:active,#documenter .docs-sidebar form.docs-search>input.is-light:active,.is-light.is-active.textarea,.is-light.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}.is-dark.textarea,.content kbd.textarea,.is-dark.input,#documenter .docs-sidebar form.docs-search>input.is-dark,.content kbd.input{border-color:#363636}.is-dark.textarea:focus,.content kbd.textarea:focus,.is-dark.input:focus,#documenter .docs-sidebar form.docs-search>input.is-dark:focus,.content kbd.input:focus,.is-dark.is-focused.textarea,.content kbd.is-focused.textarea,.is-dark.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.content kbd.is-focused.input,#documenter .docs-sidebar .content form.docs-search>input.is-focused,.is-dark.textarea:active,.content kbd.textarea:active,.is-dark.input:active,#documenter .docs-sidebar form.docs-search>input.is-dark:active,.content kbd.input:active,.is-dark.is-active.textarea,.content kbd.is-active.textarea,.is-dark.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active,.content kbd.is-active.input,#documenter .docs-sidebar .content form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(54,54,54,0.25)}.is-primary.textarea,.docstring>section>a.textarea.docs-sourcelink,.is-primary.input,#documenter .docs-sidebar form.docs-search>input.is-primary,.docstring>section>a.input.docs-sourcelink{border-color:#4eb5de}.is-primary.textarea:focus,.docstring>section>a.textarea.docs-sourcelink:focus,.is-primary.input:focus,#documenter .docs-sidebar form.docs-search>input.is-primary:focus,.docstring>section>a.input.docs-sourcelink:focus,.is-primary.is-focused.textarea,.docstring>section>a.is-focused.textarea.docs-sourcelink,.is-primary.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.docstring>section>a.is-focused.input.docs-sourcelink,.is-primary.textarea:active,.docstring>section>a.textarea.docs-sourcelink:active,.is-primary.input:active,#documenter .docs-sidebar form.docs-search>input.is-primary:active,.docstring>section>a.input.docs-sourcelink:active,.is-primary.is-active.textarea,.docstring>section>a.is-active.textarea.docs-sourcelink,.is-primary.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active,.docstring>section>a.is-active.input.docs-sourcelink{box-shadow:0 0 0 0.125em rgba(78,181,222,0.25)}.is-link.textarea,.is-link.input,#documenter .docs-sidebar form.docs-search>input.is-link{border-color:#2e63b8}.is-link.textarea:focus,.is-link.input:focus,#documenter .docs-sidebar form.docs-search>input.is-link:focus,.is-link.is-focused.textarea,.is-link.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-link.textarea:active,.is-link.input:active,#documenter .docs-sidebar form.docs-search>input.is-link:active,.is-link.is-active.textarea,.is-link.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.is-info.textarea,.is-info.input,#documenter .docs-sidebar form.docs-search>input.is-info{border-color:#209cee}.is-info.textarea:focus,.is-info.input:focus,#documenter .docs-sidebar form.docs-search>input.is-info:focus,.is-info.is-focused.textarea,.is-info.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-info.textarea:active,.is-info.input:active,#documenter .docs-sidebar form.docs-search>input.is-info:active,.is-info.is-active.textarea,.is-info.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(32,156,238,0.25)}.is-success.textarea,.is-success.input,#documenter .docs-sidebar form.docs-search>input.is-success{border-color:#22c35b}.is-success.textarea:focus,.is-success.input:focus,#documenter .docs-sidebar form.docs-search>input.is-success:focus,.is-success.is-focused.textarea,.is-success.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-success.textarea:active,.is-success.input:active,#documenter .docs-sidebar form.docs-search>input.is-success:active,.is-success.is-active.textarea,.is-success.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(34,195,91,0.25)}.is-warning.textarea,.is-warning.input,#documenter .docs-sidebar form.docs-search>input.is-warning{border-color:#ffdd57}.is-warning.textarea:focus,.is-warning.input:focus,#documenter .docs-sidebar form.docs-search>input.is-warning:focus,.is-warning.is-focused.textarea,.is-warning.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-warning.textarea:active,.is-warning.input:active,#documenter .docs-sidebar form.docs-search>input.is-warning:active,.is-warning.is-active.textarea,.is-warning.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(255,221,87,0.25)}.is-danger.textarea,.is-danger.input,#documenter .docs-sidebar form.docs-search>input.is-danger{border-color:#da0b00}.is-danger.textarea:focus,.is-danger.input:focus,#documenter .docs-sidebar form.docs-search>input.is-danger:focus,.is-danger.is-focused.textarea,.is-danger.is-focused.input,#documenter .docs-sidebar form.docs-search>input.is-focused,.is-danger.textarea:active,.is-danger.input:active,#documenter .docs-sidebar form.docs-search>input.is-danger:active,.is-danger.is-active.textarea,.is-danger.is-active.input,#documenter .docs-sidebar form.docs-search>input.is-active{box-shadow:0 0 0 0.125em rgba(218,11,0,0.25)}.is-small.textarea,.is-small.input,#documenter .docs-sidebar form.docs-search>input{border-radius:2px;font-size:.75rem}.is-medium.textarea,.is-medium.input,#documenter .docs-sidebar form.docs-search>input.is-medium{font-size:1.25rem}.is-large.textarea,.is-large.input,#documenter .docs-sidebar form.docs-search>input.is-large{font-size:1.5rem}.is-fullwidth.textarea,.is-fullwidth.input,#documenter .docs-sidebar form.docs-search>input.is-fullwidth{display:block;width:100%}.is-inline.textarea,.is-inline.input,#documenter .docs-sidebar form.docs-search>input.is-inline{display:inline;width:auto}.input.is-rounded,#documenter .docs-sidebar form.docs-search>input{border-radius:9999px;padding-left:calc(calc(0.75em - 1px) + 0.375em);padding-right:calc(calc(0.75em - 1px) + 0.375em)}.input.is-static,#documenter .docs-sidebar form.docs-search>input.is-static{background-color:transparent;border-color:transparent;box-shadow:none;padding-left:0;padding-right:0}.textarea{display:block;max-width:100%;min-width:100%;padding:calc(0.75em - 1px);resize:vertical}.textarea:not([rows]){max-height:40em;min-height:8em}.textarea[rows]{height:initial}.textarea.has-fixed-size{resize:none}.radio,.checkbox{cursor:pointer;display:inline-block;line-height:1.25;position:relative}.radio input,.checkbox input{cursor:pointer}.radio:hover,.checkbox:hover{color:#222}.radio[disabled],.checkbox[disabled],fieldset[disabled] .radio,fieldset[disabled] .checkbox,.radio input[disabled],.checkbox input[disabled]{color:#6b6b6b;cursor:not-allowed}.radio+.radio{margin-left:.5em}.select{display:inline-block;max-width:100%;position:relative;vertical-align:top}.select:not(.is-multiple){height:2.5em}.select:not(.is-multiple):not(.is-loading)::after{border-color:#2e63b8;right:1.125em;z-index:4}.select.is-rounded select,#documenter .docs-sidebar form.docs-search>input.select select{border-radius:9999px;padding-left:1em}.select select{cursor:pointer;display:block;font-size:1em;max-width:100%;outline:none}.select select::-ms-expand{display:none}.select select[disabled]:hover,fieldset[disabled] .select select:hover{border-color:#f5f5f5}.select select:not([multiple]){padding-right:2.5em}.select select[multiple]{height:auto;padding:0}.select select[multiple] option{padding:0.5em 1em}.select:not(.is-multiple):not(.is-loading):hover::after{border-color:#222}.select.is-white:not(:hover)::after{border-color:#fff}.select.is-white select{border-color:#fff}.select.is-white select:hover,.select.is-white select.is-hovered{border-color:#f2f2f2}.select.is-white select:focus,.select.is-white select.is-focused,.select.is-white select:active,.select.is-white select.is-active{box-shadow:0 0 0 0.125em rgba(255,255,255,0.25)}.select.is-black:not(:hover)::after{border-color:#0a0a0a}.select.is-black select{border-color:#0a0a0a}.select.is-black select:hover,.select.is-black select.is-hovered{border-color:#000}.select.is-black select:focus,.select.is-black select.is-focused,.select.is-black select:active,.select.is-black select.is-active{box-shadow:0 0 0 0.125em rgba(10,10,10,0.25)}.select.is-light:not(:hover)::after{border-color:#f5f5f5}.select.is-light select{border-color:#f5f5f5}.select.is-light select:hover,.select.is-light select.is-hovered{border-color:#e8e8e8}.select.is-light select:focus,.select.is-light select.is-focused,.select.is-light select:active,.select.is-light select.is-active{box-shadow:0 0 0 0.125em rgba(245,245,245,0.25)}.select.is-dark:not(:hover)::after,.content kbd.select:not(:hover)::after{border-color:#363636}.select.is-dark select,.content kbd.select select{border-color:#363636}.select.is-dark select:hover,.content kbd.select select:hover,.select.is-dark select.is-hovered,.content kbd.select select.is-hovered{border-color:#292929}.select.is-dark select:focus,.content kbd.select select:focus,.select.is-dark select.is-focused,.content kbd.select select.is-focused,.select.is-dark select:active,.content kbd.select select:active,.select.is-dark select.is-active,.content kbd.select select.is-active{box-shadow:0 0 0 0.125em rgba(54,54,54,0.25)}.select.is-primary:not(:hover)::after,.docstring>section>a.select.docs-sourcelink:not(:hover)::after{border-color:#4eb5de}.select.is-primary select,.docstring>section>a.select.docs-sourcelink select{border-color:#4eb5de}.select.is-primary select:hover,.docstring>section>a.select.docs-sourcelink select:hover,.select.is-primary select.is-hovered,.docstring>section>a.select.docs-sourcelink select.is-hovered{border-color:#39acda}.select.is-primary select:focus,.docstring>section>a.select.docs-sourcelink select:focus,.select.is-primary select.is-focused,.docstring>section>a.select.docs-sourcelink select.is-focused,.select.is-primary select:active,.docstring>section>a.select.docs-sourcelink select:active,.select.is-primary select.is-active,.docstring>section>a.select.docs-sourcelink select.is-active{box-shadow:0 0 0 0.125em rgba(78,181,222,0.25)}.select.is-link:not(:hover)::after{border-color:#2e63b8}.select.is-link select{border-color:#2e63b8}.select.is-link select:hover,.select.is-link select.is-hovered{border-color:#2958a4}.select.is-link select:focus,.select.is-link select.is-focused,.select.is-link select:active,.select.is-link select.is-active{box-shadow:0 0 0 0.125em rgba(46,99,184,0.25)}.select.is-info:not(:hover)::after{border-color:#209cee}.select.is-info select{border-color:#209cee}.select.is-info select:hover,.select.is-info select.is-hovered{border-color:#1190e3}.select.is-info select:focus,.select.is-info select.is-focused,.select.is-info select:active,.select.is-info select.is-active{box-shadow:0 0 0 0.125em rgba(32,156,238,0.25)}.select.is-success:not(:hover)::after{border-color:#22c35b}.select.is-success select{border-color:#22c35b}.select.is-success select:hover,.select.is-success select.is-hovered{border-color:#1ead51}.select.is-success select:focus,.select.is-success select.is-focused,.select.is-success select:active,.select.is-success select.is-active{box-shadow:0 0 0 0.125em rgba(34,195,91,0.25)}.select.is-warning:not(:hover)::after{border-color:#ffdd57}.select.is-warning select{border-color:#ffdd57}.select.is-warning select:hover,.select.is-warning select.is-hovered{border-color:#ffd83e}.select.is-warning select:focus,.select.is-warning select.is-focused,.select.is-warning select:active,.select.is-warning select.is-active{box-shadow:0 0 0 0.125em rgba(255,221,87,0.25)}.select.is-danger:not(:hover)::after{border-color:#da0b00}.select.is-danger select{border-color:#da0b00}.select.is-danger select:hover,.select.is-danger select.is-hovered{border-color:#c10a00}.select.is-danger select:focus,.select.is-danger select.is-focused,.select.is-danger select:active,.select.is-danger select.is-active{box-shadow:0 0 0 0.125em rgba(218,11,0,0.25)}.select.is-small,#documenter .docs-sidebar form.docs-search>input.select{border-radius:2px;font-size:.75rem}.select.is-medium{font-size:1.25rem}.select.is-large{font-size:1.5rem}.select.is-disabled::after{border-color:#6b6b6b !important;opacity:0.5}.select.is-fullwidth{width:100%}.select.is-fullwidth select{width:100%}.select.is-loading::after{margin-top:0;position:absolute;right:.625em;top:0.625em;transform:none}.select.is-loading.is-small:after,#documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}.select.is-loading.is-medium:after{font-size:1.25rem}.select.is-loading.is-large:after{font-size:1.5rem}.file{align-items:stretch;display:flex;justify-content:flex-start;position:relative}.file.is-white .file-cta{background-color:#fff;border-color:transparent;color:#0a0a0a}.file.is-white:hover .file-cta,.file.is-white.is-hovered .file-cta{background-color:#f9f9f9;border-color:transparent;color:#0a0a0a}.file.is-white:focus .file-cta,.file.is-white.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,255,255,0.25);color:#0a0a0a}.file.is-white:active .file-cta,.file.is-white.is-active .file-cta{background-color:#f2f2f2;border-color:transparent;color:#0a0a0a}.file.is-black .file-cta{background-color:#0a0a0a;border-color:transparent;color:#fff}.file.is-black:hover .file-cta,.file.is-black.is-hovered .file-cta{background-color:#040404;border-color:transparent;color:#fff}.file.is-black:focus .file-cta,.file.is-black.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(10,10,10,0.25);color:#fff}.file.is-black:active .file-cta,.file.is-black.is-active .file-cta{background-color:#000;border-color:transparent;color:#fff}.file.is-light .file-cta{background-color:#f5f5f5;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-light:hover .file-cta,.file.is-light.is-hovered .file-cta{background-color:#eee;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-light:focus .file-cta,.file.is-light.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(245,245,245,0.25);color:rgba(0,0,0,0.7)}.file.is-light:active .file-cta,.file.is-light.is-active .file-cta{background-color:#e8e8e8;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-dark .file-cta,.content kbd.file .file-cta{background-color:#363636;border-color:transparent;color:#fff}.file.is-dark:hover .file-cta,.content kbd.file:hover .file-cta,.file.is-dark.is-hovered .file-cta,.content kbd.file.is-hovered .file-cta{background-color:#2f2f2f;border-color:transparent;color:#fff}.file.is-dark:focus .file-cta,.content kbd.file:focus .file-cta,.file.is-dark.is-focused .file-cta,.content kbd.file.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(54,54,54,0.25);color:#fff}.file.is-dark:active .file-cta,.content kbd.file:active .file-cta,.file.is-dark.is-active .file-cta,.content kbd.file.is-active .file-cta{background-color:#292929;border-color:transparent;color:#fff}.file.is-primary .file-cta,.docstring>section>a.file.docs-sourcelink .file-cta{background-color:#4eb5de;border-color:transparent;color:#fff}.file.is-primary:hover .file-cta,.docstring>section>a.file.docs-sourcelink:hover .file-cta,.file.is-primary.is-hovered .file-cta,.docstring>section>a.file.is-hovered.docs-sourcelink .file-cta{background-color:#43b1dc;border-color:transparent;color:#fff}.file.is-primary:focus .file-cta,.docstring>section>a.file.docs-sourcelink:focus .file-cta,.file.is-primary.is-focused .file-cta,.docstring>section>a.file.is-focused.docs-sourcelink .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(78,181,222,0.25);color:#fff}.file.is-primary:active .file-cta,.docstring>section>a.file.docs-sourcelink:active .file-cta,.file.is-primary.is-active .file-cta,.docstring>section>a.file.is-active.docs-sourcelink .file-cta{background-color:#39acda;border-color:transparent;color:#fff}.file.is-link .file-cta{background-color:#2e63b8;border-color:transparent;color:#fff}.file.is-link:hover .file-cta,.file.is-link.is-hovered .file-cta{background-color:#2b5eae;border-color:transparent;color:#fff}.file.is-link:focus .file-cta,.file.is-link.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(46,99,184,0.25);color:#fff}.file.is-link:active .file-cta,.file.is-link.is-active .file-cta{background-color:#2958a4;border-color:transparent;color:#fff}.file.is-info .file-cta{background-color:#209cee;border-color:transparent;color:#fff}.file.is-info:hover .file-cta,.file.is-info.is-hovered .file-cta{background-color:#1497ed;border-color:transparent;color:#fff}.file.is-info:focus .file-cta,.file.is-info.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(32,156,238,0.25);color:#fff}.file.is-info:active .file-cta,.file.is-info.is-active .file-cta{background-color:#1190e3;border-color:transparent;color:#fff}.file.is-success .file-cta{background-color:#22c35b;border-color:transparent;color:#fff}.file.is-success:hover .file-cta,.file.is-success.is-hovered .file-cta{background-color:#20b856;border-color:transparent;color:#fff}.file.is-success:focus .file-cta,.file.is-success.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(34,195,91,0.25);color:#fff}.file.is-success:active .file-cta,.file.is-success.is-active .file-cta{background-color:#1ead51;border-color:transparent;color:#fff}.file.is-warning .file-cta{background-color:#ffdd57;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-warning:hover .file-cta,.file.is-warning.is-hovered .file-cta{background-color:#ffda4a;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-warning:focus .file-cta,.file.is-warning.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(255,221,87,0.25);color:rgba(0,0,0,0.7)}.file.is-warning:active .file-cta,.file.is-warning.is-active .file-cta{background-color:#ffd83e;border-color:transparent;color:rgba(0,0,0,0.7)}.file.is-danger .file-cta{background-color:#da0b00;border-color:transparent;color:#fff}.file.is-danger:hover .file-cta,.file.is-danger.is-hovered .file-cta{background-color:#cd0a00;border-color:transparent;color:#fff}.file.is-danger:focus .file-cta,.file.is-danger.is-focused .file-cta{border-color:transparent;box-shadow:0 0 0.5em rgba(218,11,0,0.25);color:#fff}.file.is-danger:active .file-cta,.file.is-danger.is-active .file-cta{background-color:#c10a00;border-color:transparent;color:#fff}.file.is-small,#documenter .docs-sidebar form.docs-search>input.file{font-size:.75rem}.file.is-normal{font-size:1rem}.file.is-medium{font-size:1.25rem}.file.is-medium .file-icon .fa{font-size:21px}.file.is-large{font-size:1.5rem}.file.is-large .file-icon .fa{font-size:28px}.file.has-name .file-cta{border-bottom-right-radius:0;border-top-right-radius:0}.file.has-name .file-name{border-bottom-left-radius:0;border-top-left-radius:0}.file.has-name.is-empty .file-cta{border-radius:4px}.file.has-name.is-empty .file-name{display:none}.file.is-boxed .file-label{flex-direction:column}.file.is-boxed .file-cta{flex-direction:column;height:auto;padding:1em 3em}.file.is-boxed .file-name{border-width:0 1px 1px}.file.is-boxed .file-icon{height:1.5em;width:1.5em}.file.is-boxed .file-icon .fa{font-size:21px}.file.is-boxed.is-small .file-icon .fa,#documenter .docs-sidebar form.docs-search>input.is-boxed .file-icon .fa{font-size:14px}.file.is-boxed.is-medium .file-icon .fa{font-size:28px}.file.is-boxed.is-large .file-icon .fa{font-size:35px}.file.is-boxed.has-name .file-cta{border-radius:4px 4px 0 0}.file.is-boxed.has-name .file-name{border-radius:0 0 4px 4px;border-width:0 1px 1px}.file.is-centered{justify-content:center}.file.is-fullwidth .file-label{width:100%}.file.is-fullwidth .file-name{flex-grow:1;max-width:none}.file.is-right{justify-content:flex-end}.file.is-right .file-cta{border-radius:0 4px 4px 0}.file.is-right .file-name{border-radius:4px 0 0 4px;border-width:1px 0 1px 1px;order:-1}.file-label{align-items:stretch;display:flex;cursor:pointer;justify-content:flex-start;overflow:hidden;position:relative}.file-label:hover .file-cta{background-color:#eee;color:#222}.file-label:hover .file-name{border-color:#d5d5d5}.file-label:active .file-cta{background-color:#e8e8e8;color:#222}.file-label:active .file-name{border-color:#cfcfcf}.file-input{height:100%;left:0;opacity:0;outline:none;position:absolute;top:0;width:100%}.file-cta,.file-name{border-color:#dbdbdb;border-radius:4px;font-size:1em;padding-left:1em;padding-right:1em;white-space:nowrap}.file-cta{background-color:#f5f5f5;color:#222}.file-name{border-color:#dbdbdb;border-style:solid;border-width:1px 1px 1px 0;display:block;max-width:16em;overflow:hidden;text-align:inherit;text-overflow:ellipsis}.file-icon{align-items:center;display:flex;height:1em;justify-content:center;margin-right:.5em;width:1em}.file-icon .fa{font-size:14px}.label{color:#222;display:block;font-size:1rem;font-weight:700}.label:not(:last-child){margin-bottom:0.5em}.label.is-small,#documenter .docs-sidebar form.docs-search>input.label{font-size:.75rem}.label.is-medium{font-size:1.25rem}.label.is-large{font-size:1.5rem}.help{display:block;font-size:.75rem;margin-top:0.25rem}.help.is-white{color:#fff}.help.is-black{color:#0a0a0a}.help.is-light{color:#f5f5f5}.help.is-dark,.content kbd.help{color:#363636}.help.is-primary,.docstring>section>a.help.docs-sourcelink{color:#4eb5de}.help.is-link{color:#2e63b8}.help.is-info{color:#209cee}.help.is-success{color:#22c35b}.help.is-warning{color:#ffdd57}.help.is-danger{color:#da0b00}.field:not(:last-child){margin-bottom:0.75rem}.field.has-addons{display:flex;justify-content:flex-start}.field.has-addons .control:not(:last-child){margin-right:-1px}.field.has-addons .control:not(:first-child):not(:last-child) .button,.field.has-addons .control:not(:first-child):not(:last-child) .input,.field.has-addons .control:not(:first-child):not(:last-child) #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .field.has-addons .control:not(:first-child):not(:last-child) form.docs-search>input,.field.has-addons .control:not(:first-child):not(:last-child) .select select{border-radius:0}.field.has-addons .control:first-child:not(:only-child) .button,.field.has-addons .control:first-child:not(:only-child) .input,.field.has-addons .control:first-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .field.has-addons .control:first-child:not(:only-child) form.docs-search>input,.field.has-addons .control:first-child:not(:only-child) .select select{border-bottom-right-radius:0;border-top-right-radius:0}.field.has-addons .control:last-child:not(:only-child) .button,.field.has-addons .control:last-child:not(:only-child) .input,.field.has-addons .control:last-child:not(:only-child) #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .field.has-addons .control:last-child:not(:only-child) form.docs-search>input,.field.has-addons .control:last-child:not(:only-child) .select select{border-bottom-left-radius:0;border-top-left-radius:0}.field.has-addons .control .button:not([disabled]):hover,.field.has-addons .control .button.is-hovered:not([disabled]),.field.has-addons .control .input:not([disabled]):hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):hover,.field.has-addons .control .input.is-hovered:not([disabled]),.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-hovered:not([disabled]),#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-hovered:not([disabled]),.field.has-addons .control .select select:not([disabled]):hover,.field.has-addons .control .select select.is-hovered:not([disabled]){z-index:2}.field.has-addons .control .button:not([disabled]):focus,.field.has-addons .control .button.is-focused:not([disabled]),.field.has-addons .control .button:not([disabled]):active,.field.has-addons .control .button.is-active:not([disabled]),.field.has-addons .control .input:not([disabled]):focus,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus,.field.has-addons .control .input.is-focused:not([disabled]),.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]),#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]),.field.has-addons .control .input:not([disabled]):active,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active,.field.has-addons .control .input.is-active:not([disabled]),.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]),#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]),.field.has-addons .control .select select:not([disabled]):focus,.field.has-addons .control .select select.is-focused:not([disabled]),.field.has-addons .control .select select:not([disabled]):active,.field.has-addons .control .select select.is-active:not([disabled]){z-index:3}.field.has-addons .control .button:not([disabled]):focus:hover,.field.has-addons .control .button.is-focused:not([disabled]):hover,.field.has-addons .control .button:not([disabled]):active:hover,.field.has-addons .control .button.is-active:not([disabled]):hover,.field.has-addons .control .input:not([disabled]):focus:hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):focus:hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):focus:hover,.field.has-addons .control .input.is-focused:not([disabled]):hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-focused:not([disabled]):hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-focused:not([disabled]):hover,.field.has-addons .control .input:not([disabled]):active:hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input:not([disabled]):active:hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input:not([disabled]):active:hover,.field.has-addons .control .input.is-active:not([disabled]):hover,.field.has-addons .control #documenter .docs-sidebar form.docs-search>input.is-active:not([disabled]):hover,#documenter .docs-sidebar .field.has-addons .control form.docs-search>input.is-active:not([disabled]):hover,.field.has-addons .control .select select:not([disabled]):focus:hover,.field.has-addons .control .select select.is-focused:not([disabled]):hover,.field.has-addons .control .select select:not([disabled]):active:hover,.field.has-addons .control .select select.is-active:not([disabled]):hover{z-index:4}.field.has-addons .control.is-expanded{flex-grow:1;flex-shrink:1}.field.has-addons.has-addons-centered{justify-content:center}.field.has-addons.has-addons-right{justify-content:flex-end}.field.has-addons.has-addons-fullwidth .control{flex-grow:1;flex-shrink:0}.field.is-grouped{display:flex;justify-content:flex-start}.field.is-grouped>.control{flex-shrink:0}.field.is-grouped>.control:not(:last-child){margin-bottom:0;margin-right:.75rem}.field.is-grouped>.control.is-expanded{flex-grow:1;flex-shrink:1}.field.is-grouped.is-grouped-centered{justify-content:center}.field.is-grouped.is-grouped-right{justify-content:flex-end}.field.is-grouped.is-grouped-multiline{flex-wrap:wrap}.field.is-grouped.is-grouped-multiline>.control:last-child,.field.is-grouped.is-grouped-multiline>.control:not(:last-child){margin-bottom:0.75rem}.field.is-grouped.is-grouped-multiline:last-child{margin-bottom:-0.75rem}.field.is-grouped.is-grouped-multiline:not(:last-child){margin-bottom:0}@media screen and (min-width: 769px),print{.field.is-horizontal{display:flex}}.field-label .label{font-size:inherit}@media screen and (max-width: 768px){.field-label{margin-bottom:0.5rem}}@media screen and (min-width: 769px),print{.field-label{flex-basis:0;flex-grow:1;flex-shrink:0;margin-right:1.5rem;text-align:right}.field-label.is-small,#documenter .docs-sidebar form.docs-search>input.field-label{font-size:.75rem;padding-top:0.375em}.field-label.is-normal{padding-top:0.375em}.field-label.is-medium{font-size:1.25rem;padding-top:0.375em}.field-label.is-large{font-size:1.5rem;padding-top:0.375em}}.field-body .field .field{margin-bottom:0}@media screen and (min-width: 769px),print{.field-body{display:flex;flex-basis:0;flex-grow:5;flex-shrink:1}.field-body .field{margin-bottom:0}.field-body>.field{flex-shrink:1}.field-body>.field:not(.is-narrow){flex-grow:1}.field-body>.field:not(:last-child){margin-right:.75rem}}.control{box-sizing:border-box;clear:both;font-size:1rem;position:relative;text-align:inherit}.control.has-icons-left .input:focus~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input:focus~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input:focus~.icon,.control.has-icons-left .select:focus~.icon,.control.has-icons-right .input:focus~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input:focus~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input:focus~.icon,.control.has-icons-right .select:focus~.icon{color:#222}.control.has-icons-left .input.is-small~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input~.icon,.control.has-icons-left .select.is-small~.icon,.control.has-icons-right .input.is-small~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input~.icon,.control.has-icons-right .select.is-small~.icon{font-size:.75rem}.control.has-icons-left .input.is-medium~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-medium~.icon,.control.has-icons-left .select.is-medium~.icon,.control.has-icons-right .input.is-medium~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-medium~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-medium~.icon,.control.has-icons-right .select.is-medium~.icon{font-size:1.25rem}.control.has-icons-left .input.is-large~.icon,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input.is-large~.icon,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input.is-large~.icon,.control.has-icons-left .select.is-large~.icon,.control.has-icons-right .input.is-large~.icon,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input.is-large~.icon,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input.is-large~.icon,.control.has-icons-right .select.is-large~.icon{font-size:1.5rem}.control.has-icons-left .icon,.control.has-icons-right .icon{color:#dbdbdb;height:2.5em;pointer-events:none;position:absolute;top:0;width:2.5em;z-index:4}.control.has-icons-left .input,.control.has-icons-left #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .control.has-icons-left form.docs-search>input,.control.has-icons-left .select select{padding-left:2.5em}.control.has-icons-left .icon.is-left{left:0}.control.has-icons-right .input,.control.has-icons-right #documenter .docs-sidebar form.docs-search>input,#documenter .docs-sidebar .control.has-icons-right form.docs-search>input,.control.has-icons-right .select select{padding-right:2.5em}.control.has-icons-right .icon.is-right{right:0}.control.is-loading::after{position:absolute !important;right:.625em;top:0.625em;z-index:4}.control.is-loading.is-small:after,#documenter .docs-sidebar form.docs-search>input.is-loading:after{font-size:.75rem}.control.is-loading.is-medium:after{font-size:1.25rem}.control.is-loading.is-large:after{font-size:1.5rem}.breadcrumb{font-size:1rem;white-space:nowrap}.breadcrumb a{align-items:center;color:#2e63b8;display:flex;justify-content:center;padding:0 .75em}.breadcrumb a:hover{color:#363636}.breadcrumb li{align-items:center;display:flex}.breadcrumb li:first-child a{padding-left:0}.breadcrumb li.is-active a{color:#222;cursor:default;pointer-events:none}.breadcrumb li+li::before{color:#b5b5b5;content:"\0002f"}.breadcrumb ul,.breadcrumb ol{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:flex-start}.breadcrumb .icon:first-child{margin-right:.5em}.breadcrumb .icon:last-child{margin-left:.5em}.breadcrumb.is-centered ol,.breadcrumb.is-centered ul{justify-content:center}.breadcrumb.is-right ol,.breadcrumb.is-right ul{justify-content:flex-end}.breadcrumb.is-small,#documenter .docs-sidebar form.docs-search>input.breadcrumb{font-size:.75rem}.breadcrumb.is-medium{font-size:1.25rem}.breadcrumb.is-large{font-size:1.5rem}.breadcrumb.has-arrow-separator li+li::before{content:"\02192"}.breadcrumb.has-bullet-separator li+li::before{content:"\02022"}.breadcrumb.has-dot-separator li+li::before{content:"\000b7"}.breadcrumb.has-succeeds-separator li+li::before{content:"\0227B"}.card{background-color:#fff;border-radius:.25rem;box-shadow:#bbb;color:#222;max-width:100%;position:relative}.card-footer:first-child,.card-content:first-child,.card-header:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-footer:last-child,.card-content:last-child,.card-header:last-child{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.card-header{background-color:rgba(0,0,0,0);align-items:stretch;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);display:flex}.card-header-title{align-items:center;color:#222;display:flex;flex-grow:1;font-weight:700;padding:0.75rem 1rem}.card-header-title.is-centered{justify-content:center}.card-header-icon{-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;color:currentColor;font-family:inherit;font-size:1em;margin:0;padding:0;align-items:center;cursor:pointer;display:flex;justify-content:center;padding:0.75rem 1rem}.card-image{display:block;position:relative}.card-image:first-child img{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-image:last-child img{border-bottom-left-radius:.25rem;border-bottom-right-radius:.25rem}.card-content{background-color:rgba(0,0,0,0);padding:1.5rem}.card-footer{background-color:rgba(0,0,0,0);border-top:1px solid #ededed;align-items:stretch;display:flex}.card-footer-item{align-items:center;display:flex;flex-basis:0;flex-grow:1;flex-shrink:0;justify-content:center;padding:.75rem}.card-footer-item:not(:last-child){border-right:1px solid #ededed}.card .media:not(:last-child){margin-bottom:1.5rem}.dropdown{display:inline-flex;position:relative;vertical-align:top}.dropdown.is-active .dropdown-menu,.dropdown.is-hoverable:hover .dropdown-menu{display:block}.dropdown.is-right .dropdown-menu{left:auto;right:0}.dropdown.is-up .dropdown-menu{bottom:100%;padding-bottom:4px;padding-top:initial;top:auto}.dropdown-menu{display:none;left:0;min-width:12rem;padding-top:4px;position:absolute;top:100%;z-index:20}.dropdown-content{background-color:#fff;border-radius:4px;box-shadow:#bbb;padding-bottom:.5rem;padding-top:.5rem}.dropdown-item{color:#222;display:block;font-size:0.875rem;line-height:1.5;padding:0.375rem 1rem;position:relative}a.dropdown-item,button.dropdown-item{padding-right:3rem;text-align:inherit;white-space:nowrap;width:100%}a.dropdown-item:hover,button.dropdown-item:hover{background-color:#f5f5f5;color:#0a0a0a}a.dropdown-item.is-active,button.dropdown-item.is-active{background-color:#2e63b8;color:#fff}.dropdown-divider{background-color:#ededed;border:none;display:block;height:1px;margin:0.5rem 0}.level{align-items:center;justify-content:space-between}.level code{border-radius:4px}.level img{display:inline-block;vertical-align:top}.level.is-mobile{display:flex}.level.is-mobile .level-left,.level.is-mobile .level-right{display:flex}.level.is-mobile .level-left+.level-right{margin-top:0}.level.is-mobile .level-item:not(:last-child){margin-bottom:0;margin-right:.75rem}.level.is-mobile .level-item:not(.is-narrow){flex-grow:1}@media screen and (min-width: 769px),print{.level{display:flex}.level>.level-item:not(.is-narrow){flex-grow:1}}.level-item{align-items:center;display:flex;flex-basis:auto;flex-grow:0;flex-shrink:0;justify-content:center}.level-item .title,.level-item .subtitle{margin-bottom:0}@media screen and (max-width: 768px){.level-item:not(:last-child){margin-bottom:.75rem}}.level-left,.level-right{flex-basis:auto;flex-grow:0;flex-shrink:0}.level-left .level-item.is-flexible,.level-right .level-item.is-flexible{flex-grow:1}@media screen and (min-width: 769px),print{.level-left .level-item:not(:last-child),.level-right .level-item:not(:last-child){margin-right:.75rem}}.level-left{align-items:center;justify-content:flex-start}@media screen and (max-width: 768px){.level-left+.level-right{margin-top:1.5rem}}@media screen and (min-width: 769px),print{.level-left{display:flex}}.level-right{align-items:center;justify-content:flex-end}@media screen and (min-width: 769px),print{.level-right{display:flex}}.media{align-items:flex-start;display:flex;text-align:inherit}.media .content:not(:last-child){margin-bottom:.75rem}.media .media{border-top:1px solid rgba(219,219,219,0.5);display:flex;padding-top:.75rem}.media .media .content:not(:last-child),.media .media .control:not(:last-child){margin-bottom:.5rem}.media .media .media{padding-top:.5rem}.media .media .media+.media{margin-top:.5rem}.media+.media{border-top:1px solid rgba(219,219,219,0.5);margin-top:1rem;padding-top:1rem}.media.is-large+.media{margin-top:1.5rem;padding-top:1.5rem}.media-left,.media-right{flex-basis:auto;flex-grow:0;flex-shrink:0}.media-left{margin-right:1rem}.media-right{margin-left:1rem}.media-content{flex-basis:auto;flex-grow:1;flex-shrink:1;text-align:inherit}@media screen and (max-width: 768px){.media-content{overflow-x:auto}}.menu{font-size:1rem}.menu.is-small,#documenter .docs-sidebar form.docs-search>input.menu{font-size:.75rem}.menu.is-medium{font-size:1.25rem}.menu.is-large{font-size:1.5rem}.menu-list{line-height:1.25}.menu-list a{border-radius:2px;color:#222;display:block;padding:0.5em 0.75em}.menu-list a:hover{background-color:#f5f5f5;color:#222}.menu-list a.is-active{background-color:#2e63b8;color:#fff}.menu-list li ul{border-left:1px solid #dbdbdb;margin:.75em;padding-left:.75em}.menu-label{color:#6b6b6b;font-size:.75em;letter-spacing:.1em;text-transform:uppercase}.menu-label:not(:first-child){margin-top:1em}.menu-label:not(:last-child){margin-bottom:1em}.message{background-color:#f5f5f5;border-radius:4px;font-size:1rem}.message strong{color:currentColor}.message a:not(.button):not(.tag):not(.dropdown-item){color:currentColor;text-decoration:underline}.message.is-small,#documenter .docs-sidebar form.docs-search>input.message{font-size:.75rem}.message.is-medium{font-size:1.25rem}.message.is-large{font-size:1.5rem}.message.is-white{background-color:#fff}.message.is-white .message-header{background-color:#fff;color:#0a0a0a}.message.is-white .message-body{border-color:#fff}.message.is-black{background-color:#fafafa}.message.is-black .message-header{background-color:#0a0a0a;color:#fff}.message.is-black .message-body{border-color:#0a0a0a}.message.is-light{background-color:#fafafa}.message.is-light .message-header{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.message.is-light .message-body{border-color:#f5f5f5}.message.is-dark,.content kbd.message{background-color:#fafafa}.message.is-dark .message-header,.content kbd.message .message-header{background-color:#363636;color:#fff}.message.is-dark .message-body,.content kbd.message .message-body{border-color:#363636}.message.is-primary,.docstring>section>a.message.docs-sourcelink{background-color:#eef8fc}.message.is-primary .message-header,.docstring>section>a.message.docs-sourcelink .message-header{background-color:#4eb5de;color:#fff}.message.is-primary .message-body,.docstring>section>a.message.docs-sourcelink .message-body{border-color:#4eb5de;color:#1a6d8e}.message.is-link{background-color:#eff3fb}.message.is-link .message-header{background-color:#2e63b8;color:#fff}.message.is-link .message-body{border-color:#2e63b8;color:#3169c4}.message.is-info{background-color:#ecf7fe}.message.is-info .message-header{background-color:#209cee;color:#fff}.message.is-info .message-body{border-color:#209cee;color:#0e72b4}.message.is-success{background-color:#eefcf3}.message.is-success .message-header{background-color:#22c35b;color:#fff}.message.is-success .message-body{border-color:#22c35b;color:#198f43}.message.is-warning{background-color:#fffbeb}.message.is-warning .message-header{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.message.is-warning .message-body{border-color:#ffdd57;color:#947600}.message.is-danger{background-color:#ffeceb}.message.is-danger .message-header{background-color:#da0b00;color:#fff}.message.is-danger .message-body{border-color:#da0b00;color:#f50c00}.message-header{align-items:center;background-color:#222;border-radius:4px 4px 0 0;color:#fff;display:flex;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.75em 1em;position:relative}.message-header .delete{flex-grow:0;flex-shrink:0;margin-left:.75em}.message-header+.message-body{border-width:0;border-top-left-radius:0;border-top-right-radius:0}.message-body{border-color:#dbdbdb;border-radius:4px;border-style:solid;border-width:0 0 0 4px;color:#222;padding:1.25em 1.5em}.message-body code,.message-body pre{background-color:#fff}.message-body pre code{background-color:rgba(0,0,0,0)}.modal{align-items:center;display:none;flex-direction:column;justify-content:center;overflow:hidden;position:fixed;z-index:40}.modal.is-active{display:flex}.modal-background{background-color:rgba(10,10,10,0.86)}.modal-content,.modal-card{margin:0 20px;max-height:calc(100vh - 160px);overflow:auto;position:relative;width:100%}@media screen and (min-width: 769px){.modal-content,.modal-card{margin:0 auto;max-height:calc(100vh - 40px);width:640px}}.modal-close{background:none;height:40px;position:fixed;right:20px;top:20px;width:40px}.modal-card{display:flex;flex-direction:column;max-height:calc(100vh - 40px);overflow:hidden;-ms-overflow-y:visible}.modal-card-head,.modal-card-foot{align-items:center;background-color:#f5f5f5;display:flex;flex-shrink:0;justify-content:flex-start;padding:20px;position:relative}.modal-card-head{border-bottom:1px solid #dbdbdb;border-top-left-radius:6px;border-top-right-radius:6px}.modal-card-title{color:#222;flex-grow:1;flex-shrink:0;font-size:1.5rem;line-height:1}.modal-card-foot{border-bottom-left-radius:6px;border-bottom-right-radius:6px;border-top:1px solid #dbdbdb}.modal-card-foot .button:not(:last-child){margin-right:.5em}.modal-card-body{-webkit-overflow-scrolling:touch;background-color:#fff;flex-grow:1;flex-shrink:1;overflow:auto;padding:20px}.navbar{background-color:#fff;min-height:3.25rem;position:relative;z-index:30}.navbar.is-white{background-color:#fff;color:#0a0a0a}.navbar.is-white .navbar-brand>.navbar-item,.navbar.is-white .navbar-brand .navbar-link{color:#0a0a0a}.navbar.is-white .navbar-brand>a.navbar-item:focus,.navbar.is-white .navbar-brand>a.navbar-item:hover,.navbar.is-white .navbar-brand>a.navbar-item.is-active,.navbar.is-white .navbar-brand .navbar-link:focus,.navbar.is-white .navbar-brand .navbar-link:hover,.navbar.is-white .navbar-brand .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-brand .navbar-link::after{border-color:#0a0a0a}.navbar.is-white .navbar-burger{color:#0a0a0a}@media screen and (min-width: 1056px){.navbar.is-white .navbar-start>.navbar-item,.navbar.is-white .navbar-start .navbar-link,.navbar.is-white .navbar-end>.navbar-item,.navbar.is-white .navbar-end .navbar-link{color:#0a0a0a}.navbar.is-white .navbar-start>a.navbar-item:focus,.navbar.is-white .navbar-start>a.navbar-item:hover,.navbar.is-white .navbar-start>a.navbar-item.is-active,.navbar.is-white .navbar-start .navbar-link:focus,.navbar.is-white .navbar-start .navbar-link:hover,.navbar.is-white .navbar-start .navbar-link.is-active,.navbar.is-white .navbar-end>a.navbar-item:focus,.navbar.is-white .navbar-end>a.navbar-item:hover,.navbar.is-white .navbar-end>a.navbar-item.is-active,.navbar.is-white .navbar-end .navbar-link:focus,.navbar.is-white .navbar-end .navbar-link:hover,.navbar.is-white .navbar-end .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-start .navbar-link::after,.navbar.is-white .navbar-end .navbar-link::after{border-color:#0a0a0a}.navbar.is-white .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-white .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link{background-color:#f2f2f2;color:#0a0a0a}.navbar.is-white .navbar-dropdown a.navbar-item.is-active{background-color:#fff;color:#0a0a0a}}.navbar.is-black{background-color:#0a0a0a;color:#fff}.navbar.is-black .navbar-brand>.navbar-item,.navbar.is-black .navbar-brand .navbar-link{color:#fff}.navbar.is-black .navbar-brand>a.navbar-item:focus,.navbar.is-black .navbar-brand>a.navbar-item:hover,.navbar.is-black .navbar-brand>a.navbar-item.is-active,.navbar.is-black .navbar-brand .navbar-link:focus,.navbar.is-black .navbar-brand .navbar-link:hover,.navbar.is-black .navbar-brand .navbar-link.is-active{background-color:#000;color:#fff}.navbar.is-black .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-black .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-black .navbar-start>.navbar-item,.navbar.is-black .navbar-start .navbar-link,.navbar.is-black .navbar-end>.navbar-item,.navbar.is-black .navbar-end .navbar-link{color:#fff}.navbar.is-black .navbar-start>a.navbar-item:focus,.navbar.is-black .navbar-start>a.navbar-item:hover,.navbar.is-black .navbar-start>a.navbar-item.is-active,.navbar.is-black .navbar-start .navbar-link:focus,.navbar.is-black .navbar-start .navbar-link:hover,.navbar.is-black .navbar-start .navbar-link.is-active,.navbar.is-black .navbar-end>a.navbar-item:focus,.navbar.is-black .navbar-end>a.navbar-item:hover,.navbar.is-black .navbar-end>a.navbar-item.is-active,.navbar.is-black .navbar-end .navbar-link:focus,.navbar.is-black .navbar-end .navbar-link:hover,.navbar.is-black .navbar-end .navbar-link.is-active{background-color:#000;color:#fff}.navbar.is-black .navbar-start .navbar-link::after,.navbar.is-black .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-black .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-black .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link{background-color:#000;color:#fff}.navbar.is-black .navbar-dropdown a.navbar-item.is-active{background-color:#0a0a0a;color:#fff}}.navbar.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-brand>.navbar-item,.navbar.is-light .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-brand>a.navbar-item:focus,.navbar.is-light .navbar-brand>a.navbar-item:hover,.navbar.is-light .navbar-brand>a.navbar-item.is-active,.navbar.is-light .navbar-brand .navbar-link:focus,.navbar.is-light .navbar-brand .navbar-link:hover,.navbar.is-light .navbar-brand .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){.navbar.is-light .navbar-start>.navbar-item,.navbar.is-light .navbar-start .navbar-link,.navbar.is-light .navbar-end>.navbar-item,.navbar.is-light .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-start>a.navbar-item:focus,.navbar.is-light .navbar-start>a.navbar-item:hover,.navbar.is-light .navbar-start>a.navbar-item.is-active,.navbar.is-light .navbar-start .navbar-link:focus,.navbar.is-light .navbar-start .navbar-link:hover,.navbar.is-light .navbar-start .navbar-link.is-active,.navbar.is-light .navbar-end>a.navbar-item:focus,.navbar.is-light .navbar-end>a.navbar-item:hover,.navbar.is-light .navbar-end>a.navbar-item.is-active,.navbar.is-light .navbar-end .navbar-link:focus,.navbar.is-light .navbar-end .navbar-link:hover,.navbar.is-light .navbar-end .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-start .navbar-link::after,.navbar.is-light .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-light .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.navbar.is-light .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}}.navbar.is-dark,.content kbd.navbar{background-color:#363636;color:#fff}.navbar.is-dark .navbar-brand>.navbar-item,.content kbd.navbar .navbar-brand>.navbar-item,.navbar.is-dark .navbar-brand .navbar-link,.content kbd.navbar .navbar-brand .navbar-link{color:#fff}.navbar.is-dark .navbar-brand>a.navbar-item:focus,.content kbd.navbar .navbar-brand>a.navbar-item:focus,.navbar.is-dark .navbar-brand>a.navbar-item:hover,.content kbd.navbar .navbar-brand>a.navbar-item:hover,.navbar.is-dark .navbar-brand>a.navbar-item.is-active,.content kbd.navbar .navbar-brand>a.navbar-item.is-active,.navbar.is-dark .navbar-brand .navbar-link:focus,.content kbd.navbar .navbar-brand .navbar-link:focus,.navbar.is-dark .navbar-brand .navbar-link:hover,.content kbd.navbar .navbar-brand .navbar-link:hover,.navbar.is-dark .navbar-brand .navbar-link.is-active,.content kbd.navbar .navbar-brand .navbar-link.is-active{background-color:#292929;color:#fff}.navbar.is-dark .navbar-brand .navbar-link::after,.content kbd.navbar .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-dark .navbar-burger,.content kbd.navbar .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-dark .navbar-start>.navbar-item,.content kbd.navbar .navbar-start>.navbar-item,.navbar.is-dark .navbar-start .navbar-link,.content kbd.navbar .navbar-start .navbar-link,.navbar.is-dark .navbar-end>.navbar-item,.content kbd.navbar .navbar-end>.navbar-item,.navbar.is-dark .navbar-end .navbar-link,.content kbd.navbar .navbar-end .navbar-link{color:#fff}.navbar.is-dark .navbar-start>a.navbar-item:focus,.content kbd.navbar .navbar-start>a.navbar-item:focus,.navbar.is-dark .navbar-start>a.navbar-item:hover,.content kbd.navbar .navbar-start>a.navbar-item:hover,.navbar.is-dark .navbar-start>a.navbar-item.is-active,.content kbd.navbar .navbar-start>a.navbar-item.is-active,.navbar.is-dark .navbar-start .navbar-link:focus,.content kbd.navbar .navbar-start .navbar-link:focus,.navbar.is-dark .navbar-start .navbar-link:hover,.content kbd.navbar .navbar-start .navbar-link:hover,.navbar.is-dark .navbar-start .navbar-link.is-active,.content kbd.navbar .navbar-start .navbar-link.is-active,.navbar.is-dark .navbar-end>a.navbar-item:focus,.content kbd.navbar .navbar-end>a.navbar-item:focus,.navbar.is-dark .navbar-end>a.navbar-item:hover,.content kbd.navbar .navbar-end>a.navbar-item:hover,.navbar.is-dark .navbar-end>a.navbar-item.is-active,.content kbd.navbar .navbar-end>a.navbar-item.is-active,.navbar.is-dark .navbar-end .navbar-link:focus,.content kbd.navbar .navbar-end .navbar-link:focus,.navbar.is-dark .navbar-end .navbar-link:hover,.content kbd.navbar .navbar-end .navbar-link:hover,.navbar.is-dark .navbar-end .navbar-link.is-active,.content kbd.navbar .navbar-end .navbar-link.is-active{background-color:#292929;color:#fff}.navbar.is-dark .navbar-start .navbar-link::after,.content kbd.navbar .navbar-start .navbar-link::after,.navbar.is-dark .navbar-end .navbar-link::after,.content kbd.navbar .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-dark .navbar-item.has-dropdown:focus .navbar-link,.content kbd.navbar .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link,.content kbd.navbar .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link,.content kbd.navbar .navbar-item.has-dropdown.is-active .navbar-link{background-color:#292929;color:#fff}.navbar.is-dark .navbar-dropdown a.navbar-item.is-active,.content kbd.navbar .navbar-dropdown a.navbar-item.is-active{background-color:#363636;color:#fff}}.navbar.is-primary,.docstring>section>a.navbar.docs-sourcelink{background-color:#4eb5de;color:#fff}.navbar.is-primary .navbar-brand>.navbar-item,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>.navbar-item,.navbar.is-primary .navbar-brand .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link{color:#fff}.navbar.is-primary .navbar-brand>a.navbar-item:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:focus,.navbar.is-primary .navbar-brand>a.navbar-item:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item:hover,.navbar.is-primary .navbar-brand>a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-brand>a.navbar-item.is-active,.navbar.is-primary .navbar-brand .navbar-link:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:focus,.navbar.is-primary .navbar-brand .navbar-link:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link:hover,.navbar.is-primary .navbar-brand .navbar-link.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link.is-active{background-color:#39acda;color:#fff}.navbar.is-primary .navbar-brand .navbar-link::after,.docstring>section>a.navbar.docs-sourcelink .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-primary .navbar-burger,.docstring>section>a.navbar.docs-sourcelink .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-primary .navbar-start>.navbar-item,.docstring>section>a.navbar.docs-sourcelink .navbar-start>.navbar-item,.navbar.is-primary .navbar-start .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link,.navbar.is-primary .navbar-end>.navbar-item,.docstring>section>a.navbar.docs-sourcelink .navbar-end>.navbar-item,.navbar.is-primary .navbar-end .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link{color:#fff}.navbar.is-primary .navbar-start>a.navbar-item:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:focus,.navbar.is-primary .navbar-start>a.navbar-item:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item:hover,.navbar.is-primary .navbar-start>a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-start>a.navbar-item.is-active,.navbar.is-primary .navbar-start .navbar-link:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:focus,.navbar.is-primary .navbar-start .navbar-link:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link:hover,.navbar.is-primary .navbar-start .navbar-link.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link.is-active,.navbar.is-primary .navbar-end>a.navbar-item:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:focus,.navbar.is-primary .navbar-end>a.navbar-item:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item:hover,.navbar.is-primary .navbar-end>a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-end>a.navbar-item.is-active,.navbar.is-primary .navbar-end .navbar-link:focus,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:focus,.navbar.is-primary .navbar-end .navbar-link:hover,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link:hover,.navbar.is-primary .navbar-end .navbar-link.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link.is-active{background-color:#39acda;color:#fff}.navbar.is-primary .navbar-start .navbar-link::after,.docstring>section>a.navbar.docs-sourcelink .navbar-start .navbar-link::after,.navbar.is-primary .navbar-end .navbar-link::after,.docstring>section>a.navbar.docs-sourcelink .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link,.docstring>section>a.navbar.docs-sourcelink .navbar-item.has-dropdown.is-active .navbar-link{background-color:#39acda;color:#fff}.navbar.is-primary .navbar-dropdown a.navbar-item.is-active,.docstring>section>a.navbar.docs-sourcelink .navbar-dropdown a.navbar-item.is-active{background-color:#4eb5de;color:#fff}}.navbar.is-link{background-color:#2e63b8;color:#fff}.navbar.is-link .navbar-brand>.navbar-item,.navbar.is-link .navbar-brand .navbar-link{color:#fff}.navbar.is-link .navbar-brand>a.navbar-item:focus,.navbar.is-link .navbar-brand>a.navbar-item:hover,.navbar.is-link .navbar-brand>a.navbar-item.is-active,.navbar.is-link .navbar-brand .navbar-link:focus,.navbar.is-link .navbar-brand .navbar-link:hover,.navbar.is-link .navbar-brand .navbar-link.is-active{background-color:#2958a4;color:#fff}.navbar.is-link .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-link .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-link .navbar-start>.navbar-item,.navbar.is-link .navbar-start .navbar-link,.navbar.is-link .navbar-end>.navbar-item,.navbar.is-link .navbar-end .navbar-link{color:#fff}.navbar.is-link .navbar-start>a.navbar-item:focus,.navbar.is-link .navbar-start>a.navbar-item:hover,.navbar.is-link .navbar-start>a.navbar-item.is-active,.navbar.is-link .navbar-start .navbar-link:focus,.navbar.is-link .navbar-start .navbar-link:hover,.navbar.is-link .navbar-start .navbar-link.is-active,.navbar.is-link .navbar-end>a.navbar-item:focus,.navbar.is-link .navbar-end>a.navbar-item:hover,.navbar.is-link .navbar-end>a.navbar-item.is-active,.navbar.is-link .navbar-end .navbar-link:focus,.navbar.is-link .navbar-end .navbar-link:hover,.navbar.is-link .navbar-end .navbar-link.is-active{background-color:#2958a4;color:#fff}.navbar.is-link .navbar-start .navbar-link::after,.navbar.is-link .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-link .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-link .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link{background-color:#2958a4;color:#fff}.navbar.is-link .navbar-dropdown a.navbar-item.is-active{background-color:#2e63b8;color:#fff}}.navbar.is-info{background-color:#209cee;color:#fff}.navbar.is-info .navbar-brand>.navbar-item,.navbar.is-info .navbar-brand .navbar-link{color:#fff}.navbar.is-info .navbar-brand>a.navbar-item:focus,.navbar.is-info .navbar-brand>a.navbar-item:hover,.navbar.is-info .navbar-brand>a.navbar-item.is-active,.navbar.is-info .navbar-brand .navbar-link:focus,.navbar.is-info .navbar-brand .navbar-link:hover,.navbar.is-info .navbar-brand .navbar-link.is-active{background-color:#1190e3;color:#fff}.navbar.is-info .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-info .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-info .navbar-start>.navbar-item,.navbar.is-info .navbar-start .navbar-link,.navbar.is-info .navbar-end>.navbar-item,.navbar.is-info .navbar-end .navbar-link{color:#fff}.navbar.is-info .navbar-start>a.navbar-item:focus,.navbar.is-info .navbar-start>a.navbar-item:hover,.navbar.is-info .navbar-start>a.navbar-item.is-active,.navbar.is-info .navbar-start .navbar-link:focus,.navbar.is-info .navbar-start .navbar-link:hover,.navbar.is-info .navbar-start .navbar-link.is-active,.navbar.is-info .navbar-end>a.navbar-item:focus,.navbar.is-info .navbar-end>a.navbar-item:hover,.navbar.is-info .navbar-end>a.navbar-item.is-active,.navbar.is-info .navbar-end .navbar-link:focus,.navbar.is-info .navbar-end .navbar-link:hover,.navbar.is-info .navbar-end .navbar-link.is-active{background-color:#1190e3;color:#fff}.navbar.is-info .navbar-start .navbar-link::after,.navbar.is-info .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-info .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-info .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link{background-color:#1190e3;color:#fff}.navbar.is-info .navbar-dropdown a.navbar-item.is-active{background-color:#209cee;color:#fff}}.navbar.is-success{background-color:#22c35b;color:#fff}.navbar.is-success .navbar-brand>.navbar-item,.navbar.is-success .navbar-brand .navbar-link{color:#fff}.navbar.is-success .navbar-brand>a.navbar-item:focus,.navbar.is-success .navbar-brand>a.navbar-item:hover,.navbar.is-success .navbar-brand>a.navbar-item.is-active,.navbar.is-success .navbar-brand .navbar-link:focus,.navbar.is-success .navbar-brand .navbar-link:hover,.navbar.is-success .navbar-brand .navbar-link.is-active{background-color:#1ead51;color:#fff}.navbar.is-success .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-success .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-success .navbar-start>.navbar-item,.navbar.is-success .navbar-start .navbar-link,.navbar.is-success .navbar-end>.navbar-item,.navbar.is-success .navbar-end .navbar-link{color:#fff}.navbar.is-success .navbar-start>a.navbar-item:focus,.navbar.is-success .navbar-start>a.navbar-item:hover,.navbar.is-success .navbar-start>a.navbar-item.is-active,.navbar.is-success .navbar-start .navbar-link:focus,.navbar.is-success .navbar-start .navbar-link:hover,.navbar.is-success .navbar-start .navbar-link.is-active,.navbar.is-success .navbar-end>a.navbar-item:focus,.navbar.is-success .navbar-end>a.navbar-item:hover,.navbar.is-success .navbar-end>a.navbar-item.is-active,.navbar.is-success .navbar-end .navbar-link:focus,.navbar.is-success .navbar-end .navbar-link:hover,.navbar.is-success .navbar-end .navbar-link.is-active{background-color:#1ead51;color:#fff}.navbar.is-success .navbar-start .navbar-link::after,.navbar.is-success .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-success .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-success .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link{background-color:#1ead51;color:#fff}.navbar.is-success .navbar-dropdown a.navbar-item.is-active{background-color:#22c35b;color:#fff}}.navbar.is-warning{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-brand>.navbar-item,.navbar.is-warning .navbar-brand .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-brand>a.navbar-item:focus,.navbar.is-warning .navbar-brand>a.navbar-item:hover,.navbar.is-warning .navbar-brand>a.navbar-item.is-active,.navbar.is-warning .navbar-brand .navbar-link:focus,.navbar.is-warning .navbar-brand .navbar-link:hover,.navbar.is-warning .navbar-brand .navbar-link.is-active{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-brand .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-burger{color:rgba(0,0,0,0.7)}@media screen and (min-width: 1056px){.navbar.is-warning .navbar-start>.navbar-item,.navbar.is-warning .navbar-start .navbar-link,.navbar.is-warning .navbar-end>.navbar-item,.navbar.is-warning .navbar-end .navbar-link{color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-start>a.navbar-item:focus,.navbar.is-warning .navbar-start>a.navbar-item:hover,.navbar.is-warning .navbar-start>a.navbar-item.is-active,.navbar.is-warning .navbar-start .navbar-link:focus,.navbar.is-warning .navbar-start .navbar-link:hover,.navbar.is-warning .navbar-start .navbar-link.is-active,.navbar.is-warning .navbar-end>a.navbar-item:focus,.navbar.is-warning .navbar-end>a.navbar-item:hover,.navbar.is-warning .navbar-end>a.navbar-item.is-active,.navbar.is-warning .navbar-end .navbar-link:focus,.navbar.is-warning .navbar-end .navbar-link:hover,.navbar.is-warning .navbar-end .navbar-link.is-active{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-start .navbar-link::after,.navbar.is-warning .navbar-end .navbar-link::after{border-color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.navbar.is-warning .navbar-dropdown a.navbar-item.is-active{background-color:#ffdd57;color:rgba(0,0,0,0.7)}}.navbar.is-danger{background-color:#da0b00;color:#fff}.navbar.is-danger .navbar-brand>.navbar-item,.navbar.is-danger .navbar-brand .navbar-link{color:#fff}.navbar.is-danger .navbar-brand>a.navbar-item:focus,.navbar.is-danger .navbar-brand>a.navbar-item:hover,.navbar.is-danger .navbar-brand>a.navbar-item.is-active,.navbar.is-danger .navbar-brand .navbar-link:focus,.navbar.is-danger .navbar-brand .navbar-link:hover,.navbar.is-danger .navbar-brand .navbar-link.is-active{background-color:#c10a00;color:#fff}.navbar.is-danger .navbar-brand .navbar-link::after{border-color:#fff}.navbar.is-danger .navbar-burger{color:#fff}@media screen and (min-width: 1056px){.navbar.is-danger .navbar-start>.navbar-item,.navbar.is-danger .navbar-start .navbar-link,.navbar.is-danger .navbar-end>.navbar-item,.navbar.is-danger .navbar-end .navbar-link{color:#fff}.navbar.is-danger .navbar-start>a.navbar-item:focus,.navbar.is-danger .navbar-start>a.navbar-item:hover,.navbar.is-danger .navbar-start>a.navbar-item.is-active,.navbar.is-danger .navbar-start .navbar-link:focus,.navbar.is-danger .navbar-start .navbar-link:hover,.navbar.is-danger .navbar-start .navbar-link.is-active,.navbar.is-danger .navbar-end>a.navbar-item:focus,.navbar.is-danger .navbar-end>a.navbar-item:hover,.navbar.is-danger .navbar-end>a.navbar-item.is-active,.navbar.is-danger .navbar-end .navbar-link:focus,.navbar.is-danger .navbar-end .navbar-link:hover,.navbar.is-danger .navbar-end .navbar-link.is-active{background-color:#c10a00;color:#fff}.navbar.is-danger .navbar-start .navbar-link::after,.navbar.is-danger .navbar-end .navbar-link::after{border-color:#fff}.navbar.is-danger .navbar-item.has-dropdown:focus .navbar-link,.navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link,.navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link{background-color:#c10a00;color:#fff}.navbar.is-danger .navbar-dropdown a.navbar-item.is-active{background-color:#da0b00;color:#fff}}.navbar>.container{align-items:stretch;display:flex;min-height:3.25rem;width:100%}.navbar.has-shadow{box-shadow:0 2px 0 0 #f5f5f5}.navbar.is-fixed-bottom,.navbar.is-fixed-top{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom{bottom:0}.navbar.is-fixed-bottom.has-shadow{box-shadow:0 -2px 0 0 #f5f5f5}.navbar.is-fixed-top{top:0}html.has-navbar-fixed-top,body.has-navbar-fixed-top{padding-top:3.25rem}html.has-navbar-fixed-bottom,body.has-navbar-fixed-bottom{padding-bottom:3.25rem}.navbar-brand,.navbar-tabs{align-items:stretch;display:flex;flex-shrink:0;min-height:3.25rem}.navbar-brand a.navbar-item:focus,.navbar-brand a.navbar-item:hover{background-color:transparent}.navbar-tabs{-webkit-overflow-scrolling:touch;max-width:100vw;overflow-x:auto;overflow-y:hidden}.navbar-burger{color:#222;-moz-appearance:none;-webkit-appearance:none;appearance:none;background:none;border:none;cursor:pointer;display:block;height:3.25rem;position:relative;width:3.25rem;margin-left:auto}.navbar-burger span{background-color:currentColor;display:block;height:1px;left:calc(50% - 8px);position:absolute;transform-origin:center;transition-duration:86ms;transition-property:background-color, opacity, transform;transition-timing-function:ease-out;width:16px}.navbar-burger span:nth-child(1){top:calc(50% - 6px)}.navbar-burger span:nth-child(2){top:calc(50% - 1px)}.navbar-burger span:nth-child(3){top:calc(50% + 4px)}.navbar-burger:hover{background-color:rgba(0,0,0,0.05)}.navbar-burger.is-active span:nth-child(1){transform:translateY(5px) rotate(45deg)}.navbar-burger.is-active span:nth-child(2){opacity:0}.navbar-burger.is-active span:nth-child(3){transform:translateY(-5px) rotate(-45deg)}.navbar-menu{display:none}.navbar-item,.navbar-link{color:#222;display:block;line-height:1.5;padding:0.5rem 0.75rem;position:relative}.navbar-item .icon:only-child,.navbar-link .icon:only-child{margin-left:-0.25rem;margin-right:-0.25rem}a.navbar-item,.navbar-link{cursor:pointer}a.navbar-item:focus,a.navbar-item:focus-within,a.navbar-item:hover,a.navbar-item.is-active,.navbar-link:focus,.navbar-link:focus-within,.navbar-link:hover,.navbar-link.is-active{background-color:#fafafa;color:#2e63b8}.navbar-item{flex-grow:0;flex-shrink:0}.navbar-item img{max-height:1.75rem}.navbar-item.has-dropdown{padding:0}.navbar-item.is-expanded{flex-grow:1;flex-shrink:1}.navbar-item.is-tab{border-bottom:1px solid transparent;min-height:3.25rem;padding-bottom:calc(0.5rem - 1px)}.navbar-item.is-tab:focus,.navbar-item.is-tab:hover{background-color:rgba(0,0,0,0);border-bottom-color:#2e63b8}.navbar-item.is-tab.is-active{background-color:rgba(0,0,0,0);border-bottom-color:#2e63b8;border-bottom-style:solid;border-bottom-width:3px;color:#2e63b8;padding-bottom:calc(0.5rem - 3px)}.navbar-content{flex-grow:1;flex-shrink:1}.navbar-link:not(.is-arrowless){padding-right:2.5em}.navbar-link:not(.is-arrowless)::after{border-color:#2e63b8;margin-top:-0.375em;right:1.125em}.navbar-dropdown{font-size:0.875rem;padding-bottom:0.5rem;padding-top:0.5rem}.navbar-dropdown .navbar-item{padding-left:1.5rem;padding-right:1.5rem}.navbar-divider{background-color:#f5f5f5;border:none;display:none;height:2px;margin:0.5rem 0}@media screen and (max-width: 1055px){.navbar>.container{display:block}.navbar-brand .navbar-item,.navbar-tabs .navbar-item{align-items:center;display:flex}.navbar-link::after{display:none}.navbar-menu{background-color:#fff;box-shadow:0 8px 16px rgba(10,10,10,0.1);padding:0.5rem 0}.navbar-menu.is-active{display:block}.navbar.is-fixed-bottom-touch,.navbar.is-fixed-top-touch{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom-touch{bottom:0}.navbar.is-fixed-bottom-touch.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}.navbar.is-fixed-top-touch{top:0}.navbar.is-fixed-top .navbar-menu,.navbar.is-fixed-top-touch .navbar-menu{-webkit-overflow-scrolling:touch;max-height:calc(100vh - 3.25rem);overflow:auto}html.has-navbar-fixed-top-touch,body.has-navbar-fixed-top-touch{padding-top:3.25rem}html.has-navbar-fixed-bottom-touch,body.has-navbar-fixed-bottom-touch{padding-bottom:3.25rem}}@media screen and (min-width: 1056px){.navbar,.navbar-menu,.navbar-start,.navbar-end{align-items:stretch;display:flex}.navbar{min-height:3.25rem}.navbar.is-spaced{padding:1rem 2rem}.navbar.is-spaced .navbar-start,.navbar.is-spaced .navbar-end{align-items:center}.navbar.is-spaced a.navbar-item,.navbar.is-spaced .navbar-link{border-radius:4px}.navbar.is-transparent a.navbar-item:focus,.navbar.is-transparent a.navbar-item:hover,.navbar.is-transparent a.navbar-item.is-active,.navbar.is-transparent .navbar-link:focus,.navbar.is-transparent .navbar-link:hover,.navbar.is-transparent .navbar-link.is-active{background-color:transparent !important}.navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link,.navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link{background-color:transparent !important}.navbar.is-transparent .navbar-dropdown a.navbar-item:focus,.navbar.is-transparent .navbar-dropdown a.navbar-item:hover{background-color:#f5f5f5;color:#0a0a0a}.navbar.is-transparent .navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#2e63b8}.navbar-burger{display:none}.navbar-item,.navbar-link{align-items:center;display:flex}.navbar-item.has-dropdown{align-items:stretch}.navbar-item.has-dropdown-up .navbar-link::after{transform:rotate(135deg) translate(0.25em, -0.25em)}.navbar-item.has-dropdown-up .navbar-dropdown{border-bottom:2px solid #dbdbdb;border-radius:6px 6px 0 0;border-top:none;bottom:100%;box-shadow:0 -8px 8px rgba(10,10,10,0.1);top:auto}.navbar-item.is-active .navbar-dropdown,.navbar-item.is-hoverable:focus .navbar-dropdown,.navbar-item.is-hoverable:focus-within .navbar-dropdown,.navbar-item.is-hoverable:hover .navbar-dropdown{display:block}.navbar.is-spaced .navbar-item.is-active .navbar-dropdown,.navbar-item.is-active .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-hoverable:focus .navbar-dropdown,.navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-hoverable:focus-within .navbar-dropdown,.navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed,.navbar.is-spaced .navbar-item.is-hoverable:hover .navbar-dropdown,.navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed{opacity:1;pointer-events:auto;transform:translateY(0)}.navbar-menu{flex-grow:1;flex-shrink:0}.navbar-start{justify-content:flex-start;margin-right:auto}.navbar-end{justify-content:flex-end;margin-left:auto}.navbar-dropdown{background-color:#fff;border-bottom-left-radius:6px;border-bottom-right-radius:6px;border-top:2px solid #dbdbdb;box-shadow:0 8px 8px rgba(10,10,10,0.1);display:none;font-size:0.875rem;left:0;min-width:100%;position:absolute;top:100%;z-index:20}.navbar-dropdown .navbar-item{padding:0.375rem 1rem;white-space:nowrap}.navbar-dropdown a.navbar-item{padding-right:3rem}.navbar-dropdown a.navbar-item:focus,.navbar-dropdown a.navbar-item:hover{background-color:#f5f5f5;color:#0a0a0a}.navbar-dropdown a.navbar-item.is-active{background-color:#f5f5f5;color:#2e63b8}.navbar.is-spaced .navbar-dropdown,.navbar-dropdown.is-boxed{border-radius:6px;border-top:none;box-shadow:0 8px 8px rgba(10,10,10,0.1), 0 0 0 1px rgba(10,10,10,0.1);display:block;opacity:0;pointer-events:none;top:calc(100% + (-4px));transform:translateY(-5px);transition-duration:86ms;transition-property:opacity, transform}.navbar-dropdown.is-right{left:auto;right:0}.navbar-divider{display:block}.navbar>.container .navbar-brand,.container>.navbar .navbar-brand{margin-left:-.75rem}.navbar>.container .navbar-menu,.container>.navbar .navbar-menu{margin-right:-.75rem}.navbar.is-fixed-bottom-desktop,.navbar.is-fixed-top-desktop{left:0;position:fixed;right:0;z-index:30}.navbar.is-fixed-bottom-desktop{bottom:0}.navbar.is-fixed-bottom-desktop.has-shadow{box-shadow:0 -2px 3px rgba(10,10,10,0.1)}.navbar.is-fixed-top-desktop{top:0}html.has-navbar-fixed-top-desktop,body.has-navbar-fixed-top-desktop{padding-top:3.25rem}html.has-navbar-fixed-bottom-desktop,body.has-navbar-fixed-bottom-desktop{padding-bottom:3.25rem}html.has-spaced-navbar-fixed-top,body.has-spaced-navbar-fixed-top{padding-top:5.25rem}html.has-spaced-navbar-fixed-bottom,body.has-spaced-navbar-fixed-bottom{padding-bottom:5.25rem}a.navbar-item.is-active,.navbar-link.is-active{color:#0a0a0a}a.navbar-item.is-active:not(:focus):not(:hover),.navbar-link.is-active:not(:focus):not(:hover){background-color:rgba(0,0,0,0)}.navbar-item.has-dropdown:focus .navbar-link,.navbar-item.has-dropdown:hover .navbar-link,.navbar-item.has-dropdown.is-active .navbar-link{background-color:#fafafa}}.hero.is-fullheight-with-navbar{min-height:calc(100vh - 3.25rem)}.pagination{font-size:1rem;margin:-.25rem}.pagination.is-small,#documenter .docs-sidebar form.docs-search>input.pagination{font-size:.75rem}.pagination.is-medium{font-size:1.25rem}.pagination.is-large{font-size:1.5rem}.pagination.is-rounded .pagination-previous,#documenter .docs-sidebar form.docs-search>input.pagination .pagination-previous,.pagination.is-rounded .pagination-next,#documenter .docs-sidebar form.docs-search>input.pagination .pagination-next{padding-left:1em;padding-right:1em;border-radius:9999px}.pagination.is-rounded .pagination-link,#documenter .docs-sidebar form.docs-search>input.pagination .pagination-link{border-radius:9999px}.pagination,.pagination-list{align-items:center;display:flex;justify-content:center;text-align:center}.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis{font-size:1em;justify-content:center;margin:.25rem;padding-left:.5em;padding-right:.5em;text-align:center}.pagination-previous,.pagination-next,.pagination-link{border-color:#dbdbdb;color:#222;min-width:2.5em}.pagination-previous:hover,.pagination-next:hover,.pagination-link:hover{border-color:#b5b5b5;color:#363636}.pagination-previous:focus,.pagination-next:focus,.pagination-link:focus{border-color:#3c5dcd}.pagination-previous:active,.pagination-next:active,.pagination-link:active{box-shadow:inset 0 1px 2px rgba(10,10,10,0.2)}.pagination-previous[disabled],.pagination-previous.is-disabled,.pagination-next[disabled],.pagination-next.is-disabled,.pagination-link[disabled],.pagination-link.is-disabled{background-color:#dbdbdb;border-color:#dbdbdb;box-shadow:none;color:#6b6b6b;opacity:0.5}.pagination-previous,.pagination-next{padding-left:.75em;padding-right:.75em;white-space:nowrap}.pagination-link.is-current{background-color:#2e63b8;border-color:#2e63b8;color:#fff}.pagination-ellipsis{color:#b5b5b5;pointer-events:none}.pagination-list{flex-wrap:wrap}.pagination-list li{list-style:none}@media screen and (max-width: 768px){.pagination{flex-wrap:wrap}.pagination-previous,.pagination-next{flex-grow:1;flex-shrink:1}.pagination-list li{flex-grow:1;flex-shrink:1}}@media screen and (min-width: 769px),print{.pagination-list{flex-grow:1;flex-shrink:1;justify-content:flex-start;order:1}.pagination-previous,.pagination-next,.pagination-link,.pagination-ellipsis{margin-bottom:0;margin-top:0}.pagination-previous{order:2}.pagination-next{order:3}.pagination{justify-content:space-between;margin-bottom:0;margin-top:0}.pagination.is-centered .pagination-previous{order:1}.pagination.is-centered .pagination-list{justify-content:center;order:2}.pagination.is-centered .pagination-next{order:3}.pagination.is-right .pagination-previous{order:1}.pagination.is-right .pagination-next{order:2}.pagination.is-right .pagination-list{justify-content:flex-end;order:3}}.panel{border-radius:6px;box-shadow:#bbb;font-size:1rem}.panel:not(:last-child){margin-bottom:1.5rem}.panel.is-white .panel-heading{background-color:#fff;color:#0a0a0a}.panel.is-white .panel-tabs a.is-active{border-bottom-color:#fff}.panel.is-white .panel-block.is-active .panel-icon{color:#fff}.panel.is-black .panel-heading{background-color:#0a0a0a;color:#fff}.panel.is-black .panel-tabs a.is-active{border-bottom-color:#0a0a0a}.panel.is-black .panel-block.is-active .panel-icon{color:#0a0a0a}.panel.is-light .panel-heading{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.panel.is-light .panel-tabs a.is-active{border-bottom-color:#f5f5f5}.panel.is-light .panel-block.is-active .panel-icon{color:#f5f5f5}.panel.is-dark .panel-heading,.content kbd.panel .panel-heading{background-color:#363636;color:#fff}.panel.is-dark .panel-tabs a.is-active,.content kbd.panel .panel-tabs a.is-active{border-bottom-color:#363636}.panel.is-dark .panel-block.is-active .panel-icon,.content kbd.panel .panel-block.is-active .panel-icon{color:#363636}.panel.is-primary .panel-heading,.docstring>section>a.panel.docs-sourcelink .panel-heading{background-color:#4eb5de;color:#fff}.panel.is-primary .panel-tabs a.is-active,.docstring>section>a.panel.docs-sourcelink .panel-tabs a.is-active{border-bottom-color:#4eb5de}.panel.is-primary .panel-block.is-active .panel-icon,.docstring>section>a.panel.docs-sourcelink .panel-block.is-active .panel-icon{color:#4eb5de}.panel.is-link .panel-heading{background-color:#2e63b8;color:#fff}.panel.is-link .panel-tabs a.is-active{border-bottom-color:#2e63b8}.panel.is-link .panel-block.is-active .panel-icon{color:#2e63b8}.panel.is-info .panel-heading{background-color:#209cee;color:#fff}.panel.is-info .panel-tabs a.is-active{border-bottom-color:#209cee}.panel.is-info .panel-block.is-active .panel-icon{color:#209cee}.panel.is-success .panel-heading{background-color:#22c35b;color:#fff}.panel.is-success .panel-tabs a.is-active{border-bottom-color:#22c35b}.panel.is-success .panel-block.is-active .panel-icon{color:#22c35b}.panel.is-warning .panel-heading{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.panel.is-warning .panel-tabs a.is-active{border-bottom-color:#ffdd57}.panel.is-warning .panel-block.is-active .panel-icon{color:#ffdd57}.panel.is-danger .panel-heading{background-color:#da0b00;color:#fff}.panel.is-danger .panel-tabs a.is-active{border-bottom-color:#da0b00}.panel.is-danger .panel-block.is-active .panel-icon{color:#da0b00}.panel-tabs:not(:last-child),.panel-block:not(:last-child){border-bottom:1px solid #ededed}.panel-heading{background-color:#ededed;border-radius:6px 6px 0 0;color:#222;font-size:1.25em;font-weight:700;line-height:1.25;padding:0.75em 1em}.panel-tabs{align-items:flex-end;display:flex;font-size:.875em;justify-content:center}.panel-tabs a{border-bottom:1px solid #dbdbdb;margin-bottom:-1px;padding:0.5em}.panel-tabs a.is-active{border-bottom-color:#4a4a4a;color:#363636}.panel-list a{color:#222}.panel-list a:hover{color:#2e63b8}.panel-block{align-items:center;color:#222;display:flex;justify-content:flex-start;padding:0.5em 0.75em}.panel-block input[type="checkbox"]{margin-right:.75em}.panel-block>.control{flex-grow:1;flex-shrink:1;width:100%}.panel-block.is-wrapped{flex-wrap:wrap}.panel-block.is-active{border-left-color:#2e63b8;color:#363636}.panel-block.is-active .panel-icon{color:#2e63b8}.panel-block:last-child{border-bottom-left-radius:6px;border-bottom-right-radius:6px}a.panel-block,label.panel-block{cursor:pointer}a.panel-block:hover,label.panel-block:hover{background-color:#f5f5f5}.panel-icon{display:inline-block;font-size:14px;height:1em;line-height:1em;text-align:center;vertical-align:top;width:1em;color:#6b6b6b;margin-right:.75em}.panel-icon .fa{font-size:inherit;line-height:inherit}.tabs{-webkit-overflow-scrolling:touch;align-items:stretch;display:flex;font-size:1rem;justify-content:space-between;overflow:hidden;overflow-x:auto;white-space:nowrap}.tabs a{align-items:center;border-bottom-color:#dbdbdb;border-bottom-style:solid;border-bottom-width:1px;color:#222;display:flex;justify-content:center;margin-bottom:-1px;padding:0.5em 1em;vertical-align:top}.tabs a:hover{border-bottom-color:#222;color:#222}.tabs li{display:block}.tabs li.is-active a{border-bottom-color:#2e63b8;color:#2e63b8}.tabs ul{align-items:center;border-bottom-color:#dbdbdb;border-bottom-style:solid;border-bottom-width:1px;display:flex;flex-grow:1;flex-shrink:0;justify-content:flex-start}.tabs ul.is-left{padding-right:0.75em}.tabs ul.is-center{flex:none;justify-content:center;padding-left:0.75em;padding-right:0.75em}.tabs ul.is-right{justify-content:flex-end;padding-left:0.75em}.tabs .icon:first-child{margin-right:.5em}.tabs .icon:last-child{margin-left:.5em}.tabs.is-centered ul{justify-content:center}.tabs.is-right ul{justify-content:flex-end}.tabs.is-boxed a{border:1px solid transparent;border-radius:4px 4px 0 0}.tabs.is-boxed a:hover{background-color:#f5f5f5;border-bottom-color:#dbdbdb}.tabs.is-boxed li.is-active a{background-color:#fff;border-color:#dbdbdb;border-bottom-color:rgba(0,0,0,0) !important}.tabs.is-fullwidth li{flex-grow:1;flex-shrink:0}.tabs.is-toggle a{border-color:#dbdbdb;border-style:solid;border-width:1px;margin-bottom:0;position:relative}.tabs.is-toggle a:hover{background-color:#f5f5f5;border-color:#b5b5b5;z-index:2}.tabs.is-toggle li+li{margin-left:-1px}.tabs.is-toggle li:first-child a{border-top-left-radius:4px;border-bottom-left-radius:4px}.tabs.is-toggle li:last-child a{border-top-right-radius:4px;border-bottom-right-radius:4px}.tabs.is-toggle li.is-active a{background-color:#2e63b8;border-color:#2e63b8;color:#fff;z-index:1}.tabs.is-toggle ul{border-bottom:none}.tabs.is-toggle.is-toggle-rounded li:first-child a{border-bottom-left-radius:9999px;border-top-left-radius:9999px;padding-left:1.25em}.tabs.is-toggle.is-toggle-rounded li:last-child a{border-bottom-right-radius:9999px;border-top-right-radius:9999px;padding-right:1.25em}.tabs.is-small,#documenter .docs-sidebar form.docs-search>input.tabs{font-size:.75rem}.tabs.is-medium{font-size:1.25rem}.tabs.is-large{font-size:1.5rem}.column{display:block;flex-basis:0;flex-grow:1;flex-shrink:1;padding:.75rem}.columns.is-mobile>.column.is-narrow{flex:none;width:unset}.columns.is-mobile>.column.is-full{flex:none;width:100%}.columns.is-mobile>.column.is-three-quarters{flex:none;width:75%}.columns.is-mobile>.column.is-two-thirds{flex:none;width:66.6666%}.columns.is-mobile>.column.is-half{flex:none;width:50%}.columns.is-mobile>.column.is-one-third{flex:none;width:33.3333%}.columns.is-mobile>.column.is-one-quarter{flex:none;width:25%}.columns.is-mobile>.column.is-one-fifth{flex:none;width:20%}.columns.is-mobile>.column.is-two-fifths{flex:none;width:40%}.columns.is-mobile>.column.is-three-fifths{flex:none;width:60%}.columns.is-mobile>.column.is-four-fifths{flex:none;width:80%}.columns.is-mobile>.column.is-offset-three-quarters{margin-left:75%}.columns.is-mobile>.column.is-offset-two-thirds{margin-left:66.6666%}.columns.is-mobile>.column.is-offset-half{margin-left:50%}.columns.is-mobile>.column.is-offset-one-third{margin-left:33.3333%}.columns.is-mobile>.column.is-offset-one-quarter{margin-left:25%}.columns.is-mobile>.column.is-offset-one-fifth{margin-left:20%}.columns.is-mobile>.column.is-offset-two-fifths{margin-left:40%}.columns.is-mobile>.column.is-offset-three-fifths{margin-left:60%}.columns.is-mobile>.column.is-offset-four-fifths{margin-left:80%}.columns.is-mobile>.column.is-0{flex:none;width:0%}.columns.is-mobile>.column.is-offset-0{margin-left:0%}.columns.is-mobile>.column.is-1{flex:none;width:8.33333337%}.columns.is-mobile>.column.is-offset-1{margin-left:8.33333337%}.columns.is-mobile>.column.is-2{flex:none;width:16.66666674%}.columns.is-mobile>.column.is-offset-2{margin-left:16.66666674%}.columns.is-mobile>.column.is-3{flex:none;width:25%}.columns.is-mobile>.column.is-offset-3{margin-left:25%}.columns.is-mobile>.column.is-4{flex:none;width:33.33333337%}.columns.is-mobile>.column.is-offset-4{margin-left:33.33333337%}.columns.is-mobile>.column.is-5{flex:none;width:41.66666674%}.columns.is-mobile>.column.is-offset-5{margin-left:41.66666674%}.columns.is-mobile>.column.is-6{flex:none;width:50%}.columns.is-mobile>.column.is-offset-6{margin-left:50%}.columns.is-mobile>.column.is-7{flex:none;width:58.33333337%}.columns.is-mobile>.column.is-offset-7{margin-left:58.33333337%}.columns.is-mobile>.column.is-8{flex:none;width:66.66666674%}.columns.is-mobile>.column.is-offset-8{margin-left:66.66666674%}.columns.is-mobile>.column.is-9{flex:none;width:75%}.columns.is-mobile>.column.is-offset-9{margin-left:75%}.columns.is-mobile>.column.is-10{flex:none;width:83.33333337%}.columns.is-mobile>.column.is-offset-10{margin-left:83.33333337%}.columns.is-mobile>.column.is-11{flex:none;width:91.66666674%}.columns.is-mobile>.column.is-offset-11{margin-left:91.66666674%}.columns.is-mobile>.column.is-12{flex:none;width:100%}.columns.is-mobile>.column.is-offset-12{margin-left:100%}@media screen and (max-width: 768px){.column.is-narrow-mobile{flex:none;width:unset}.column.is-full-mobile{flex:none;width:100%}.column.is-three-quarters-mobile{flex:none;width:75%}.column.is-two-thirds-mobile{flex:none;width:66.6666%}.column.is-half-mobile{flex:none;width:50%}.column.is-one-third-mobile{flex:none;width:33.3333%}.column.is-one-quarter-mobile{flex:none;width:25%}.column.is-one-fifth-mobile{flex:none;width:20%}.column.is-two-fifths-mobile{flex:none;width:40%}.column.is-three-fifths-mobile{flex:none;width:60%}.column.is-four-fifths-mobile{flex:none;width:80%}.column.is-offset-three-quarters-mobile{margin-left:75%}.column.is-offset-two-thirds-mobile{margin-left:66.6666%}.column.is-offset-half-mobile{margin-left:50%}.column.is-offset-one-third-mobile{margin-left:33.3333%}.column.is-offset-one-quarter-mobile{margin-left:25%}.column.is-offset-one-fifth-mobile{margin-left:20%}.column.is-offset-two-fifths-mobile{margin-left:40%}.column.is-offset-three-fifths-mobile{margin-left:60%}.column.is-offset-four-fifths-mobile{margin-left:80%}.column.is-0-mobile{flex:none;width:0%}.column.is-offset-0-mobile{margin-left:0%}.column.is-1-mobile{flex:none;width:8.33333337%}.column.is-offset-1-mobile{margin-left:8.33333337%}.column.is-2-mobile{flex:none;width:16.66666674%}.column.is-offset-2-mobile{margin-left:16.66666674%}.column.is-3-mobile{flex:none;width:25%}.column.is-offset-3-mobile{margin-left:25%}.column.is-4-mobile{flex:none;width:33.33333337%}.column.is-offset-4-mobile{margin-left:33.33333337%}.column.is-5-mobile{flex:none;width:41.66666674%}.column.is-offset-5-mobile{margin-left:41.66666674%}.column.is-6-mobile{flex:none;width:50%}.column.is-offset-6-mobile{margin-left:50%}.column.is-7-mobile{flex:none;width:58.33333337%}.column.is-offset-7-mobile{margin-left:58.33333337%}.column.is-8-mobile{flex:none;width:66.66666674%}.column.is-offset-8-mobile{margin-left:66.66666674%}.column.is-9-mobile{flex:none;width:75%}.column.is-offset-9-mobile{margin-left:75%}.column.is-10-mobile{flex:none;width:83.33333337%}.column.is-offset-10-mobile{margin-left:83.33333337%}.column.is-11-mobile{flex:none;width:91.66666674%}.column.is-offset-11-mobile{margin-left:91.66666674%}.column.is-12-mobile{flex:none;width:100%}.column.is-offset-12-mobile{margin-left:100%}}@media screen and (min-width: 769px),print{.column.is-narrow,.column.is-narrow-tablet{flex:none;width:unset}.column.is-full,.column.is-full-tablet{flex:none;width:100%}.column.is-three-quarters,.column.is-three-quarters-tablet{flex:none;width:75%}.column.is-two-thirds,.column.is-two-thirds-tablet{flex:none;width:66.6666%}.column.is-half,.column.is-half-tablet{flex:none;width:50%}.column.is-one-third,.column.is-one-third-tablet{flex:none;width:33.3333%}.column.is-one-quarter,.column.is-one-quarter-tablet{flex:none;width:25%}.column.is-one-fifth,.column.is-one-fifth-tablet{flex:none;width:20%}.column.is-two-fifths,.column.is-two-fifths-tablet{flex:none;width:40%}.column.is-three-fifths,.column.is-three-fifths-tablet{flex:none;width:60%}.column.is-four-fifths,.column.is-four-fifths-tablet{flex:none;width:80%}.column.is-offset-three-quarters,.column.is-offset-three-quarters-tablet{margin-left:75%}.column.is-offset-two-thirds,.column.is-offset-two-thirds-tablet{margin-left:66.6666%}.column.is-offset-half,.column.is-offset-half-tablet{margin-left:50%}.column.is-offset-one-third,.column.is-offset-one-third-tablet{margin-left:33.3333%}.column.is-offset-one-quarter,.column.is-offset-one-quarter-tablet{margin-left:25%}.column.is-offset-one-fifth,.column.is-offset-one-fifth-tablet{margin-left:20%}.column.is-offset-two-fifths,.column.is-offset-two-fifths-tablet{margin-left:40%}.column.is-offset-three-fifths,.column.is-offset-three-fifths-tablet{margin-left:60%}.column.is-offset-four-fifths,.column.is-offset-four-fifths-tablet{margin-left:80%}.column.is-0,.column.is-0-tablet{flex:none;width:0%}.column.is-offset-0,.column.is-offset-0-tablet{margin-left:0%}.column.is-1,.column.is-1-tablet{flex:none;width:8.33333337%}.column.is-offset-1,.column.is-offset-1-tablet{margin-left:8.33333337%}.column.is-2,.column.is-2-tablet{flex:none;width:16.66666674%}.column.is-offset-2,.column.is-offset-2-tablet{margin-left:16.66666674%}.column.is-3,.column.is-3-tablet{flex:none;width:25%}.column.is-offset-3,.column.is-offset-3-tablet{margin-left:25%}.column.is-4,.column.is-4-tablet{flex:none;width:33.33333337%}.column.is-offset-4,.column.is-offset-4-tablet{margin-left:33.33333337%}.column.is-5,.column.is-5-tablet{flex:none;width:41.66666674%}.column.is-offset-5,.column.is-offset-5-tablet{margin-left:41.66666674%}.column.is-6,.column.is-6-tablet{flex:none;width:50%}.column.is-offset-6,.column.is-offset-6-tablet{margin-left:50%}.column.is-7,.column.is-7-tablet{flex:none;width:58.33333337%}.column.is-offset-7,.column.is-offset-7-tablet{margin-left:58.33333337%}.column.is-8,.column.is-8-tablet{flex:none;width:66.66666674%}.column.is-offset-8,.column.is-offset-8-tablet{margin-left:66.66666674%}.column.is-9,.column.is-9-tablet{flex:none;width:75%}.column.is-offset-9,.column.is-offset-9-tablet{margin-left:75%}.column.is-10,.column.is-10-tablet{flex:none;width:83.33333337%}.column.is-offset-10,.column.is-offset-10-tablet{margin-left:83.33333337%}.column.is-11,.column.is-11-tablet{flex:none;width:91.66666674%}.column.is-offset-11,.column.is-offset-11-tablet{margin-left:91.66666674%}.column.is-12,.column.is-12-tablet{flex:none;width:100%}.column.is-offset-12,.column.is-offset-12-tablet{margin-left:100%}}@media screen and (max-width: 1055px){.column.is-narrow-touch{flex:none;width:unset}.column.is-full-touch{flex:none;width:100%}.column.is-three-quarters-touch{flex:none;width:75%}.column.is-two-thirds-touch{flex:none;width:66.6666%}.column.is-half-touch{flex:none;width:50%}.column.is-one-third-touch{flex:none;width:33.3333%}.column.is-one-quarter-touch{flex:none;width:25%}.column.is-one-fifth-touch{flex:none;width:20%}.column.is-two-fifths-touch{flex:none;width:40%}.column.is-three-fifths-touch{flex:none;width:60%}.column.is-four-fifths-touch{flex:none;width:80%}.column.is-offset-three-quarters-touch{margin-left:75%}.column.is-offset-two-thirds-touch{margin-left:66.6666%}.column.is-offset-half-touch{margin-left:50%}.column.is-offset-one-third-touch{margin-left:33.3333%}.column.is-offset-one-quarter-touch{margin-left:25%}.column.is-offset-one-fifth-touch{margin-left:20%}.column.is-offset-two-fifths-touch{margin-left:40%}.column.is-offset-three-fifths-touch{margin-left:60%}.column.is-offset-four-fifths-touch{margin-left:80%}.column.is-0-touch{flex:none;width:0%}.column.is-offset-0-touch{margin-left:0%}.column.is-1-touch{flex:none;width:8.33333337%}.column.is-offset-1-touch{margin-left:8.33333337%}.column.is-2-touch{flex:none;width:16.66666674%}.column.is-offset-2-touch{margin-left:16.66666674%}.column.is-3-touch{flex:none;width:25%}.column.is-offset-3-touch{margin-left:25%}.column.is-4-touch{flex:none;width:33.33333337%}.column.is-offset-4-touch{margin-left:33.33333337%}.column.is-5-touch{flex:none;width:41.66666674%}.column.is-offset-5-touch{margin-left:41.66666674%}.column.is-6-touch{flex:none;width:50%}.column.is-offset-6-touch{margin-left:50%}.column.is-7-touch{flex:none;width:58.33333337%}.column.is-offset-7-touch{margin-left:58.33333337%}.column.is-8-touch{flex:none;width:66.66666674%}.column.is-offset-8-touch{margin-left:66.66666674%}.column.is-9-touch{flex:none;width:75%}.column.is-offset-9-touch{margin-left:75%}.column.is-10-touch{flex:none;width:83.33333337%}.column.is-offset-10-touch{margin-left:83.33333337%}.column.is-11-touch{flex:none;width:91.66666674%}.column.is-offset-11-touch{margin-left:91.66666674%}.column.is-12-touch{flex:none;width:100%}.column.is-offset-12-touch{margin-left:100%}}@media screen and (min-width: 1056px){.column.is-narrow-desktop{flex:none;width:unset}.column.is-full-desktop{flex:none;width:100%}.column.is-three-quarters-desktop{flex:none;width:75%}.column.is-two-thirds-desktop{flex:none;width:66.6666%}.column.is-half-desktop{flex:none;width:50%}.column.is-one-third-desktop{flex:none;width:33.3333%}.column.is-one-quarter-desktop{flex:none;width:25%}.column.is-one-fifth-desktop{flex:none;width:20%}.column.is-two-fifths-desktop{flex:none;width:40%}.column.is-three-fifths-desktop{flex:none;width:60%}.column.is-four-fifths-desktop{flex:none;width:80%}.column.is-offset-three-quarters-desktop{margin-left:75%}.column.is-offset-two-thirds-desktop{margin-left:66.6666%}.column.is-offset-half-desktop{margin-left:50%}.column.is-offset-one-third-desktop{margin-left:33.3333%}.column.is-offset-one-quarter-desktop{margin-left:25%}.column.is-offset-one-fifth-desktop{margin-left:20%}.column.is-offset-two-fifths-desktop{margin-left:40%}.column.is-offset-three-fifths-desktop{margin-left:60%}.column.is-offset-four-fifths-desktop{margin-left:80%}.column.is-0-desktop{flex:none;width:0%}.column.is-offset-0-desktop{margin-left:0%}.column.is-1-desktop{flex:none;width:8.33333337%}.column.is-offset-1-desktop{margin-left:8.33333337%}.column.is-2-desktop{flex:none;width:16.66666674%}.column.is-offset-2-desktop{margin-left:16.66666674%}.column.is-3-desktop{flex:none;width:25%}.column.is-offset-3-desktop{margin-left:25%}.column.is-4-desktop{flex:none;width:33.33333337%}.column.is-offset-4-desktop{margin-left:33.33333337%}.column.is-5-desktop{flex:none;width:41.66666674%}.column.is-offset-5-desktop{margin-left:41.66666674%}.column.is-6-desktop{flex:none;width:50%}.column.is-offset-6-desktop{margin-left:50%}.column.is-7-desktop{flex:none;width:58.33333337%}.column.is-offset-7-desktop{margin-left:58.33333337%}.column.is-8-desktop{flex:none;width:66.66666674%}.column.is-offset-8-desktop{margin-left:66.66666674%}.column.is-9-desktop{flex:none;width:75%}.column.is-offset-9-desktop{margin-left:75%}.column.is-10-desktop{flex:none;width:83.33333337%}.column.is-offset-10-desktop{margin-left:83.33333337%}.column.is-11-desktop{flex:none;width:91.66666674%}.column.is-offset-11-desktop{margin-left:91.66666674%}.column.is-12-desktop{flex:none;width:100%}.column.is-offset-12-desktop{margin-left:100%}}@media screen and (min-width: 1216px){.column.is-narrow-widescreen{flex:none;width:unset}.column.is-full-widescreen{flex:none;width:100%}.column.is-three-quarters-widescreen{flex:none;width:75%}.column.is-two-thirds-widescreen{flex:none;width:66.6666%}.column.is-half-widescreen{flex:none;width:50%}.column.is-one-third-widescreen{flex:none;width:33.3333%}.column.is-one-quarter-widescreen{flex:none;width:25%}.column.is-one-fifth-widescreen{flex:none;width:20%}.column.is-two-fifths-widescreen{flex:none;width:40%}.column.is-three-fifths-widescreen{flex:none;width:60%}.column.is-four-fifths-widescreen{flex:none;width:80%}.column.is-offset-three-quarters-widescreen{margin-left:75%}.column.is-offset-two-thirds-widescreen{margin-left:66.6666%}.column.is-offset-half-widescreen{margin-left:50%}.column.is-offset-one-third-widescreen{margin-left:33.3333%}.column.is-offset-one-quarter-widescreen{margin-left:25%}.column.is-offset-one-fifth-widescreen{margin-left:20%}.column.is-offset-two-fifths-widescreen{margin-left:40%}.column.is-offset-three-fifths-widescreen{margin-left:60%}.column.is-offset-four-fifths-widescreen{margin-left:80%}.column.is-0-widescreen{flex:none;width:0%}.column.is-offset-0-widescreen{margin-left:0%}.column.is-1-widescreen{flex:none;width:8.33333337%}.column.is-offset-1-widescreen{margin-left:8.33333337%}.column.is-2-widescreen{flex:none;width:16.66666674%}.column.is-offset-2-widescreen{margin-left:16.66666674%}.column.is-3-widescreen{flex:none;width:25%}.column.is-offset-3-widescreen{margin-left:25%}.column.is-4-widescreen{flex:none;width:33.33333337%}.column.is-offset-4-widescreen{margin-left:33.33333337%}.column.is-5-widescreen{flex:none;width:41.66666674%}.column.is-offset-5-widescreen{margin-left:41.66666674%}.column.is-6-widescreen{flex:none;width:50%}.column.is-offset-6-widescreen{margin-left:50%}.column.is-7-widescreen{flex:none;width:58.33333337%}.column.is-offset-7-widescreen{margin-left:58.33333337%}.column.is-8-widescreen{flex:none;width:66.66666674%}.column.is-offset-8-widescreen{margin-left:66.66666674%}.column.is-9-widescreen{flex:none;width:75%}.column.is-offset-9-widescreen{margin-left:75%}.column.is-10-widescreen{flex:none;width:83.33333337%}.column.is-offset-10-widescreen{margin-left:83.33333337%}.column.is-11-widescreen{flex:none;width:91.66666674%}.column.is-offset-11-widescreen{margin-left:91.66666674%}.column.is-12-widescreen{flex:none;width:100%}.column.is-offset-12-widescreen{margin-left:100%}}@media screen and (min-width: 1408px){.column.is-narrow-fullhd{flex:none;width:unset}.column.is-full-fullhd{flex:none;width:100%}.column.is-three-quarters-fullhd{flex:none;width:75%}.column.is-two-thirds-fullhd{flex:none;width:66.6666%}.column.is-half-fullhd{flex:none;width:50%}.column.is-one-third-fullhd{flex:none;width:33.3333%}.column.is-one-quarter-fullhd{flex:none;width:25%}.column.is-one-fifth-fullhd{flex:none;width:20%}.column.is-two-fifths-fullhd{flex:none;width:40%}.column.is-three-fifths-fullhd{flex:none;width:60%}.column.is-four-fifths-fullhd{flex:none;width:80%}.column.is-offset-three-quarters-fullhd{margin-left:75%}.column.is-offset-two-thirds-fullhd{margin-left:66.6666%}.column.is-offset-half-fullhd{margin-left:50%}.column.is-offset-one-third-fullhd{margin-left:33.3333%}.column.is-offset-one-quarter-fullhd{margin-left:25%}.column.is-offset-one-fifth-fullhd{margin-left:20%}.column.is-offset-two-fifths-fullhd{margin-left:40%}.column.is-offset-three-fifths-fullhd{margin-left:60%}.column.is-offset-four-fifths-fullhd{margin-left:80%}.column.is-0-fullhd{flex:none;width:0%}.column.is-offset-0-fullhd{margin-left:0%}.column.is-1-fullhd{flex:none;width:8.33333337%}.column.is-offset-1-fullhd{margin-left:8.33333337%}.column.is-2-fullhd{flex:none;width:16.66666674%}.column.is-offset-2-fullhd{margin-left:16.66666674%}.column.is-3-fullhd{flex:none;width:25%}.column.is-offset-3-fullhd{margin-left:25%}.column.is-4-fullhd{flex:none;width:33.33333337%}.column.is-offset-4-fullhd{margin-left:33.33333337%}.column.is-5-fullhd{flex:none;width:41.66666674%}.column.is-offset-5-fullhd{margin-left:41.66666674%}.column.is-6-fullhd{flex:none;width:50%}.column.is-offset-6-fullhd{margin-left:50%}.column.is-7-fullhd{flex:none;width:58.33333337%}.column.is-offset-7-fullhd{margin-left:58.33333337%}.column.is-8-fullhd{flex:none;width:66.66666674%}.column.is-offset-8-fullhd{margin-left:66.66666674%}.column.is-9-fullhd{flex:none;width:75%}.column.is-offset-9-fullhd{margin-left:75%}.column.is-10-fullhd{flex:none;width:83.33333337%}.column.is-offset-10-fullhd{margin-left:83.33333337%}.column.is-11-fullhd{flex:none;width:91.66666674%}.column.is-offset-11-fullhd{margin-left:91.66666674%}.column.is-12-fullhd{flex:none;width:100%}.column.is-offset-12-fullhd{margin-left:100%}}.columns{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}.columns:last-child{margin-bottom:-.75rem}.columns:not(:last-child){margin-bottom:calc(1.5rem - .75rem)}.columns.is-centered{justify-content:center}.columns.is-gapless{margin-left:0;margin-right:0;margin-top:0}.columns.is-gapless>.column{margin:0;padding:0 !important}.columns.is-gapless:not(:last-child){margin-bottom:1.5rem}.columns.is-gapless:last-child{margin-bottom:0}.columns.is-mobile{display:flex}.columns.is-multiline{flex-wrap:wrap}.columns.is-vcentered{align-items:center}@media screen and (min-width: 769px),print{.columns:not(.is-desktop){display:flex}}@media screen and (min-width: 1056px){.columns.is-desktop{display:flex}}.columns.is-variable{--columnGap: 0.75rem;margin-left:calc(-1 * var(--columnGap));margin-right:calc(-1 * var(--columnGap))}.columns.is-variable>.column{padding-left:var(--columnGap);padding-right:var(--columnGap)}.columns.is-variable.is-0{--columnGap: 0rem}@media screen and (max-width: 768px){.columns.is-variable.is-0-mobile{--columnGap: 0rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-0-tablet{--columnGap: 0rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-0-tablet-only{--columnGap: 0rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-0-touch{--columnGap: 0rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-0-desktop{--columnGap: 0rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-0-desktop-only{--columnGap: 0rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-0-widescreen{--columnGap: 0rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-0-widescreen-only{--columnGap: 0rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-0-fullhd{--columnGap: 0rem}}.columns.is-variable.is-1{--columnGap: .25rem}@media screen and (max-width: 768px){.columns.is-variable.is-1-mobile{--columnGap: .25rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-1-tablet{--columnGap: .25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-1-tablet-only{--columnGap: .25rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-1-touch{--columnGap: .25rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-1-desktop{--columnGap: .25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-1-desktop-only{--columnGap: .25rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-1-widescreen{--columnGap: .25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-1-widescreen-only{--columnGap: .25rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-1-fullhd{--columnGap: .25rem}}.columns.is-variable.is-2{--columnGap: .5rem}@media screen and (max-width: 768px){.columns.is-variable.is-2-mobile{--columnGap: .5rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-2-tablet{--columnGap: .5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-2-tablet-only{--columnGap: .5rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-2-touch{--columnGap: .5rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-2-desktop{--columnGap: .5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-2-desktop-only{--columnGap: .5rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-2-widescreen{--columnGap: .5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-2-widescreen-only{--columnGap: .5rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-2-fullhd{--columnGap: .5rem}}.columns.is-variable.is-3{--columnGap: .75rem}@media screen and (max-width: 768px){.columns.is-variable.is-3-mobile{--columnGap: .75rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-3-tablet{--columnGap: .75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-3-tablet-only{--columnGap: .75rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-3-touch{--columnGap: .75rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-3-desktop{--columnGap: .75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-3-desktop-only{--columnGap: .75rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-3-widescreen{--columnGap: .75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-3-widescreen-only{--columnGap: .75rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-3-fullhd{--columnGap: .75rem}}.columns.is-variable.is-4{--columnGap: 1rem}@media screen and (max-width: 768px){.columns.is-variable.is-4-mobile{--columnGap: 1rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-4-tablet{--columnGap: 1rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-4-tablet-only{--columnGap: 1rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-4-touch{--columnGap: 1rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-4-desktop{--columnGap: 1rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-4-desktop-only{--columnGap: 1rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-4-widescreen{--columnGap: 1rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-4-widescreen-only{--columnGap: 1rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-4-fullhd{--columnGap: 1rem}}.columns.is-variable.is-5{--columnGap: 1.25rem}@media screen and (max-width: 768px){.columns.is-variable.is-5-mobile{--columnGap: 1.25rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-5-tablet{--columnGap: 1.25rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-5-tablet-only{--columnGap: 1.25rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-5-touch{--columnGap: 1.25rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-5-desktop{--columnGap: 1.25rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-5-desktop-only{--columnGap: 1.25rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-5-widescreen{--columnGap: 1.25rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-5-widescreen-only{--columnGap: 1.25rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-5-fullhd{--columnGap: 1.25rem}}.columns.is-variable.is-6{--columnGap: 1.5rem}@media screen and (max-width: 768px){.columns.is-variable.is-6-mobile{--columnGap: 1.5rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-6-tablet{--columnGap: 1.5rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-6-tablet-only{--columnGap: 1.5rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-6-touch{--columnGap: 1.5rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-6-desktop{--columnGap: 1.5rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-6-desktop-only{--columnGap: 1.5rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-6-widescreen{--columnGap: 1.5rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-6-widescreen-only{--columnGap: 1.5rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-6-fullhd{--columnGap: 1.5rem}}.columns.is-variable.is-7{--columnGap: 1.75rem}@media screen and (max-width: 768px){.columns.is-variable.is-7-mobile{--columnGap: 1.75rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-7-tablet{--columnGap: 1.75rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-7-tablet-only{--columnGap: 1.75rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-7-touch{--columnGap: 1.75rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-7-desktop{--columnGap: 1.75rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-7-desktop-only{--columnGap: 1.75rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-7-widescreen{--columnGap: 1.75rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-7-widescreen-only{--columnGap: 1.75rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-7-fullhd{--columnGap: 1.75rem}}.columns.is-variable.is-8{--columnGap: 2rem}@media screen and (max-width: 768px){.columns.is-variable.is-8-mobile{--columnGap: 2rem}}@media screen and (min-width: 769px),print{.columns.is-variable.is-8-tablet{--columnGap: 2rem}}@media screen and (min-width: 769px) and (max-width: 1055px){.columns.is-variable.is-8-tablet-only{--columnGap: 2rem}}@media screen and (max-width: 1055px){.columns.is-variable.is-8-touch{--columnGap: 2rem}}@media screen and (min-width: 1056px){.columns.is-variable.is-8-desktop{--columnGap: 2rem}}@media screen and (min-width: 1056px) and (max-width: 1215px){.columns.is-variable.is-8-desktop-only{--columnGap: 2rem}}@media screen and (min-width: 1216px){.columns.is-variable.is-8-widescreen{--columnGap: 2rem}}@media screen and (min-width: 1216px) and (max-width: 1407px){.columns.is-variable.is-8-widescreen-only{--columnGap: 2rem}}@media screen and (min-width: 1408px){.columns.is-variable.is-8-fullhd{--columnGap: 2rem}}.tile{align-items:stretch;display:block;flex-basis:0;flex-grow:1;flex-shrink:1;min-height:min-content}.tile.is-ancestor{margin-left:-.75rem;margin-right:-.75rem;margin-top:-.75rem}.tile.is-ancestor:last-child{margin-bottom:-.75rem}.tile.is-ancestor:not(:last-child){margin-bottom:.75rem}.tile.is-child{margin:0 !important}.tile.is-parent{padding:.75rem}.tile.is-vertical{flex-direction:column}.tile.is-vertical>.tile.is-child:not(:last-child){margin-bottom:1.5rem !important}@media screen and (min-width: 769px),print{.tile:not(.is-child){display:flex}.tile.is-1{flex:none;width:8.33333337%}.tile.is-2{flex:none;width:16.66666674%}.tile.is-3{flex:none;width:25%}.tile.is-4{flex:none;width:33.33333337%}.tile.is-5{flex:none;width:41.66666674%}.tile.is-6{flex:none;width:50%}.tile.is-7{flex:none;width:58.33333337%}.tile.is-8{flex:none;width:66.66666674%}.tile.is-9{flex:none;width:75%}.tile.is-10{flex:none;width:83.33333337%}.tile.is-11{flex:none;width:91.66666674%}.tile.is-12{flex:none;width:100%}}.hero{align-items:stretch;display:flex;flex-direction:column;justify-content:space-between}.hero .navbar{background:none}.hero .tabs ul{border-bottom:none}.hero.is-white{background-color:#fff;color:#0a0a0a}.hero.is-white a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-white strong{color:inherit}.hero.is-white .title{color:#0a0a0a}.hero.is-white .subtitle{color:rgba(10,10,10,0.9)}.hero.is-white .subtitle a:not(.button),.hero.is-white .subtitle strong{color:#0a0a0a}@media screen and (max-width: 1055px){.hero.is-white .navbar-menu{background-color:#fff}}.hero.is-white .navbar-item,.hero.is-white .navbar-link{color:rgba(10,10,10,0.7)}.hero.is-white a.navbar-item:hover,.hero.is-white a.navbar-item.is-active,.hero.is-white .navbar-link:hover,.hero.is-white .navbar-link.is-active{background-color:#f2f2f2;color:#0a0a0a}.hero.is-white .tabs a{color:#0a0a0a;opacity:0.9}.hero.is-white .tabs a:hover{opacity:1}.hero.is-white .tabs li.is-active a{color:#fff !important;opacity:1}.hero.is-white .tabs.is-boxed a,.hero.is-white .tabs.is-toggle a{color:#0a0a0a}.hero.is-white .tabs.is-boxed a:hover,.hero.is-white .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-white .tabs.is-boxed li.is-active a,.hero.is-white .tabs.is-boxed li.is-active a:hover,.hero.is-white .tabs.is-toggle li.is-active a,.hero.is-white .tabs.is-toggle li.is-active a:hover{background-color:#0a0a0a;border-color:#0a0a0a;color:#fff}.hero.is-white.is-bold{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}@media screen and (max-width: 768px){.hero.is-white.is-bold .navbar-menu{background-image:linear-gradient(141deg, #e8e3e4 0%, #fff 71%, #fff 100%)}}.hero.is-black{background-color:#0a0a0a;color:#fff}.hero.is-black a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-black strong{color:inherit}.hero.is-black .title{color:#fff}.hero.is-black .subtitle{color:rgba(255,255,255,0.9)}.hero.is-black .subtitle a:not(.button),.hero.is-black .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-black .navbar-menu{background-color:#0a0a0a}}.hero.is-black .navbar-item,.hero.is-black .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-black a.navbar-item:hover,.hero.is-black a.navbar-item.is-active,.hero.is-black .navbar-link:hover,.hero.is-black .navbar-link.is-active{background-color:#000;color:#fff}.hero.is-black .tabs a{color:#fff;opacity:0.9}.hero.is-black .tabs a:hover{opacity:1}.hero.is-black .tabs li.is-active a{color:#0a0a0a !important;opacity:1}.hero.is-black .tabs.is-boxed a,.hero.is-black .tabs.is-toggle a{color:#fff}.hero.is-black .tabs.is-boxed a:hover,.hero.is-black .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-black .tabs.is-boxed li.is-active a,.hero.is-black .tabs.is-boxed li.is-active a:hover,.hero.is-black .tabs.is-toggle li.is-active a,.hero.is-black .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#0a0a0a}.hero.is-black.is-bold{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}@media screen and (max-width: 768px){.hero.is-black.is-bold .navbar-menu{background-image:linear-gradient(141deg, #000 0%, #0a0a0a 71%, #181616 100%)}}.hero.is-light{background-color:#f5f5f5;color:rgba(0,0,0,0.7)}.hero.is-light a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-light strong{color:inherit}.hero.is-light .title{color:rgba(0,0,0,0.7)}.hero.is-light .subtitle{color:rgba(0,0,0,0.9)}.hero.is-light .subtitle a:not(.button),.hero.is-light .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){.hero.is-light .navbar-menu{background-color:#f5f5f5}}.hero.is-light .navbar-item,.hero.is-light .navbar-link{color:rgba(0,0,0,0.7)}.hero.is-light a.navbar-item:hover,.hero.is-light a.navbar-item.is-active,.hero.is-light .navbar-link:hover,.hero.is-light .navbar-link.is-active{background-color:#e8e8e8;color:rgba(0,0,0,0.7)}.hero.is-light .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}.hero.is-light .tabs a:hover{opacity:1}.hero.is-light .tabs li.is-active a{color:#f5f5f5 !important;opacity:1}.hero.is-light .tabs.is-boxed a,.hero.is-light .tabs.is-toggle a{color:rgba(0,0,0,0.7)}.hero.is-light .tabs.is-boxed a:hover,.hero.is-light .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-light .tabs.is-boxed li.is-active a,.hero.is-light .tabs.is-boxed li.is-active a:hover,.hero.is-light .tabs.is-toggle li.is-active a,.hero.is-light .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#f5f5f5}.hero.is-light.is-bold{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}@media screen and (max-width: 768px){.hero.is-light.is-bold .navbar-menu{background-image:linear-gradient(141deg, #dfd8d9 0%, #f5f5f5 71%, #fff 100%)}}.hero.is-dark,.content kbd.hero{background-color:#363636;color:#fff}.hero.is-dark a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.content kbd.hero a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-dark strong,.content kbd.hero strong{color:inherit}.hero.is-dark .title,.content kbd.hero .title{color:#fff}.hero.is-dark .subtitle,.content kbd.hero .subtitle{color:rgba(255,255,255,0.9)}.hero.is-dark .subtitle a:not(.button),.content kbd.hero .subtitle a:not(.button),.hero.is-dark .subtitle strong,.content kbd.hero .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-dark .navbar-menu,.content kbd.hero .navbar-menu{background-color:#363636}}.hero.is-dark .navbar-item,.content kbd.hero .navbar-item,.hero.is-dark .navbar-link,.content kbd.hero .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-dark a.navbar-item:hover,.content kbd.hero a.navbar-item:hover,.hero.is-dark a.navbar-item.is-active,.content kbd.hero a.navbar-item.is-active,.hero.is-dark .navbar-link:hover,.content kbd.hero .navbar-link:hover,.hero.is-dark .navbar-link.is-active,.content kbd.hero .navbar-link.is-active{background-color:#292929;color:#fff}.hero.is-dark .tabs a,.content kbd.hero .tabs a{color:#fff;opacity:0.9}.hero.is-dark .tabs a:hover,.content kbd.hero .tabs a:hover{opacity:1}.hero.is-dark .tabs li.is-active a,.content kbd.hero .tabs li.is-active a{color:#363636 !important;opacity:1}.hero.is-dark .tabs.is-boxed a,.content kbd.hero .tabs.is-boxed a,.hero.is-dark .tabs.is-toggle a,.content kbd.hero .tabs.is-toggle a{color:#fff}.hero.is-dark .tabs.is-boxed a:hover,.content kbd.hero .tabs.is-boxed a:hover,.hero.is-dark .tabs.is-toggle a:hover,.content kbd.hero .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-dark .tabs.is-boxed li.is-active a,.content kbd.hero .tabs.is-boxed li.is-active a,.hero.is-dark .tabs.is-boxed li.is-active a:hover,.hero.is-dark .tabs.is-toggle li.is-active a,.content kbd.hero .tabs.is-toggle li.is-active a,.hero.is-dark .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#363636}.hero.is-dark.is-bold,.content kbd.hero.is-bold{background-image:linear-gradient(141deg, #1f191a 0%, #363636 71%, #46403f 100%)}@media screen and (max-width: 768px){.hero.is-dark.is-bold .navbar-menu,.content kbd.hero.is-bold .navbar-menu{background-image:linear-gradient(141deg, #1f191a 0%, #363636 71%, #46403f 100%)}}.hero.is-primary,.docstring>section>a.hero.docs-sourcelink{background-color:#4eb5de;color:#fff}.hero.is-primary a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.docstring>section>a.hero.docs-sourcelink a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-primary strong,.docstring>section>a.hero.docs-sourcelink strong{color:inherit}.hero.is-primary .title,.docstring>section>a.hero.docs-sourcelink .title{color:#fff}.hero.is-primary .subtitle,.docstring>section>a.hero.docs-sourcelink .subtitle{color:rgba(255,255,255,0.9)}.hero.is-primary .subtitle a:not(.button),.docstring>section>a.hero.docs-sourcelink .subtitle a:not(.button),.hero.is-primary .subtitle strong,.docstring>section>a.hero.docs-sourcelink .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-primary .navbar-menu,.docstring>section>a.hero.docs-sourcelink .navbar-menu{background-color:#4eb5de}}.hero.is-primary .navbar-item,.docstring>section>a.hero.docs-sourcelink .navbar-item,.hero.is-primary .navbar-link,.docstring>section>a.hero.docs-sourcelink .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-primary a.navbar-item:hover,.docstring>section>a.hero.docs-sourcelink a.navbar-item:hover,.hero.is-primary a.navbar-item.is-active,.docstring>section>a.hero.docs-sourcelink a.navbar-item.is-active,.hero.is-primary .navbar-link:hover,.docstring>section>a.hero.docs-sourcelink .navbar-link:hover,.hero.is-primary .navbar-link.is-active,.docstring>section>a.hero.docs-sourcelink .navbar-link.is-active{background-color:#39acda;color:#fff}.hero.is-primary .tabs a,.docstring>section>a.hero.docs-sourcelink .tabs a{color:#fff;opacity:0.9}.hero.is-primary .tabs a:hover,.docstring>section>a.hero.docs-sourcelink .tabs a:hover{opacity:1}.hero.is-primary .tabs li.is-active a,.docstring>section>a.hero.docs-sourcelink .tabs li.is-active a{color:#4eb5de !important;opacity:1}.hero.is-primary .tabs.is-boxed a,.docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a,.hero.is-primary .tabs.is-toggle a,.docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a{color:#fff}.hero.is-primary .tabs.is-boxed a:hover,.docstring>section>a.hero.docs-sourcelink .tabs.is-boxed a:hover,.hero.is-primary .tabs.is-toggle a:hover,.docstring>section>a.hero.docs-sourcelink .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-primary .tabs.is-boxed li.is-active a,.docstring>section>a.hero.docs-sourcelink .tabs.is-boxed li.is-active a,.hero.is-primary .tabs.is-boxed li.is-active a:hover,.hero.is-primary .tabs.is-toggle li.is-active a,.docstring>section>a.hero.docs-sourcelink .tabs.is-toggle li.is-active a,.hero.is-primary .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#4eb5de}.hero.is-primary.is-bold,.docstring>section>a.hero.is-bold.docs-sourcelink{background-image:linear-gradient(141deg, #1bc7de 0%, #4eb5de 71%, #5fa9e7 100%)}@media screen and (max-width: 768px){.hero.is-primary.is-bold .navbar-menu,.docstring>section>a.hero.is-bold.docs-sourcelink .navbar-menu{background-image:linear-gradient(141deg, #1bc7de 0%, #4eb5de 71%, #5fa9e7 100%)}}.hero.is-link{background-color:#2e63b8;color:#fff}.hero.is-link a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-link strong{color:inherit}.hero.is-link .title{color:#fff}.hero.is-link .subtitle{color:rgba(255,255,255,0.9)}.hero.is-link .subtitle a:not(.button),.hero.is-link .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-link .navbar-menu{background-color:#2e63b8}}.hero.is-link .navbar-item,.hero.is-link .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-link a.navbar-item:hover,.hero.is-link a.navbar-item.is-active,.hero.is-link .navbar-link:hover,.hero.is-link .navbar-link.is-active{background-color:#2958a4;color:#fff}.hero.is-link .tabs a{color:#fff;opacity:0.9}.hero.is-link .tabs a:hover{opacity:1}.hero.is-link .tabs li.is-active a{color:#2e63b8 !important;opacity:1}.hero.is-link .tabs.is-boxed a,.hero.is-link .tabs.is-toggle a{color:#fff}.hero.is-link .tabs.is-boxed a:hover,.hero.is-link .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-link .tabs.is-boxed li.is-active a,.hero.is-link .tabs.is-boxed li.is-active a:hover,.hero.is-link .tabs.is-toggle li.is-active a,.hero.is-link .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#2e63b8}.hero.is-link.is-bold{background-image:linear-gradient(141deg, #1b6098 0%, #2e63b8 71%, #2d51d2 100%)}@media screen and (max-width: 768px){.hero.is-link.is-bold .navbar-menu{background-image:linear-gradient(141deg, #1b6098 0%, #2e63b8 71%, #2d51d2 100%)}}.hero.is-info{background-color:#209cee;color:#fff}.hero.is-info a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-info strong{color:inherit}.hero.is-info .title{color:#fff}.hero.is-info .subtitle{color:rgba(255,255,255,0.9)}.hero.is-info .subtitle a:not(.button),.hero.is-info .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-info .navbar-menu{background-color:#209cee}}.hero.is-info .navbar-item,.hero.is-info .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-info a.navbar-item:hover,.hero.is-info a.navbar-item.is-active,.hero.is-info .navbar-link:hover,.hero.is-info .navbar-link.is-active{background-color:#1190e3;color:#fff}.hero.is-info .tabs a{color:#fff;opacity:0.9}.hero.is-info .tabs a:hover{opacity:1}.hero.is-info .tabs li.is-active a{color:#209cee !important;opacity:1}.hero.is-info .tabs.is-boxed a,.hero.is-info .tabs.is-toggle a{color:#fff}.hero.is-info .tabs.is-boxed a:hover,.hero.is-info .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-info .tabs.is-boxed li.is-active a,.hero.is-info .tabs.is-boxed li.is-active a:hover,.hero.is-info .tabs.is-toggle li.is-active a,.hero.is-info .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#209cee}.hero.is-info.is-bold{background-image:linear-gradient(141deg, #05a6d6 0%, #209cee 71%, #3287f5 100%)}@media screen and (max-width: 768px){.hero.is-info.is-bold .navbar-menu{background-image:linear-gradient(141deg, #05a6d6 0%, #209cee 71%, #3287f5 100%)}}.hero.is-success{background-color:#22c35b;color:#fff}.hero.is-success a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-success strong{color:inherit}.hero.is-success .title{color:#fff}.hero.is-success .subtitle{color:rgba(255,255,255,0.9)}.hero.is-success .subtitle a:not(.button),.hero.is-success .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-success .navbar-menu{background-color:#22c35b}}.hero.is-success .navbar-item,.hero.is-success .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-success a.navbar-item:hover,.hero.is-success a.navbar-item.is-active,.hero.is-success .navbar-link:hover,.hero.is-success .navbar-link.is-active{background-color:#1ead51;color:#fff}.hero.is-success .tabs a{color:#fff;opacity:0.9}.hero.is-success .tabs a:hover{opacity:1}.hero.is-success .tabs li.is-active a{color:#22c35b !important;opacity:1}.hero.is-success .tabs.is-boxed a,.hero.is-success .tabs.is-toggle a{color:#fff}.hero.is-success .tabs.is-boxed a:hover,.hero.is-success .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-success .tabs.is-boxed li.is-active a,.hero.is-success .tabs.is-boxed li.is-active a:hover,.hero.is-success .tabs.is-toggle li.is-active a,.hero.is-success .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#22c35b}.hero.is-success.is-bold{background-image:linear-gradient(141deg, #12a02c 0%, #22c35b 71%, #1fdf83 100%)}@media screen and (max-width: 768px){.hero.is-success.is-bold .navbar-menu{background-image:linear-gradient(141deg, #12a02c 0%, #22c35b 71%, #1fdf83 100%)}}.hero.is-warning{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.hero.is-warning a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-warning strong{color:inherit}.hero.is-warning .title{color:rgba(0,0,0,0.7)}.hero.is-warning .subtitle{color:rgba(0,0,0,0.9)}.hero.is-warning .subtitle a:not(.button),.hero.is-warning .subtitle strong{color:rgba(0,0,0,0.7)}@media screen and (max-width: 1055px){.hero.is-warning .navbar-menu{background-color:#ffdd57}}.hero.is-warning .navbar-item,.hero.is-warning .navbar-link{color:rgba(0,0,0,0.7)}.hero.is-warning a.navbar-item:hover,.hero.is-warning a.navbar-item.is-active,.hero.is-warning .navbar-link:hover,.hero.is-warning .navbar-link.is-active{background-color:#ffd83e;color:rgba(0,0,0,0.7)}.hero.is-warning .tabs a{color:rgba(0,0,0,0.7);opacity:0.9}.hero.is-warning .tabs a:hover{opacity:1}.hero.is-warning .tabs li.is-active a{color:#ffdd57 !important;opacity:1}.hero.is-warning .tabs.is-boxed a,.hero.is-warning .tabs.is-toggle a{color:rgba(0,0,0,0.7)}.hero.is-warning .tabs.is-boxed a:hover,.hero.is-warning .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-warning .tabs.is-boxed li.is-active a,.hero.is-warning .tabs.is-boxed li.is-active a:hover,.hero.is-warning .tabs.is-toggle li.is-active a,.hero.is-warning .tabs.is-toggle li.is-active a:hover{background-color:rgba(0,0,0,0.7);border-color:rgba(0,0,0,0.7);color:#ffdd57}.hero.is-warning.is-bold{background-image:linear-gradient(141deg, #ffae24 0%, #ffdd57 71%, #fffa71 100%)}@media screen and (max-width: 768px){.hero.is-warning.is-bold .navbar-menu{background-image:linear-gradient(141deg, #ffae24 0%, #ffdd57 71%, #fffa71 100%)}}.hero.is-danger{background-color:#da0b00;color:#fff}.hero.is-danger a:not(.button):not(.dropdown-item):not(.tag):not(.pagination-link.is-current),.hero.is-danger strong{color:inherit}.hero.is-danger .title{color:#fff}.hero.is-danger .subtitle{color:rgba(255,255,255,0.9)}.hero.is-danger .subtitle a:not(.button),.hero.is-danger .subtitle strong{color:#fff}@media screen and (max-width: 1055px){.hero.is-danger .navbar-menu{background-color:#da0b00}}.hero.is-danger .navbar-item,.hero.is-danger .navbar-link{color:rgba(255,255,255,0.7)}.hero.is-danger a.navbar-item:hover,.hero.is-danger a.navbar-item.is-active,.hero.is-danger .navbar-link:hover,.hero.is-danger .navbar-link.is-active{background-color:#c10a00;color:#fff}.hero.is-danger .tabs a{color:#fff;opacity:0.9}.hero.is-danger .tabs a:hover{opacity:1}.hero.is-danger .tabs li.is-active a{color:#da0b00 !important;opacity:1}.hero.is-danger .tabs.is-boxed a,.hero.is-danger .tabs.is-toggle a{color:#fff}.hero.is-danger .tabs.is-boxed a:hover,.hero.is-danger .tabs.is-toggle a:hover{background-color:rgba(10,10,10,0.1)}.hero.is-danger .tabs.is-boxed li.is-active a,.hero.is-danger .tabs.is-boxed li.is-active a:hover,.hero.is-danger .tabs.is-toggle li.is-active a,.hero.is-danger .tabs.is-toggle li.is-active a:hover{background-color:#fff;border-color:#fff;color:#da0b00}.hero.is-danger.is-bold{background-image:linear-gradient(141deg, #a70013 0%, #da0b00 71%, #f43500 100%)}@media screen and (max-width: 768px){.hero.is-danger.is-bold .navbar-menu{background-image:linear-gradient(141deg, #a70013 0%, #da0b00 71%, #f43500 100%)}}.hero.is-small .hero-body,#documenter .docs-sidebar form.docs-search>input.hero .hero-body{padding:1.5rem}@media screen and (min-width: 769px),print{.hero.is-medium .hero-body{padding:9rem 4.5rem}}@media screen and (min-width: 769px),print{.hero.is-large .hero-body{padding:18rem 6rem}}.hero.is-halfheight .hero-body,.hero.is-fullheight .hero-body,.hero.is-fullheight-with-navbar .hero-body{align-items:center;display:flex}.hero.is-halfheight .hero-body>.container,.hero.is-fullheight .hero-body>.container,.hero.is-fullheight-with-navbar .hero-body>.container{flex-grow:1;flex-shrink:1}.hero.is-halfheight{min-height:50vh}.hero.is-fullheight{min-height:100vh}.hero-video{overflow:hidden}.hero-video video{left:50%;min-height:100%;min-width:100%;position:absolute;top:50%;transform:translate3d(-50%, -50%, 0)}.hero-video.is-transparent{opacity:0.3}@media screen and (max-width: 768px){.hero-video{display:none}}.hero-buttons{margin-top:1.5rem}@media screen and (max-width: 768px){.hero-buttons .button{display:flex}.hero-buttons .button:not(:last-child){margin-bottom:0.75rem}}@media screen and (min-width: 769px),print{.hero-buttons{display:flex;justify-content:center}.hero-buttons .button:not(:last-child){margin-right:1.5rem}}.hero-head,.hero-foot{flex-grow:0;flex-shrink:0}.hero-body{flex-grow:1;flex-shrink:0;padding:3rem 1.5rem}@media screen and (min-width: 769px),print{.hero-body{padding:3rem 3rem}}.section{padding:3rem 1.5rem}@media screen and (min-width: 1056px){.section{padding:3rem 3rem}.section.is-medium{padding:9rem 4.5rem}.section.is-large{padding:18rem 6rem}}.footer{background-color:#fafafa;padding:3rem 1.5rem 6rem}h1 .docs-heading-anchor,h1 .docs-heading-anchor:hover,h1 .docs-heading-anchor:visited,h2 .docs-heading-anchor,h2 .docs-heading-anchor:hover,h2 .docs-heading-anchor:visited,h3 .docs-heading-anchor,h3 .docs-heading-anchor:hover,h3 .docs-heading-anchor:visited,h4 .docs-heading-anchor,h4 .docs-heading-anchor:hover,h4 .docs-heading-anchor:visited,h5 .docs-heading-anchor,h5 .docs-heading-anchor:hover,h5 .docs-heading-anchor:visited,h6 .docs-heading-anchor,h6 .docs-heading-anchor:hover,h6 .docs-heading-anchor:visited{color:#222}h1 .docs-heading-anchor-permalink,h2 .docs-heading-anchor-permalink,h3 .docs-heading-anchor-permalink,h4 .docs-heading-anchor-permalink,h5 .docs-heading-anchor-permalink,h6 .docs-heading-anchor-permalink{visibility:hidden;vertical-align:middle;margin-left:0.5em;font-size:0.7rem}h1 .docs-heading-anchor-permalink::before,h2 .docs-heading-anchor-permalink::before,h3 .docs-heading-anchor-permalink::before,h4 .docs-heading-anchor-permalink::before,h5 .docs-heading-anchor-permalink::before,h6 .docs-heading-anchor-permalink::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f0c1"}h1:hover .docs-heading-anchor-permalink,h2:hover .docs-heading-anchor-permalink,h3:hover .docs-heading-anchor-permalink,h4:hover .docs-heading-anchor-permalink,h5:hover .docs-heading-anchor-permalink,h6:hover .docs-heading-anchor-permalink{visibility:visible}.docs-dark-only{display:none !important}pre{position:relative;overflow:hidden}pre code,pre code.hljs{padding:0 .75rem !important;overflow:auto;display:block}pre code:first-of-type,pre code.hljs:first-of-type{padding-top:0.5rem !important}pre code:last-of-type,pre code.hljs:last-of-type{padding-bottom:0.5rem !important}pre .copy-button{opacity:0.2;transition:opacity 0.2s;position:absolute;right:0em;top:0em;padding:0.5em;width:2.5em;height:2.5em;background:transparent;border:none;font-family:"Font Awesome 6 Free";color:#222;cursor:pointer;text-align:center}pre .copy-button:focus,pre .copy-button:hover{opacity:1;background:rgba(34,34,34,0.1);color:#2e63b8}pre .copy-button.success{color:#259a12;opacity:1}pre .copy-button.error{color:#cb3c33;opacity:1}pre:hover .copy-button{opacity:1}.admonition{background-color:#b5b5b5;border-style:solid;border-width:1px;border-color:#363636;border-radius:4px;font-size:1rem}.admonition strong{color:currentColor}.admonition.is-small,#documenter .docs-sidebar form.docs-search>input.admonition{font-size:.75rem}.admonition.is-medium{font-size:1.25rem}.admonition.is-large{font-size:1.5rem}.admonition.is-default{background-color:#b5b5b5;border-color:#363636}.admonition.is-default>.admonition-header{background-color:#363636;color:#fff}.admonition.is-default>.admonition-body{color:#fff}.admonition.is-info{background-color:#def0fc;border-color:#209cee}.admonition.is-info>.admonition-header{background-color:#209cee;color:#fff}.admonition.is-info>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-success{background-color:#bdf4d1;border-color:#22c35b}.admonition.is-success>.admonition-header{background-color:#22c35b;color:#fff}.admonition.is-success>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-warning{background-color:#fff3c5;border-color:#ffdd57}.admonition.is-warning>.admonition-header{background-color:#ffdd57;color:rgba(0,0,0,0.7)}.admonition.is-warning>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-danger{background-color:#ffaba7;border-color:#da0b00}.admonition.is-danger>.admonition-header{background-color:#da0b00;color:#fff}.admonition.is-danger>.admonition-body{color:rgba(0,0,0,0.7)}.admonition.is-compat{background-color:#bdeff5;border-color:#1db5c9}.admonition.is-compat>.admonition-header{background-color:#1db5c9;color:#fff}.admonition.is-compat>.admonition-body{color:rgba(0,0,0,0.7)}.admonition-header{color:#fff;background-color:#363636;align-items:center;font-weight:700;justify-content:space-between;line-height:1.25;padding:0.5rem .75rem;position:relative}.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;margin-right:.75rem;content:"\f06a"}details.admonition.is-details>.admonition-header{list-style:none}details.admonition.is-details>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f055"}details.admonition.is-details[open]>.admonition-header:before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f056"}.admonition-body{color:#222;padding:0.5rem .75rem}.admonition-body pre{background-color:#f5f5f5}.admonition-body code{background-color:rgba(0,0,0,0.05)}.docstring{margin-bottom:1em;background-color:rgba(0,0,0,0);border:1px solid #dbdbdb;box-shadow:2px 2px 3px rgba(10,10,10,0.1);max-width:100%}.docstring>header{cursor:pointer;display:flex;flex-grow:1;align-items:stretch;padding:0.5rem .75rem;background-color:#f5f5f5;box-shadow:0 0.125em 0.25em rgba(10,10,10,0.1);box-shadow:none;border-bottom:1px solid #dbdbdb}.docstring>header code{background-color:transparent}.docstring>header .docstring-article-toggle-button{min-width:1.1rem;padding:0.2rem 0.2rem 0.2rem 0}.docstring>header .docstring-binding{margin-right:0.3em}.docstring>header .docstring-category{margin-left:0.3em}.docstring>section{position:relative;padding:.75rem .75rem;border-bottom:1px solid #dbdbdb}.docstring>section:last-child{border-bottom:none}.docstring>section>a.docs-sourcelink{transition:opacity 0.3s;opacity:0;position:absolute;right:.375rem;bottom:.375rem}.docstring>section>a.docs-sourcelink:focus{opacity:1 !important}.docstring:hover>section>a.docs-sourcelink{opacity:0.2}.docstring:focus-within>section>a.docs-sourcelink{opacity:0.2}.docstring>section:hover a.docs-sourcelink{opacity:1}.documenter-example-output{background-color:#fff}.outdated-warning-overlay{position:fixed;top:0;left:0;right:0;box-shadow:0 0 10px rgba(0,0,0,0.3);z-index:999;background-color:#ffaba7;color:rgba(0,0,0,0.7);border-bottom:3px solid #da0b00;padding:10px 35px;text-align:center;font-size:15px}.outdated-warning-overlay .outdated-warning-closer{position:absolute;top:calc(50% - 10px);right:18px;cursor:pointer;width:12px}.outdated-warning-overlay a{color:#2e63b8}.outdated-warning-overlay a:hover{color:#363636}.content pre{border:1px solid #dbdbdb}.content code{font-weight:inherit}.content a code{color:#2e63b8}.content h1 code,.content h2 code,.content h3 code,.content h4 code,.content h5 code,.content h6 code{color:#222}.content table{display:block;width:initial;max-width:100%;overflow-x:auto}.content blockquote>ul:first-child,.content blockquote>ol:first-child,.content .admonition-body>ul:first-child,.content .admonition-body>ol:first-child{margin-top:0}pre,code{font-variant-ligatures:no-contextual}.breadcrumb a.is-disabled{cursor:default;pointer-events:none}.breadcrumb a.is-disabled,.breadcrumb a.is-disabled:hover{color:#222}.hljs{background:initial !important}.katex .katex-mathml{top:0;right:0}.katex-display,mjx-container,.MathJax_Display{margin:0.5em 0 !important}html{-moz-osx-font-smoothing:auto;-webkit-font-smoothing:auto}li.no-marker{list-style:none}#documenter .docs-main>article{overflow-wrap:break-word}#documenter .docs-main>article .math-container{overflow-x:auto;overflow-y:hidden}@media screen and (min-width: 1056px){#documenter .docs-main{max-width:52rem;margin-left:20rem;padding-right:1rem}}@media screen and (max-width: 1055px){#documenter .docs-main{width:100%}#documenter .docs-main>article{max-width:52rem;margin-left:auto;margin-right:auto;margin-bottom:1rem;padding:0 1rem}#documenter .docs-main>header,#documenter .docs-main>nav{max-width:100%;width:100%;margin:0}}#documenter .docs-main header.docs-navbar{background-color:#fff;border-bottom:1px solid #dbdbdb;z-index:2;min-height:4rem;margin-bottom:1rem;display:flex}#documenter .docs-main header.docs-navbar .breadcrumb{flex-grow:1}#documenter .docs-main header.docs-navbar .docs-sidebar-button{display:block;font-size:1.5rem;padding-bottom:0.1rem;margin-right:1rem}#documenter .docs-main header.docs-navbar .docs-right{display:flex;white-space:nowrap;gap:1rem;align-items:center}#documenter .docs-main header.docs-navbar .docs-right .docs-icon,#documenter .docs-main header.docs-navbar .docs-right .docs-label{display:inline-block}#documenter .docs-main header.docs-navbar .docs-right .docs-label{padding:0;margin-left:0.3em}@media screen and (max-width: 1055px){#documenter .docs-main header.docs-navbar .docs-right .docs-navbar-link{margin-left:0.4rem;margin-right:0.4rem}}#documenter .docs-main header.docs-navbar>*{margin:auto 0}@media screen and (max-width: 1055px){#documenter .docs-main header.docs-navbar{position:sticky;top:0;padding:0 1rem;transition-property:top, box-shadow;-webkit-transition-property:top, box-shadow;transition-duration:0.3s;-webkit-transition-duration:0.3s}#documenter .docs-main header.docs-navbar.headroom--not-top{box-shadow:.2rem 0rem .4rem #bbb;transition-duration:0.7s;-webkit-transition-duration:0.7s}#documenter .docs-main header.docs-navbar.headroom--unpinned.headroom--not-top.headroom--not-bottom{top:-4.5rem;transition-duration:0.7s;-webkit-transition-duration:0.7s}}#documenter .docs-main section.footnotes{border-top:1px solid #dbdbdb}#documenter .docs-main section.footnotes li .tag:first-child,#documenter .docs-main section.footnotes li .docstring>section>a.docs-sourcelink:first-child,#documenter .docs-main section.footnotes li .content kbd:first-child,.content #documenter .docs-main section.footnotes li kbd:first-child{margin-right:1em;margin-bottom:0.4em}#documenter .docs-main .docs-footer{display:flex;flex-wrap:wrap;margin-left:0;margin-right:0;border-top:1px solid #dbdbdb;padding-top:1rem;padding-bottom:1rem}@media screen and (max-width: 1055px){#documenter .docs-main .docs-footer{padding-left:1rem;padding-right:1rem}}#documenter .docs-main .docs-footer .docs-footer-nextpage,#documenter .docs-main .docs-footer .docs-footer-prevpage{flex-grow:1}#documenter .docs-main .docs-footer .docs-footer-nextpage{text-align:right}#documenter .docs-main .docs-footer .flexbox-break{flex-basis:100%;height:0}#documenter .docs-main .docs-footer .footer-message{font-size:0.8em;margin:0.5em auto 0 auto;text-align:center}#documenter .docs-sidebar{display:flex;flex-direction:column;color:#0a0a0a;background-color:#f5f5f5;border-right:1px solid #dbdbdb;padding:0;flex:0 0 18rem;z-index:5;font-size:1rem;position:fixed;left:-18rem;width:18rem;height:100%;transition:left 0.3s}#documenter .docs-sidebar.visible{left:0;box-shadow:.4rem 0rem .8rem #bbb}@media screen and (min-width: 1056px){#documenter .docs-sidebar.visible{box-shadow:none}}@media screen and (min-width: 1056px){#documenter .docs-sidebar{left:0;top:0}}#documenter .docs-sidebar .docs-logo{margin-top:1rem;padding:0 1rem}#documenter .docs-sidebar .docs-logo>img{max-height:6rem;margin:auto}#documenter .docs-sidebar .docs-package-name{flex-shrink:0;font-size:1.5rem;font-weight:700;text-align:center;white-space:nowrap;overflow:hidden;padding:0.5rem 0}#documenter .docs-sidebar .docs-package-name .docs-autofit{max-width:16.2rem}#documenter .docs-sidebar .docs-package-name a,#documenter .docs-sidebar .docs-package-name a:hover{color:#0a0a0a}#documenter .docs-sidebar .docs-version-selector{border-top:1px solid #dbdbdb;display:none;padding:0.5rem}#documenter .docs-sidebar .docs-version-selector.visible{display:flex}#documenter .docs-sidebar ul.docs-menu{flex-grow:1;user-select:none;border-top:1px solid #dbdbdb;padding-bottom:1.5rem}#documenter .docs-sidebar ul.docs-menu>li>.tocitem{font-weight:bold}#documenter .docs-sidebar ul.docs-menu>li li{font-size:.95rem;margin-left:1em;border-left:1px solid #dbdbdb}#documenter .docs-sidebar ul.docs-menu input.collapse-toggle{display:none}#documenter .docs-sidebar ul.docs-menu ul.collapsed{display:none}#documenter .docs-sidebar ul.docs-menu input:checked~ul.collapsed{display:block}#documenter .docs-sidebar ul.docs-menu label.tocitem{display:flex}#documenter .docs-sidebar ul.docs-menu label.tocitem .docs-label{flex-grow:2}#documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron{display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-size:.75rem;margin-left:1rem;margin-top:auto;margin-bottom:auto}#documenter .docs-sidebar ul.docs-menu label.tocitem .docs-chevron::before{font-family:"Font Awesome 6 Free";font-weight:900;content:"\f054"}#documenter .docs-sidebar ul.docs-menu input:checked~label.tocitem .docs-chevron::before{content:"\f078"}#documenter .docs-sidebar ul.docs-menu .tocitem{display:block;padding:0.5rem 0.5rem}#documenter .docs-sidebar ul.docs-menu .tocitem,#documenter .docs-sidebar ul.docs-menu .tocitem:hover{color:#0a0a0a;background:#f5f5f5}#documenter .docs-sidebar ul.docs-menu a.tocitem:hover,#documenter .docs-sidebar ul.docs-menu label.tocitem:hover{color:#0a0a0a;background-color:#ebebeb}#documenter .docs-sidebar ul.docs-menu li.is-active{border-top:1px solid #dbdbdb;border-bottom:1px solid #dbdbdb;background-color:#fff}#documenter .docs-sidebar ul.docs-menu li.is-active .tocitem,#documenter .docs-sidebar ul.docs-menu li.is-active .tocitem:hover{background-color:#fff;color:#0a0a0a}#documenter .docs-sidebar ul.docs-menu li.is-active ul.internal .tocitem:hover{background-color:#ebebeb;color:#0a0a0a}#documenter .docs-sidebar ul.docs-menu>li.is-active:first-child{border-top:none}#documenter .docs-sidebar ul.docs-menu ul.internal{margin:0 0.5rem 0.5rem;border-top:1px solid #dbdbdb}#documenter .docs-sidebar ul.docs-menu ul.internal li{font-size:.85rem;border-left:none;margin-left:0;margin-top:0.5rem}#documenter .docs-sidebar ul.docs-menu ul.internal .tocitem{width:100%;padding:0}#documenter .docs-sidebar ul.docs-menu ul.internal .tocitem::before{content:"⚬";margin-right:0.4em}#documenter .docs-sidebar form.docs-search{margin:auto;margin-top:0.5rem;margin-bottom:0.5rem}#documenter .docs-sidebar form.docs-search>input{width:14.4rem}#documenter .docs-sidebar #documenter-search-query{color:#707070;width:14.4rem;box-shadow:inset 0 1px 2px rgba(10,10,10,0.1)}@media screen and (min-width: 1056px){#documenter .docs-sidebar ul.docs-menu{overflow-y:auto;-webkit-overflow-scroll:touch}#documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar{width:.3rem;background:none}#documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#e0e0e0}#documenter .docs-sidebar ul.docs-menu::-webkit-scrollbar-thumb:hover{background:#ccc}}@media screen and (max-width: 1055px){#documenter .docs-sidebar{overflow-y:auto;-webkit-overflow-scroll:touch}#documenter .docs-sidebar::-webkit-scrollbar{width:.3rem;background:none}#documenter .docs-sidebar::-webkit-scrollbar-thumb{border-radius:5px 0px 0px 5px;background:#e0e0e0}#documenter .docs-sidebar::-webkit-scrollbar-thumb:hover{background:#ccc}}kbd.search-modal-key-hints{border-radius:0.25rem;border:1px solid rgba(0,0,0,0.6);box-shadow:0 2px 0 1px rgba(0,0,0,0.6);cursor:default;font-size:0.9rem;line-height:1.5;min-width:0.75rem;text-align:center;padding:0.1rem 0.3rem;position:relative;top:-1px}.search-min-width-50{min-width:50%}.search-min-height-100{min-height:100%}.search-modal-card-body{max-height:calc(100vh - 15rem)}.search-result-link{border-radius:0.7em;transition:all 300ms}.search-result-link:hover,.search-result-link:focus{background-color:rgba(0,128,128,0.1)}.search-result-link .property-search-result-badge,.search-result-link .search-filter{transition:all 300ms}.property-search-result-badge,.search-filter{padding:0.15em 0.5em;font-size:0.8em;font-style:italic;text-transform:none !important;line-height:1.5;color:#f5f5f5;background-color:rgba(51,65,85,0.501961);border-radius:0.6rem}.search-result-link:hover .property-search-result-badge,.search-result-link:hover .search-filter,.search-result-link:focus .property-search-result-badge,.search-result-link:focus .search-filter{color:#f1f5f9;background-color:#333}.search-filter{color:#333;background-color:#f5f5f5;transition:all 300ms}.search-filter:hover,.search-filter:focus{color:#333}.search-filter-selected{color:#f5f5f5;background-color:rgba(139,0,139,0.5)}.search-filter-selected:hover,.search-filter-selected:focus{color:#f5f5f5}.search-result-highlight{background-color:#ffdd57;color:black}.search-divider{border-bottom:1px solid #dbdbdb}.search-result-title{width:85%;color:#333}.search-result-code-title{font-size:0.875rem;font-family:"JuliaMono","SFMono-Regular","Menlo","Consolas","Liberation Mono","DejaVu Sans Mono",monospace}#search-modal .modal-card-body::-webkit-scrollbar,#search-modal .filter-tabs::-webkit-scrollbar{height:10px;width:10px;background-color:transparent}#search-modal .modal-card-body::-webkit-scrollbar-thumb,#search-modal .filter-tabs::-webkit-scrollbar-thumb{background-color:gray;border-radius:1rem}#search-modal .modal-card-body::-webkit-scrollbar-track,#search-modal .filter-tabs::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,0.6);background-color:transparent}.w-100{width:100%}.gap-2{gap:0.5rem}.gap-4{gap:1rem}.gap-8{gap:2rem}.ansi span.sgr1{font-weight:bolder}.ansi span.sgr2{font-weight:lighter}.ansi span.sgr3{font-style:italic}.ansi span.sgr4{text-decoration:underline}.ansi span.sgr7{color:#fff;background-color:#222}.ansi span.sgr8{color:transparent}.ansi span.sgr8 span{color:transparent}.ansi span.sgr9{text-decoration:line-through}.ansi span.sgr30{color:#242424}.ansi span.sgr31{color:#a7201f}.ansi span.sgr32{color:#066f00}.ansi span.sgr33{color:#856b00}.ansi span.sgr34{color:#2149b0}.ansi span.sgr35{color:#7d4498}.ansi span.sgr36{color:#007989}.ansi span.sgr37{color:gray}.ansi span.sgr40{background-color:#242424}.ansi span.sgr41{background-color:#a7201f}.ansi span.sgr42{background-color:#066f00}.ansi span.sgr43{background-color:#856b00}.ansi span.sgr44{background-color:#2149b0}.ansi span.sgr45{background-color:#7d4498}.ansi span.sgr46{background-color:#007989}.ansi span.sgr47{background-color:gray}.ansi span.sgr90{color:#616161}.ansi span.sgr91{color:#cb3c33}.ansi span.sgr92{color:#0e8300}.ansi span.sgr93{color:#a98800}.ansi span.sgr94{color:#3c5dcd}.ansi span.sgr95{color:#9256af}.ansi span.sgr96{color:#008fa3}.ansi span.sgr97{color:#f5f5f5}.ansi span.sgr100{background-color:#616161}.ansi span.sgr101{background-color:#cb3c33}.ansi span.sgr102{background-color:#0e8300}.ansi span.sgr103{background-color:#a98800}.ansi span.sgr104{background-color:#3c5dcd}.ansi span.sgr105{background-color:#9256af}.ansi span.sgr106{background-color:#008fa3}.ansi span.sgr107{background-color:#f5f5f5}code.language-julia-repl>span.hljs-meta{color:#066f00;font-weight:bolder}/*! Theme: Default Description: Original highlight.js style Author: (c) Ivan Sagalaev @@ -6,4 +6,4 @@ Website: https://highlightjs.org/ License: see project LICENSE Touched: 2021 -*/pre code.hljs{display:block;overflow-x:auto}code.hljs{padding:3px 5px}.hljs{background:#F0F0F0;color:#444}.hljs-comment{color:#888888}.hljs-tag,.hljs-punctuation{color:#444a}.hljs-tag .hljs-name,.hljs-tag .hljs-attr{color:#444}.hljs-keyword,.hljs-attribute,.hljs-selector-tag,.hljs-meta .hljs-keyword,.hljs-doctag,.hljs-name{font-weight:bold}.hljs-type,.hljs-string,.hljs-number,.hljs-selector-id,.hljs-selector-class,.hljs-quote,.hljs-template-tag,.hljs-deletion{color:#880000}.hljs-title,.hljs-section{color:#880000;font-weight:bold}.hljs-regexp,.hljs-symbol,.hljs-variable,.hljs-template-variable,.hljs-link,.hljs-selector-attr,.hljs-operator,.hljs-selector-pseudo{color:#BC6060}.hljs-literal{color:#78A960}.hljs-built_in,.hljs-bullet,.hljs-code,.hljs-addition{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta .hljs-string{color:#4d99bf}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold} +*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#F3F3F3;color:#444}.hljs-comment{color:#697070}.hljs-tag,.hljs-punctuation{color:#444a}.hljs-tag .hljs-name,.hljs-tag .hljs-attr{color:#444}.hljs-keyword,.hljs-attribute,.hljs-selector-tag,.hljs-meta .hljs-keyword,.hljs-doctag,.hljs-name{font-weight:bold}.hljs-type,.hljs-string,.hljs-number,.hljs-selector-id,.hljs-selector-class,.hljs-quote,.hljs-template-tag,.hljs-deletion{color:#880000}.hljs-title,.hljs-section{color:#880000;font-weight:bold}.hljs-regexp,.hljs-symbol,.hljs-variable,.hljs-template-variable,.hljs-link,.hljs-selector-attr,.hljs-operator,.hljs-selector-pseudo{color:#ab5656}.hljs-literal{color:#695}.hljs-built_in,.hljs-bullet,.hljs-code,.hljs-addition{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta .hljs-string{color:#38a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold} diff --git a/dev/assets/themeswap.js b/dev/assets/themeswap.js index c58e993..9f5eebe 100644 --- a/dev/assets/themeswap.js +++ b/dev/assets/themeswap.js @@ -1,20 +1,17 @@ // Small function to quickly swap out themes. Gets put into the tag.. function set_theme_from_local_storage() { - // Intialize the theme to null, which means default + // Initialize the theme to null, which means default var theme = null; // If the browser supports the localstorage and is not disabled then try to get the // documenter theme - if(window.localStorage != null) { + if (window.localStorage != null) { // Get the user-picked theme from localStorage. May be `null`, which means the default // theme. - theme = window.localStorage.getItem("documenter-theme"); + theme = window.localStorage.getItem("documenter-theme"); } - // Check if the browser supports user color preference - var darkPreference = false; // Check if the users preference is for dark color scheme - if(window.matchMedia('(prefers-color-scheme: dark)').matches === true) { - darkPreference = true; - } + var darkPreference = + window.matchMedia("(prefers-color-scheme: dark)").matches === true; // Initialize a few variables for the loop: // // - active: will contain the index of the theme that should be active. Note that there @@ -24,43 +21,64 @@ function set_theme_from_local_storage() { // // - disabled: style sheets that should be disabled (i.e. all the theme style sheets // that are not the currently active theme) - var active = null; var disabled = []; var darkTheme = null; + var active = null; + var disabled = []; + var primaryLightTheme = null; + var primaryDarkTheme = null; for (var i = 0; i < document.styleSheets.length; i++) { var ss = document.styleSheets[i]; // The tag of each style sheet is expected to have a data-theme-name attribute // which must contain the name of the theme. The names in localStorage much match this. var themename = ss.ownerNode.getAttribute("data-theme-name"); // attribute not set => non-theme stylesheet => ignore - if(themename === null) continue; + if (themename === null) continue; // To distinguish the default (primary) theme, it needs to have the data-theme-primary // attribute set. - var isprimary = (ss.ownerNode.getAttribute("data-theme-primary") !== null); - // Check if the theme is primary dark theme - var isDarkTheme = (ss.ownerNode.getAttribute("data-theme-primary-dark") !== null); - // If ss is for dark theme then set the value of darkTheme to the name of the theme - if(isDarkTheme) darkTheme = themename; + if (ss.ownerNode.getAttribute("data-theme-primary") !== null) { + primaryLightTheme = themename; + } + // Check if the theme is primary dark theme so that we could store its name in darkTheme + if (ss.ownerNode.getAttribute("data-theme-primary-dark") !== null) { + primaryDarkTheme = themename; + } // If we find a matching theme (and it's not the default), we'll set active to non-null - if(themename === theme) active = i; + if (themename === theme) active = i; // Store the style sheets of inactive themes so that we could disable them - if(themename !== theme) disabled.push(ss); + if (themename !== theme) disabled.push(ss); } - if(active !== null) { + var activeTheme = null; + if (active !== null) { // If we did find an active theme, we'll (1) add the theme--$(theme) class to - document.getElementsByTagName('html')[0].className = "theme--" + theme; - // and (2) disable all the other theme stylesheets - disabled.forEach(function(ss){ - ss.disabled = true; - }); + document.getElementsByTagName("html")[0].className = "theme--" + theme; + activeTheme = theme; + } else { + // If we did _not_ find an active theme, then we need to fall back to the primary theme + // which can either be dark or light, depending on the user's OS preference. + var activeTheme = darkPreference ? primaryDarkTheme : primaryLightTheme; + // In case it somehow happens that the relevant primary theme was not found in the + // preceding loop, we abort without doing anything. + if (activeTheme === null) { + console.error("Unable to determine primary theme."); + return; + } + // When switching to the primary light theme, then we must not have a class name + // for the tag. That's only for non-primary or the primary dark theme. + if (darkPreference) { + document.getElementsByTagName("html")[0].className = + "theme--" + activeTheme; + } else { + document.getElementsByTagName("html")[0].className = ""; + } } - else if(darkTheme !== null && darkPreference === true) { - // If we did find an active theme, we'll (1) add the theme--$(theme) class to - document.getElementsByTagName('html')[0].className = "theme--" + darkTheme; - // and (2) disable all the other theme stylesheets - disabled.forEach(function(ss){ - if (ss.ownerNode.getAttribute("data-theme-name") !== darkTheme) { - ss.disabled = true; - } - }); + for (var i = 0; i < document.styleSheets.length; i++) { + var ss = document.styleSheets[i]; + // The tag of each style sheet is expected to have a data-theme-name attribute + // which must contain the name of the theme. The names in localStorage much match this. + var themename = ss.ownerNode.getAttribute("data-theme-name"); + // attribute not set => non-theme stylesheet => ignore + if (themename === null) continue; + // we'll disable all the stylesheets, except for the active one + ss.disabled = !(themename == activeTheme); } } set_theme_from_local_storage(); diff --git a/dev/assets/warner.js b/dev/assets/warner.js index 5531c88..3f6f5d0 100644 --- a/dev/assets/warner.js +++ b/dev/assets/warner.js @@ -1,49 +1,52 @@ -function maybeAddWarning () { - // DOCUMENTER_NEWEST is defined in versions.js, DOCUMENTER_CURRENT_VERSION and DOCUMENTER_STABLE - // in siteinfo.js. - // If either of these are undefined something went horribly wrong, so we abort. - if ( - window.DOCUMENTER_NEWEST === undefined || - window.DOCUMENTER_CURRENT_VERSION === undefined || - window.DOCUMENTER_STABLE === undefined - ) { - return - }; +function maybeAddWarning() { + // DOCUMENTER_NEWEST is defined in versions.js, DOCUMENTER_CURRENT_VERSION and DOCUMENTER_STABLE + // in siteinfo.js. + // If either of these are undefined something went horribly wrong, so we abort. + if ( + window.DOCUMENTER_NEWEST === undefined || + window.DOCUMENTER_CURRENT_VERSION === undefined || + window.DOCUMENTER_STABLE === undefined + ) { + return; + } - // Current version is not a version number, so we can't tell if it's the newest version. Abort. - if (!/v(\d+\.)*\d+/.test(window.DOCUMENTER_CURRENT_VERSION)) { - return - }; + // Current version is not a version number, so we can't tell if it's the newest version. Abort. + if (!/v(\d+\.)*\d+/.test(window.DOCUMENTER_CURRENT_VERSION)) { + return; + } - // Current version is newest version, so no need to add a warning. - if (window.DOCUMENTER_NEWEST === window.DOCUMENTER_CURRENT_VERSION) { - return - }; + // Current version is newest version, so no need to add a warning. + if (window.DOCUMENTER_NEWEST === window.DOCUMENTER_CURRENT_VERSION) { + return; + } - // Add a noindex meta tag (unless one exists) so that search engines don't index this version of the docs. - if (document.body.querySelector('meta[name="robots"]') === null) { - const meta = document.createElement('meta'); - meta.name = 'robots'; - meta.content = 'noindex'; + // Add a noindex meta tag (unless one exists) so that search engines don't index this version of the docs. + if (document.body.querySelector('meta[name="robots"]') === null) { + const meta = document.createElement("meta"); + meta.name = "robots"; + meta.content = "noindex"; - document.getElementsByTagName('head')[0].appendChild(meta); - }; + document.getElementsByTagName("head")[0].appendChild(meta); + } - const div = document.createElement('div'); - div.classList.add('outdated-warning-overlay'); - const closer = document.createElement('button'); - closer.classList.add('outdated-warning-closer', 'delete'); - closer.addEventListener('click', function () { - document.body.removeChild(div); - }); - const href = window.documenterBaseURL + '/../' + window.DOCUMENTER_STABLE; - div.innerHTML = 'This documentation is not for the latest stable release, but for either the development version or an older release.
    Click here to go to the documentation for the latest stable release.'; - div.appendChild(closer); - document.body.appendChild(div); -}; + const div = document.createElement("div"); + div.classList.add("outdated-warning-overlay"); + const closer = document.createElement("button"); + closer.classList.add("outdated-warning-closer", "delete"); + closer.addEventListener("click", function () { + document.body.removeChild(div); + }); + const href = window.documenterBaseURL + "/../" + window.DOCUMENTER_STABLE; + div.innerHTML = + 'This documentation is not for the latest stable release, but for either the development version or an older release.
    Click here to go to the documentation for the latest stable release.'; + div.appendChild(closer); + document.body.appendChild(div); +} -if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', maybeAddWarning); +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", maybeAddWarning); } else { - maybeAddWarning(); -}; + maybeAddWarning(); +} diff --git a/dev/index.html b/dev/index.html index ca7f6c5..22b0abf 100644 --- a/dev/index.html +++ b/dev/index.html @@ -1,5 +1,5 @@ -Home · MomentClosure.jl

    MomentClosure

    MomentClosure.jl is a tool to automatically obtain time-evolution equations of moments up to an arbitrary order for virtually any chemical reaction network or system of stochastic differential equations (SDEs), implementing a wide array of moment closure approximations commonly used in stochastic biochemical kinetics [1]. MomentClosure is (attempted to be) fairly well-integrated within the broader Julia ecosystem utilising a number of familiar packages:

    Features

    • Chemical reaction networks containing any number of molecular species and reactions with any type of smooth propensity functions are supported. Models can be defined using Catalyst as ModelingToolkit.ReactionSystem.
    • Added support for reaction networks involving reaction products that are geometrically distributed random variables. An example of such network is an autoregulatory gene network with bursty protein production where the burst size follows a geometric distribution, see this example for more details.
    • Equations describing the time evolution of means and central moments of the number of molecules of each species in the system can be generated up to arbitrary order [2, 3]. Note that non-polynomial propensity functions are Taylor expanded to a specified order. Raw moment equations can also be generated for mass-action systems (where all propensity functions are polynomials).
    • SDE systems defined as ModelingToolkit.SDESystem are supported (big thanks to @FHoltorf). Similarly to reaction networks with non-polynomial propensities, non-polynomial drift and diffusion coefficients are Taylor expanded.
    • Currently implemented moment closure approximations include:
      • zero (central-moment neglect) closure [4, 5]
      • normal closure [4]
      • poisson closure [4]
      • log-normal closure [5]
      • gamma closure [5]
      • derivative matching [6]
      • conditional gaussian closure [7]
      • conditional derivative matching [7]
      • linear mapping approximation [8]
    • Moment equations are constructed as a ModelingToolkit.ODESystem that can be solved using any DifferentialEquations ODE solver. Moreover, parameter estimation, sensitivity analysis and bifurcation analysis tools can be applied to further study the resulting system of equations.
    • Latexify can be used to generate LaTeX expressions of the corresponding moment equations.

    Installation

    MomentClosure can be installed through the Julia package manager:

    ]add MomentClosure
    +Home · MomentClosure.jl

    MomentClosure

    MomentClosure.jl is a tool to automatically obtain time-evolution equations of moments up to an arbitrary order for virtually any chemical reaction network or system of stochastic differential equations (SDEs), implementing a wide array of moment closure approximations commonly used in stochastic biochemical kinetics [1]. MomentClosure is (attempted to be) fairly well-integrated within the broader Julia ecosystem utilising a number of familiar packages:

    Features

    • Chemical reaction networks containing any number of molecular species and reactions with any type of smooth propensity functions are supported. Models can be defined using Catalyst as ModelingToolkit.ReactionSystem.
    • Added support for reaction networks involving reaction products that are geometrically distributed random variables. An example of such network is an autoregulatory gene network with bursty protein production where the burst size follows a geometric distribution, see this example for more details.
    • Equations describing the time evolution of means and central moments of the number of molecules of each species in the system can be generated up to arbitrary order [2, 3]. Note that non-polynomial propensity functions are Taylor expanded to a specified order. Raw moment equations can also be generated for mass-action systems (where all propensity functions are polynomials).
    • SDE systems defined as ModelingToolkit.SDESystem are supported (big thanks to @FHoltorf). Similarly to reaction networks with non-polynomial propensities, non-polynomial drift and diffusion coefficients are Taylor expanded.
    • Currently implemented moment closure approximations include:
      • zero (central-moment neglect) closure [4, 5]
      • normal closure [4]
      • poisson closure [4]
      • log-normal closure [5]
      • gamma closure [5]
      • derivative matching [6]
      • conditional gaussian closure [7]
      • conditional derivative matching [7]
      • linear mapping approximation [8]
    • Moment equations are constructed as a ModelingToolkit.ODESystem that can be solved using any DifferentialEquations ODE solver. Moreover, parameter estimation, sensitivity analysis and bifurcation analysis tools can be applied to further study the resulting system of equations.
    • Latexify can be used to generate LaTeX expressions of the corresponding moment equations.

    Installation

    MomentClosure can be installed through the Julia package manager:

    ]add MomentClosure
     using MomentClosure

    Citation

    If you use MomentClosure in your work, please cite our paper:

    @article{MomentClosure2021,
         author = {Sukys, Augustinas and Grima, Ramon},
         title = "{MomentClosure.jl: automated moment closure approximations in Julia}",
    @@ -13,4 +13,4 @@
         doi = {10.1093/bioinformatics/btab469},
         url = {https://doi.org/10.1093/bioinformatics/btab469},
         eprint = {https://academic.oup.com/bioinformatics/article-pdf/38/1/289/41891091/btab469.pdf},
    -}

    References

    [1]: D. Schnoerr, G. Sanguinetti, and R. Grima, "Approximation and inference methods for stochastic biochemical kinetics - a tutorial review", Journal of Physics A: Mathematical and Theoretical 50, 093001 (2017). https://doi.org/10.1088/1751-8121/aa54d9

    [2]: A. Ale, P. Kirk, and M. P. H. Stumpf, "A general moment expansion method for stochastic kinetic models", The Journal of Chemical Physics 138, 174101 (2013). https://doi.org/10.1063/1.4802475

    [3]: C. H. Lee, "A Moment Closure Method for Stochastic Chemical Reaction Networks with General Kinetics", MATCH Communications in Mathematical and in Computer Chemistry 70, 785-800 (2013). https://match.pmf.kg.ac.rs/electronicversions/Match70/n3/match70n3785-800.pdf

    [4]: D. Schnoerr, G. Sanguinetti, and R. Grima, "Comparison of different moment-closure approximations for stochastic chemical kinetics", The Journal of Chemical Physics 143, 185101 (2015). https://doi.org/10.1063/1.4934990

    [5]: E. Lakatos, A. Ale, P. D. W. Kirk, and M. P. H. Stumpf, "Multivariate moment closure techniques for stochastic kinetic models", The Journal of Chemical Physics 143, 094107 (2015). https://doi.org/10.1063/1.4929837

    [6]: A. Singh and J. P. Hespanha, "Lognormal Moment Closures for Biochemical Reactions", in Proceedings of the 45th IEEE Conference on Decision and Control, ISSN: 0191-2216 (Dec. 2006), pp. 2063-2068. https://doi.org/10.1109/CDC.2006.376994

    [7]: M. Soltani, C. A. Vargas-Garcia, and A. Singh, "Conditional Moment Closure Schemes for Studying Stochastic Dynamics of Genetic Circuits", IEEE Transactions on Biomedical Circuits and Systems 9, 518-526 (2015). https://doi.org/10.1109/TBCAS.2015.2453158

    [8]: Z. Cao and R. Grima, "Linear mapping approximation of gene regulatory networks with stochastic dynamics", Nature Communications 9, 3305 (2018). https://doi.org/10.1038/s41467-018-05822-0

    +}

    References

    [1]: D. Schnoerr, G. Sanguinetti, and R. Grima, "Approximation and inference methods for stochastic biochemical kinetics - a tutorial review", Journal of Physics A: Mathematical and Theoretical 50, 093001 (2017). https://doi.org/10.1088/1751-8121/aa54d9

    [2]: A. Ale, P. Kirk, and M. P. H. Stumpf, "A general moment expansion method for stochastic kinetic models", The Journal of Chemical Physics 138, 174101 (2013). https://doi.org/10.1063/1.4802475

    [3]: C. H. Lee, "A Moment Closure Method for Stochastic Chemical Reaction Networks with General Kinetics", MATCH Communications in Mathematical and in Computer Chemistry 70, 785-800 (2013). https://match.pmf.kg.ac.rs/electronicversions/Match70/n3/match70n3785-800.pdf

    [4]: D. Schnoerr, G. Sanguinetti, and R. Grima, "Comparison of different moment-closure approximations for stochastic chemical kinetics", The Journal of Chemical Physics 143, 185101 (2015). https://doi.org/10.1063/1.4934990

    [5]: E. Lakatos, A. Ale, P. D. W. Kirk, and M. P. H. Stumpf, "Multivariate moment closure techniques for stochastic kinetic models", The Journal of Chemical Physics 143, 094107 (2015). https://doi.org/10.1063/1.4929837

    [6]: A. Singh and J. P. Hespanha, "Lognormal Moment Closures for Biochemical Reactions", in Proceedings of the 45th IEEE Conference on Decision and Control, ISSN: 0191-2216 (Dec. 2006), pp. 2063-2068. https://doi.org/10.1109/CDC.2006.376994

    [7]: M. Soltani, C. A. Vargas-Garcia, and A. Singh, "Conditional Moment Closure Schemes for Studying Stochastic Dynamics of Genetic Circuits", IEEE Transactions on Biomedical Circuits and Systems 9, 518-526 (2015). https://doi.org/10.1109/TBCAS.2015.2453158

    [8]: Z. Cao and R. Grima, "Linear mapping approximation of gene regulatory networks with stochastic dynamics", Nature Communications 9, 3305 (2018). https://doi.org/10.1038/s41467-018-05822-0

    diff --git a/dev/search/index.html b/dev/search/index.html deleted file mode 100644 index 794b3c5..0000000 --- a/dev/search/index.html +++ /dev/null @@ -1,2 +0,0 @@ - -Search · MomentClosure.jl diff --git a/dev/search_index.js b/dev/search_index.js index 7393e6a..19693fc 100644 --- a/dev/search_index.js +++ b/dev/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"theory/linear_mapping_approximation/#linear_mapping_approximation","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"","category":"section"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"The Linear Mapping Approximation (LMA) provides a novel way of approximating the solution of the CME and has been shown to be accurate for a variety of models of gene regulatory networks (GRNs) [1]. It is based on mapping a nonlinear GRN onto an equivalent linear GRN so that the exact solution of the linear system gives an approximate solution of the nonlinear system. The LMA is restricted in its applicability to chemical reaction networks where one of the substrates in each nonlinear reaction is a molecular species which copy number can be either zero or one (a Bernoulli/binary random variable). Note that a network can contain an arbitrary number of such species but more than one of them cannot be involved in any nonlinear reaction. Below we provide a short overview of the LMA and urge the reader to see the original paper for a more comprehensive description [1].","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"To explain the LMA procedure, we start by considering a simple example of a two-state GRN as done in a previous section on conditional closures, denoting the binary gene state by g and the protein number by p. We assume that there is a single nonlinear reversible reaction in the network given by","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"beginalign*\r\nG+P undersetσ_ustackrelσ_brightleftharpoons G^*\r\nendalign*","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"where P denotes the protein and the gene can be in either state G (g=1) or G^* (g=0). Our aim is to find an approximate time-dependent probability distribution of protein numbers p at time t.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"The steps of performing the LMA can then be described as follows:","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"1. Find the linear network by replacing any reversible nonlinear reaction (it must involve one binary species) in the nonlinear network by a reversible pseudo first-order reaction between the binary species' states.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"In our example, we replace the reaction above with G undersetσ_ustackrelbarσ_brightleftharpoons G^*, noting that the rate parameter is changed from σ_b to barσ_b. Moreover, this approach is just as applicable in case of cooperativity, e.g., G+nP rightleftharpoons G^* (where n is an integer indicating the cooperative order) would be similarly replaced with G rightleftharpoons G^*.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"2. Approximate the changed rate parameters of the linearised reactions by their expectation values.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"As noted in [1], the first-order reaction G stackrelbarσ_brightarrow G^* maps onto the second-order reaction G+P stackrelσ_brightarrow G^* if we choose barσ_b = σ_b left(p g=1 right), where p g=1 indicates the instantaneous protein number given the gene is in the state G. In LMA, we use the mean-field approximation taking the expectation value of the rate so that\nbeginalign*\r\nbarσ_b = σ_b left langle p g=1 right rangle = σ_b fracleftlangle pg rightrangleleftlangle g rightrangle\r\nendalign*\nThe same procedure can be extended to the general nonlinear reaction where n proteins bind cooperatively. The effective parameter is then given by\nbarσ_b = σ_b fracleftlangle prod_i=0^n-1 left( p-iright)g rightrangleleftlangle g rightrangle","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"3. Write down the moment equations for the linear network using the approximated stochastic rates.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"Note that the moment equations must be generated up the order given by the highest order nonlinear reaction in the network. If the only nonlinear reaction is the second-order reaction G+P stackrelσ_brightarrow G^*, we need to consider only moments up to the second order (as hinted by the functional form of barσ_b above). However, the moment hierarchy is otherwise closed, no additional moment closure approximations need to be performed, and therefore we can solve the moment equations in a straightforward manner.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"4. Solve the moment equations numerically up to time t and plug the resulting moment values into the equations for the effective parameters. Proceed to calculate the time-average of these parameters over the time-interval 0 t.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"In our example, plugging the solved-for moment values into the equation for barσ_b allows us to interpret the effective parameter as a time-dependent function barσ_b(t). However, as the time-dependent probability distribution solution of the CME for the nonlinear network with a general time-dependent barσ_b is most likely intractable, we transform barσ_b(t) into a time-independent constant by taking its time-average barσ_b^* = int_0^t barσ_b(t) dt t. This approach is justified in [1] by considering the Magnus expansion.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"5. Obtain the time-dependent probability distribution solution of the CME of the linear network assuming that the rate parameters of the linearised reactions are time-independent constants.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"Note that this step is the major limitation of the LMA as closed-form solutions are available only for a handful of systems (consult [1] for more details).","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"6. Finally, construct the approximate probability distribution of the nonlinear network at time t by replacing the respective rate parameters with their time-averaged equivalents obtained in the previous step.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"MomentClosure.jl provides automated generation of the closed moment equations using LMA given a nonlinear chemical reaction network and its linear equivalent. This encapsulates the first three steps of the LMA procedure outlined above which are general and can be seen as an original moment closure approximation. We apply the LMA on simple models of nonlinear GRNs and also discuss how the subsequent LMA steps can be performed in Julia on a case-by-case basis in this tutorial example.","category":"page"},{"location":"theory/linear_mapping_approximation/#References","page":"Linear Mapping Approximation","title":"References","text":"","category":"section"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"[1]: Z. Cao and R. Grima, \"Linear mapping approximation of gene regulatory networks with stochastic dynamics\", Nature Communications 9, 3305 (2018). https://doi.org/10.1038/s41467-018-05822-0","category":"page"},{"location":"tutorials/P53_system_example/#P53-System-Example","page":"P53 System Example","title":"P53 System Example","text":"","category":"section"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"In this example tutorial, we consider the oscillatory p53-Mdm2 system which has been studied by Lakatos et al. (2015) using central moment expansion up to 5th order with zero, normal, log-normal and gamma closures. We attempt to reproduce a number of results published in their paper.","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"In contrast to the Brusselator we considered before, the p53-Mdm2 system contains non-polynomial propensities and hence is a good showcase for generating central moment equations using different values of q and comparing their accuracy. Note that this was not considered by Lakatos et al. who set q = m+1 throughout their study. We remind the reader that m denotes the moment expansion order and q is the order of Taylor expansion of the propensity functions: the moment equations are generated up to m^textth order and may include central moments up q^textth order so that all moments of orders m+1 dotsc q must be approximated using some moment closure method (see the Moment Expansion theory section for more details).","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"The p53-Mdm2 reaction network is described by the stoichiometric matrix","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"S = beginbmatrix\r\n 1 -1 -1 0 0 0\r\n 0 0 0 1 -1 0 \r\n 0 0 0 0 1 -1\r\n endbmatrix","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"and six reaction propensities","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"beginalign*\r\na_1 = k_1 \r\na_2 = k_2 x_ \r\na_3 = k_3 fracx yx + k_7 \r\na_4 = k_4 x \r\na_5 = k_5 y₀ \r\na_6 = k_6 y\r\nendalign*","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"where the variables are","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"number of p53 molecules x\nnumber of precursor of Mdm2 molecules y_0\nnumber of Mdm2 molecules y","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"with parameters","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"p53 production rate k_1\nMdm2-independent p53 degradation rate k_2\nsaturating p53 degradation rate k_3\np53-dependent Mdm2 production rate k_4\nMdm2 maturation rate k_5\nMdm2 degradation rate k_6\np53 threshold for degradation by Mdm2 k_7","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"We begin by loading all the packages we will need","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"using Catalyst, MomentClosure, OrdinaryDiffEq, JumpProcesses,\r\n DiffEqBase.EnsembleAnalysis, Plots, Plots.PlotMeasures","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"and then build the model using Catalyst and set its parameters as follows:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"# → for mass-actions rate\r\n# ⇒ for non mass-actions rate\r\nrn = @reaction_network begin\r\n @parameters k₁ k₂ k₃ k₄ k₅ k₆ k₇\r\n (k₁), 0 → x\r\n (k₂), x → 0\r\n (k₃*x*y/(x+k₇)), x ⇒ 0\r\n (k₄*x), 0 ⇒ y₀\r\n (k₅), y₀ → y\r\n (k₆), y → 0\r\nend\r\n\r\n# parameters [k₁, k₂, k₃, k₄, k₅, k₆, k₇]\r\np = [90, 0.002, 1.7, 1.1, 0.93, 0.96, 0.01]\r\n\r\n# initial molecule numbers [x, y₀, y]\r\nu₀ = [70, 30, 60]","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Let's first simulate the reaction network using SSA in order to have a reference point of the real system dynamics. We choose a relatively long simulation time span in order to clearly see how the molecule numbers converge to their steady-state values and opt for 5 times 10^4 SSA realisations:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"# time interval to solve one on\r\ntspan = (0., 200.)\r\n\r\n# constructing the discrete jump problem using DifferentialEquations\r\njsys = convert(JumpSystem, rn, combinatoric_ratelaws=false)\r\ndprob = DiscreteProblem(jsys, u₀, tspan, p)\r\n\r\njprob = JumpProblem(jsys, dprob, Direct(), save_positions=(false, false))\r\nensembleprob = EnsembleProblem(jprob)\r\n\r\n# @time is only a rough estimate and not a proper benchmark\r\n@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.2, trajectories=50000)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"1332.443829 seconds (2.90 G allocations: 69.838 GiB, 42.81% gc time)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Single SSA trajectories show sustained oscillations in molecule numbers:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"plot(sol_SSA[666], labels=[\"p53\" \"pre-Mdm2\" \"Mdm2\"], lw=2, tspan=(0., 100.),\r\n linecolor=[1 3 2], xlabel=\"Time [h]\", ylabel=\"Number of molecules\", size=(700, 400))","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 SSA one trajectory)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"The mean population dynamics show damped oscillations as the single trajectories get dephased over time and eventually reach steady-state values:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"means_SSA, vars_SSA = timeseries_steps_meanvar(sol_SSA)\r\nplot(means_SSA, labels=[\"p53\" \"pre-Mdm2\" \"Mdm2\"], lw=2, linecolor=[1 3 2],\r\n xlabel=\"Time [h]\", ylabel=\"Number of molecules\", size=(700, 400))","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 SSA mean trajectories)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Note that many more SSA runs are needed to completely denoise the mean trajectories (especially at later times).","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Finally, we can look at the marginal distributions noting a high level of asymmetry at the chosen time point t=25:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"data = componentwise_vectors_timepoint(sol_SSA, 25.0)\r\nh1 = histogram(data[1], normalize=true, xlabel=\"x\", ylabel=\"P(x)\")\r\nh2 = histogram(data[2], normalize=true, xlabel=\"y₀\", ylabel=\"P(y₀)\")\r\nh3 = histogram(data[3], normalize=true, xlabel=\"y\", ylabel=\"P(y)\")\r\nusing Plots.PlotMeasures\r\nplot(h1, h2, h3, legend=false, layout=(1,3), size = (1050, 250),\r\n left_margin = 5PlotMeasures.mm, bottom_margin = 7PlotMeasures.mm, guidefontsize=10)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 distribution)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Given the long runtime of the SSA above, it makes sense to turn to approximation methods such as moment closure which is usually much faster (suitable if only information about moments is needed). We start with the simplest second order, m =2, moment expansion and consider normal, log-normal and gamma closures. Our interest here is to see how the accuracy of each closure changes when the Taylor expansion order q is increased. Note that zero closure is equivalent to normal closure when q=3 (as third order central moments and cumulants are equivalent) and does not change when q is increased as all the higher order moments will be simply set to zero.","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"We can generate the corresponding plots of the mean p53 molecule number, x, as follows:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"closures = [\"normal\", \"log-normal\", \"gamma\"]\r\n\r\n# initialise separate plot for each closure\r\nplts = [plot() for i in 1:length(closures)]\r\n\r\nfor q in 3:6\r\n eqs = generate_central_moment_eqs(rn, 2, q, combinatoric_ratelaws=false)\r\n for (closure, plt) in zip(closures, plts)\r\n closed_eqs = moment_closure(eqs, closure)\r\n\r\n u₀map = deterministic_IC(u₀, closed_eqs)\r\n oprob = ODEProblem(closed_eqs, u₀map, tspan, p)\r\n\r\n sol = solve(oprob, Tsit5(), saveat=0.1)\r\n plt = plot!(plt, sol, idxs=[1], lw=3, label = \"q = \"*string(q))\r\n end\r\nend\r\n\r\nfor plt in plts\r\n plt = plot!(plt, xlabel = \"Time [h]\", ylabel = \"Mean number of p53 molecules\")\r\n plt = plot!(plt, means_SSA.t, means_SSA[1,:], lw=2, linestyle=:dash, label = \"SSA\", color=\"gray\")\r\nend","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Normal closure:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"plot(plts[1], size=(750, 450), leftmargin=2PlotMeasures.mm)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 normal means 2nd order expansion)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Log-normal closure:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"plot(plts[2], size=(750, 450), leftmargin=2PlotMeasures.mm)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 log-normal means 2nd order expansion)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Zoomed-in log-normal closure (to better see the initial dampening in trajectories):","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"plot(plts[2], xlims=(0., 50.), lw=3)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 log-normal means 2nd order expansion)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Gamma closure:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"plot(plts[3], size=(750, 450), leftmargin=2PlotMeasures.mm)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 gamma means 2nd order expansion)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"When using normal closure, including central moments all the way up to 6th order (q=6) is needed in order to obtain qualitatively correct system behaviour. As the true distribution (as plotted above) is highly asymmetric, one may expect that performing normal closure, i.e., assuming that the system has a (symmetric) Gaussian distribution, is not the most optimal choice. For log-normal and gamma closures, quite accurate predictions are obtained with q=4 whereas q=6 tends to overestimate the dampening initially but better captures the steady-state behaviour. Note that for odd values of q log-normal and gamma closures introduced numerical instabilities and the moments could not be evaluated for the entire time course.","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"We can also plot the variance predictions:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"# rerunning the same calculations as they are reasonably fast\r\nplt = plot()\r\nfor q in [4,6]\r\n eqs = generate_central_moment_eqs(rn, 2, q, combinatoric_ratelaws=false)\r\n for closure in closures\r\n closed_eqs = moment_closure(eqs, closure)\r\n\r\n u₀map = deterministic_IC(u₀, closed_eqs)\r\n oprob = ODEProblem(closed_eqs, u₀map, tspan, p)\r\n sol = solve(oprob, Tsit5(), saveat=0.1)\r\n\r\n # index of M₂₀₀ can be checked with `u₀map` or `closed_eqs.odes.states`\r\n plt = plot!(plt, sol, idxs=[4], lw=3, label = closure*\" q = \"*string(q))\r\n end\r\nend\r\n\r\nplt = plot!(plt, xlabel = \"Time [h]\", ylabel = \"Variance of p53 molecule number\", legend=:topleft)\r\nplt = plot!(plt, means_SSA.t, vars_SSA[1,:], lw=2, linestyle=:dash, label = \"SSA\", color=\"gray\")\r\nplot(plt, size=(750, 450))","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 variances 2nd order expansion)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Log-normal closure with q=6 clearly gives the best estimate of the variance. Therefore, including increasingly higher-order moment information in second-order moment expansion tends to leads to an overall more accurate statistical description of the P53-Mdm2 system.","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"We can extend the analysis further by considering higher order moment expansions (increasing m). Let's look at third-order expansion with q values 4 and 6 (odd q leads to heavy numerical instabilities as before):","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"closures = [\"zero\", \"normal\", \"log-normal\", \"gamma\"]\r\n\r\nplt_means = [plot() for i in 1:2]\r\nplt_vars = [plot() for i in 1:2]\r\n\r\nq_vals = [4, 6]\r\n\r\nfor (q, plt_m, plt_v) in zip(q_vals, plt_means, plt_vars)\r\n\r\n eqs = generate_central_moment_eqs(rn, 3, q, combinatoric_ratelaws=false)\r\n for closure in closures\r\n\r\n closed_eqs = moment_closure(eqs, closure)\r\n\r\n u₀map = deterministic_IC(u₀, closed_eqs)\r\n oprob = ODEProblem(closed_eqs, u₀map, tspan, p)\r\n\r\n sol = solve(oprob, Tsit5(), saveat=0.1)\r\n plt_m = plot!(plt_m, sol, idxs=[1], label = closure) \r\n plt_v = plot!(plt_v, sol, idxs=[4], label = closure)\r\n\r\n end\r\n\r\n plt_m = plot!(plt_m, means_SSA.t, means_SSA[1,:], title=\"m = 3, q = \"*string(q),\r\n linestyle=:dash, label = \"SSA\", color=\"gray\", legend=false)\r\n\r\n plt_v = plot!(plt_v, vars_SSA.t, vars_SSA[1,:], linestyle=:dash, label = \"SSA\", color=\"gray\", legend=false)\r\n\r\nend\r\n\r\nplt_means[1] = plot(plt_means[1], ylabel = \"Mean p53 molecule number\")\r\nplt_vars[1] = plot(plt_vars[1], ylabel = \"Variance of p53 molecule number\", legend=:topleft)\r\nplot(plt_means..., plt_vars..., size=(1250, 750), lw=1.5, xlabel=\"Time [h]\",\r\n guidefontsize=10, titlefontsize=12, legendfontsize=8, leftmargin=4mm, bottommargin=2mm)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 3rd order expansion)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"The results are rather interesting: the mean trajectories initially show the characteristic dampened oscillations, which, however, fail to converge to a steady-state value and instead start growing in amplitude as the time increases—this behaviour is also more pronounced for higher q. Surprisingly, log-normal and gamma closures still provide fairly accurate variance estimates. Note that zero closure ODEs fail to be evaluated for the entire time course at all, displaying strongly oscillatory mean trajectories and even exponentially growing variances. Therefore, third order moment expansion and all of the applied closure methods fail to give physically meaningful results.","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"This outcome seems concerning as Lakatos et al. (2015) state that the same closures reached steady-state at extended simulation time (using identical parameter set). In order to investigate this discrepancy further, we turn to Python MEANS package, the implementation of which is fully based on the technical details presented in Lakatos et al. (2015). Note that the package has not been maintained for years, only works on Python 2 and setting up its dependencies may be fiddly. Nevertheless, having done that, we can generate and solve the moment equations up to third order running the following code in a separate Python 2 notebook:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"import means\r\nimport means.examples\r\nimport numpy as np\r\nimport matplotlib.pyplot as plt\r\n\r\nsys = means.examples.MODEL_P53\r\n\r\nps = [90, 0.002, 1.7, 1.1, 0.93, 0.96, 0.01]\r\nic_values = [70, 30, 60]\r\n\r\ntspan = np.arange(0, 200, 0.1)\r\n\r\nplt.figure(figsize=(10,6))\r\n\r\nfor closure in [\"normal\", \"log-normal\", \"gamma\"]:\r\n odes = means.mea_approximation(sys, 3, closure=closure, multivariate=True)\r\n simulation = means.Simulation(odes)\r\n trajectories = simulation.simulate_system(ps, ic_values, tspan)\r\n trajectories[0].plot(label=closure)\r\n\r\nplt.margins(x=0)\r\nplt.xlabel('Time [h]', fontsize=12)\r\nplt.ylabel('Mean p53 molecule number', fontsize=12)\r\nplt.tick_params(axis='both', which='major', labelsize=10)\r\nplt.legend(fontsize=12)\r\nplt.show()","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 3rd order expansion MEANS)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"We observe that the mean trajectories fail to converge after all, hinting that some of the results published in Lakatos et al. (2015) may benefit from a more critical analysis. Note that MEANS does not allow arbitrary q values and automatically sets q = m+1, hence third-order moment expansion using MEANS is equivalent to our m=3 q=4 case.","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"We stress that the obtained mean trajectories using the two packages are not identical due to different implementations of the closure methods (different solvers do not have a significant effect in this case). Lakatos et al. (2015) (and hence MEANS) formulate the normal, log-normal and gamma closure functions exclusively in terms of first and second order moments—higher order moments, whose corresponding ODEs are being solved for simultaneously, are not included in the construction of closure functions. One could say that such formulation makes a stronger assumption about the underlying distribution and does not utilise all the information available about the system—our implementation takes that into account. For example, in case of m=3 q=4 moment expansion, we approximate the fourth order central moments in terms of third and lower order moments, whereas MEANS would approximate it using only first and second order moments. Curiously, MEANS formulation appears to be more numerically stable (shows weaker oscillations) at longer times in this particular case, as can be seen from the plots above. Nevertheless, as both approaches failed to produce physically meaningful results, we do not investigate the numerical differences further—one would still generally expect that the inclusion of the computed higher-order moment values will improve the numerical stability of the ODEs and the accuracy of moment estimates.","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Finally, we can check whether better estimates can be obtained using even higher, fifth, order expansion with q=6:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"plt = plot()\r\nclosures = [\"zero\", \"normal\", \"log-normal\", \"gamma\"]\r\n\r\neqs = generate_central_moment_eqs(rn, 5, 6, combinatoric_ratelaws=false)\r\n# faster to store than recompute in case we want to try different solvers/params\r\noprobs = Dict()\r\n\r\nfor closure in closures\r\n closed_eqs = moment_closure(eqs, closure)\r\n\r\n u₀map = deterministic_IC(u₀, closed_eqs)\r\n oprobs[closure] = ODEProblem(closed_eqs, u₀map, tspan, p)\r\n sol = solve(oprobs[closure], Tsit5(), saveat=0.1)\r\n\r\n plt = plot!(plt, sol, idxs=[1], label = closure) \r\nend\r\n\r\nplt = plot!(plt, xlabel = \"Time [h]\", ylabel = \"Mean p53 molecule number\")\r\nplt = plot!(plt, means_SSA.t, means_SSA[1, :], linestyle=:dash, label = \"SSA\", color=\"gray\")\r\nplot(plt, size=(750, 450), lw=2)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 5th order expansion)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"All closures are highly numerically unstable and fail to provide physically meaningful results. Performing similar fifth order moment expansion using the MEANS package we obtain (full code can be found in the example Jupyter notebook):","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 5th order expansion MEANS)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Note that normal closure is not included in the plot as it failed to converge using MEANS while log-normal and gamma closures seem to be much more stable in comparison to MomentClosure results (albeit still unphysical). In contrast, normal closure is the only one which succeeded in being evaluated for the entire time course using MomentClosure (full time not shown in the plot) which again is a result of the implementational differences between the two packages.","category":"page"},{"location":"tutorials/SIR_example/#SIR_example","page":"SIR Model Example","title":"SIR Model Example","text":"","category":"section"},{"location":"tutorials/SIR_example/","page":"SIR Model Example","title":"SIR Model Example","text":"See here for an example application of MomentClosure to the SIR model (thanks to @sdwfrost).","category":"page"},{"location":"theory/moment_expansion_SDE/#moment_expansion_SDE","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"","category":"section"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"Moment equations can be also written down for models described by N-dimensional Stochastic Differential Equations (SDEs) of the form ","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\r\n dmathbfn = mathbff left(mathbfn t right) dt + mathbfGleft( mathbfn t right) dmathbfw_t\r\nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"where mathbfn=(n_1 dotsc n_N) is a N times 1 state vector, mathbff left(mathbfn t right) = left( f_1(mathbfn t) dotsc f_N(mathbfn t) right)^top is the deterministic (drift) term, mathbfG(mathbfn t) is a N times m (diffusion) matrix and mathbfw_t is a m times 1 vector of Wiener processes so that langle dmathbfw_t rangle = mathbf0 and dmathbfw_t dmathbfw_t^top = mathbfIdt, with mathbfI being an m times m identity matrix. Note that the notation used throughout is consistent with that of the previous section, and the state vector here is the same as for a chemical reaction network of N species (the only difference being that its elements are now continuous variables). The derivations below are based on Ghusinga et al. (2017) [1] and Bover (1978) [2].","category":"page"},{"location":"theory/moment_expansion_SDE/#raw_moment_eqs_SDE","page":"Moment Expansion (SDE)","title":"Raw Moment Equations","text":"","category":"section"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"To obtain the raw moment equations, we begin with Itô's lemma stating that for any smooth scalar function h(mathbfn) one has ","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\r\n dh(mathbfn) = left sum_i=1^N fracpartial h(mathbfn) partial n_i f_i + frac12 sum_i=1^N sum_j=1^N fracpartial^2 h(mathbfn) partial n_i partial n_j (mathbfGmathbfG^top)_ij rightdt + sum_i=1^N sum_j=1^N fracpartial h(mathbfn) partial n_i mathbfG_ij dw_j \r\nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"Taking the expectation of both sides we obtain","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\r\n fracd langle h(mathbfn) rangledt = sum_i=1^N leftlangle fracpartial h(mathbfn)partial n_i f_i rightrangle + frac12 sum_i=1^N sum_j=1^N leftlangle fracpartial^2 h(mathbfn)partial n_i partial n_j (mathbfGmathbfG^top)_ijrightrangle \r\nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"where we have used the fact that langle dmathbfw rangle = mathbf0. Finally, the general form of raw moment equations up to m^textth order is obtained by setting h(mathbfn) = mathbfn^mathbfi = n_1^i_1 dotsm n_N^i_N, so that langle h(mathbfn) rangle = mu_mathbfi and mathbfi = sum_j=1^N i_j leq m, leading to ","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\r\n fracdmu_mathbfidt = sum_j=1^N leftlangle fracpartial mathbfn^mathbfi partial n_j f_j rightrangle + frac12 sum_j=1^N sum_k=1^N leftlangle fracpartial^2 mathbfn^mathbfi partial n_j partial n_k (mathbfGmathbfG^top)_jkrightrangle \r\nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"The equation for the mean vector mathbfμ = langle mathbfn rangle = (mu_1 dotsc mu_N) take a particularly simple form (as the second derivatives are zero):","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\r\n fracdmathbfμdt = langle mathbff(mathbfn t) rangle\r\nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/#central_moment_eqs_SDE","page":"Moment Expansion (SDE)","title":"Central Moment Equations","text":"","category":"section"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"Note that the raw moment expansion formulated above is valid only when the SDE terms mathbff left(mathbfn t right) and mathbfG(mathbfn t) are polynomial functions. If these functions are non-polynomial, we have to consider central moment equations and Taylor expand both mathbff left(mathbfn t right) and mathbfG(mathbfn t) around the mean mathbfμ up to the expansion order q (as done in case of the CME with non-polynomial propensities).","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"The corresponding Taylor expansions can be written down as:","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\r\n f_j(mathbfn) = sum_mathbfk=0^q frac1mathbfkD^mathbfk f_j(mathbfμ) (mathbfn - mathbfμ)^mathbfk + dotsb \r\n left( mathbfG(mathbfn) mathbfG(mathbfn)^top right)_jk = sum_mathbfl=0^q frac1mathbfl D^mathbfl left( mathbfG(mathbfμ)mathbfG(mathbfμ)^top right)_jk (mathbfn - mathbfμ)^mathbfl + dotsb \r\nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"and we remind the reader that we have previously introduced the notation","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\r\nmathbfk = k_1dotsm k_N \r\nD^mathbfk f = fracpartial^mathbfkpartial n_1^k_1 dotsm partial n_N^k_N f\r\n(mathbfn - mathbfμ)^mathbfk = (n_1-mu_1)^k_1 dotsm (n_N-mu_N)^k_N \r\nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"It follows that the equations for the means can now be written down as:","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\r\n fracdmu_idt = langle f_i rangle = sum_mathbfj=0^q frac1mathbfj D^mathbfj f_i(mathbfμ) M_mathbfj + dotsb \r\nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"where M_mathbfj = langle (mathbfn-mathbfμ)^mathbfj rangle are central moments.","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"To obtain the central moment equations, we first perform a change of variables mathbfy = mathbfn - langle mathbfn rangle and note again that dlangle mathbfn rangledt = langle mathbff(mathbfn t) rangle, so that the SDE becomes","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\r\n dmathbfy = left mathbffleft(mathbfy + langlemathbfnrangle t right) - leftlangle mathbff left(mathbfy + langlemathbfnrangle t right) rightrangle right dt + mathbfGleft(mathbfy + langlemathbfnrangle t right) dmathbfw_t \r\nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"Then, using Itô's lemma for a smooth function h(mathbfy) and taking the expectation of both sides we find","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\r\n fracd langle h(mathbfy) rangledt = sum_i=1^N left leftlangle fracpartial h(mathbfy)partial y_i f_i rightrangle - leftlangle fracpartial h(mathbfy)partial y_i rightrangle leftlangle f_i rightrangle right + frac12 sum_i=1^N sum_j=1^N leftlangle fracpartial^2 h(mathbfy)partial y_i partial y_j (mathbfGmathbfG^top)_ijrightrangle \r\nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"Letting h(mathbfy) = (mathbfn - mathbfμ)^mathbfi and substituting in the needed Taylor expansions we obtain the final form of central moment equations:","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\r\n fracd M_mathbfidt = sum_j=1^N Bigg leftlangle fracpartial (mathbfn - mathbfμ)^mathbfi partial (n_j - mu_j) sum_mathbfk=0^q-mathbfi+1 frac1mathbfk D^mathbfk f_j(mathbfμ) (mathbfn-mathbfμ)^mathbfk + dotsb rightrangle \r\n - leftlangle fracpartial (mathbfn-mathbfμ)^mathbfi partial(n_j - μ_j) rightrangle leftlangle sum_mathbfk=0^q frac1mathbfk D^mathbfk f_j(mathbfμ) (mathbfn-mathbfμ)^mathbfk + dotsb rightrangle Bigg \r\n + frac12 sum_j=1^N sum_k=1^N leftlangle fracpartial^2 (mathbfn-mathbfμ)^mathbfipartial(n_j-mu_j)partial(n_k-mu_k) sum_mathbfl=0^q-mathbfi+2 frac1mathbfl D^mathbfl left( mathbfG(mathbfμ) mathbfG(mathbfμ)^top right)_jk (mathbfn-mathbfμ)^mathbfl + dotsc rightrangle\r\nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/#References","page":"Moment Expansion (SDE)","title":"References","text":"","category":"section"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"[1]: K. R. Ghusinga, M. Soltani, A. Lamperski, S. V. Dhople, and A. Singh, \"Approximate moment dynamics for polynomial and trigonometric stochastic systems\", IEEE 56th Annual Conference on Decision and Control (2017). https://doi.org/10.1109/CDC.2017.8263922","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"[2]: D. C. C. Bover, \"Moment Equation Methods for Nonlinear Stochastic Systems\", Journal of Mathematical Analysis and Applications 65, 306-320 (1978). https://doi.org/10.1016/0022-247X(78)90182-8","category":"page"},{"location":"theory/moment_expansion_CME/#moment_expansion_CME","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"","category":"section"},{"location":"theory/moment_expansion_CME/#chemical_master_equation","page":"Moment Expansion (CME)","title":"The Chemical Master Equation","text":"","category":"section"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"Consider a chemical reaction network with N different molecular species X_i (i=1 dotsc N) and R chemical reactions, so that the system can be described by [1]:","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign*\r\n sum_i=1^N s_ij X_i xrightarrowk_j sum_i=1^N r_ij X_i quad j=1dotscR\r\nendalign*","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"where s_ij and r_ij respectively denote the numbers of reactant and product molecules of species i in the chemical reaction j. The stoichiometric matrix is defined as S_ij = r_ij - s_ij (the net change in the number of molecules of species X_i when the r^textth reaction occurs). The state of the system is determined by the state vector mathbfn=(n_1 dotsc n_N), where n_i is the number of X_i molecules. The time evolution of the probability distribution of mathbfn is described by the Chemical Master Equation (CME)","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginequation\r\n fracd P(mathbfn t)dt = sum^R_r=1 Big a_r(mathbfn-S_r)P(mathbfn-S_r t) - a_r(mathbfn) P(mathbfn t) Big tag1\r\nendequation","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"where a_r(mathbfn) is the propensity function of the r^textth reaction and S_r is the r^textth column of the stoichiometric matrix S.","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"Modelling using the CME framework is common in the study of biochemical and gene networks within cells. Although such master equations are rather simple in structure, for most systems there are no known analytical solutions and their stochastic simulations can be very computationally expensive. One possible approach to investigate the system at hand is to approximate the whole probability distribution solution of the CME in terms of its first few moments (e.g. mean and variance).","category":"page"},{"location":"theory/moment_expansion_CME/#raw_moment_eqs","page":"Moment Expansion (CME)","title":"Raw Moment Equations","text":"","category":"section"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"From Eq. (1) we can obtain a system of ordinary differential equations (ODEs) governing the time-evolution of the raw moments of the system up to specified moment expansion order m, given by mu_mathbfi = mu_i_1 dotsc i_N = langle n_1^i_1 dotsm n_N^i_N rangle, where the indices mathbfi=(i_1 dotsc i_N) are restricted such that mathbfi = sum_j=1^N i_j leq m. Note that first order raw moments are simply the means. For example, when N = 3, the mean molecule number of second species in the system is given by mu_2 = mu_0 1 0 = langle n_2 rangle (when N=3). We chose to relax the notation throughout so that the means can be indicated by a single index of the molecular species (used in this section) or by the corresponding one-hot vector (used in the code).","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"To find the first moment equations, we multiply the CME by n_i and sum over all possible states:","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign*\r\n sum_mathbfn n_i fracdP(mathbfnt)dt = sum_n_1^infty sum_n_2^infty dotsm sum_n_N^infty n_i fracdP(mathbfnt)dt \r\n = sum_r sum_mathbfn n_i a_r(mathbfn-S_r)P(mathbfn-S_r t) - n_i a_r(mathbfn) P(mathbfn t) \r\nendalign*","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"Applying a transformation mathbfn-S_r rightarrow mathbfn on the first term in the sum leads to","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign*\r\n fracdmu_idt = sum_r sum_mathbfn (n_i+S_ir) a_r(mathbfn)P(mathbfn t) - n_i a_r(mathbfn) P(mathbfn t) \r\n = sum_r sum_mathbfn S_ir a_r(mathbfn) P(mathbfn t) \r\n = sum_r S_ir langle a_r(mathbfn) rangle tag2\r\nendalign*","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"The derivation can be extended to the multivariate case of higher order moments mu_mathbfi with mathbfi leq m:","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign*\r\n fracdmu_mathbfidt = sum_mathbfn n_1^i_1dotsm n_N^i_N fracdP(mathbfn t)dt \r\n = sum_r sum_mathbfn left (n_1+S_1r)^i_1dotsm (n_N +S_2r)^i_N - n_1^i_1dotsm n_N^i_N right a_r(mathbfn)P(mathbfn t) \r\n = sum_r sum_mathbfn left sum^i_1_j_1=0 binomi_1j_1 n_1^j_1S_1r^i_1-j_1 dotsm sum^i_N_j_N=0 binomi_Nj_N n_N^j_NS_Nr^ i_N-j_N - n_1^i_1dotsm n_N^i_N right a_r(mathbfn)P(mathbfn t) \r\n = sum_r sum_mathbfn sum^mathbfi-1_mathbfj=0 binomi_1j_1 dotsm binomi_Nj_N S_1r^i_1-j_1 dotsm S_Nr^ i_N-j_N n_1^j_1 dotsm n_N^j_N a_r(mathbfn)P(mathbfn t) \r\n = sum_r sum^mathbfi-1_mathbfj=0 binom mathbfi mathbfj S_r^mathbfi-mathbfj langle mathbfn^mathbfj a_r(mathbfn) rangle \r\nendalign*","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"where we have introduced multi-index notation:","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign\r\n mathbfi = sum^N_j=1 i_j tag3 \r\n sum^mathbfi-1_mathbfj=0 = sum_substack0 leq j_1 leq i_1 dotsc 0 leq j_N leq i_N 0 leq j_1+dotsb+j_N leq mathbfi-1 tag4 \r\n binom mathbfi mathbfj = binomi_1j_1 dotsm binomi_Nj_N tag5 \r\n mathbfn^mathbfj = n_1^j_1dotsm n_N^j_N tag6 \r\n S_r^mathbfi-mathbfj = S_1r^ i_1-j_1 dotsm S_Nr^ i_N-j_N tag7\r\nendalign","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"It is crucial to stress three key points:","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"Throughout all derivations presented in this section we assume that the components of the net stoichiometry matrix S are constant values. However, in certain cases the reaction product may itself be a stochastic variable so that the corresponding expectation values, langle S_r^mathbfi-mathbfj rangle, must be taken into account. We have implemented a limited support for such systems where components of S can be independent geometrically distributed variables, see the specific gene network example.\nGeneration of raw moment equations is only possible if the kinetics of the system at hand are governed by the law of mass action where all propensity functions are polynomials in mathbfn, otherwise the expectation value terms langle a_r(mathbfn) rangle and langle n_i_1^j_1 dotsm n_i_N^j_N a_r(mathbfn) rangle are ill-defined. This key issue can be overcome by the general central moment expansion method presented below.\nThe order of the polynomials a_r(mathbfn) determines the order of moments encountered in the generated system of ODEs. If the system is linear (contains only zeroth and first order reactions), the m^textth order moments will depend only of moments of order m or lower, hence constituting a finite hierarchy of moment ODEs that can be readily solved numerically or otherwise without approximations. However, if the system is non-linear (involves second or higher order reactions), moment equations will depend on higher order moments. For example, if the reaction network contains bimolecular reactions, the corresponding propensity functions will be second order polynomials and hence m^textth order moment equations will now depend on (m+1)^th order moments. This leads to an infinite hierarchy of coupled moment equations where each moment will depend on higher order moments—it cannot be solved directly and needs to be truncated. This can be achieved using one of many moment closure approximations that express (m+1)^textth order moments in terms of m^textth and lower order moments using different distributional assumptions, effectively closing the hierarchy and enabling one to solve the moment equations up to m^textth order [1]. Details of all closure methods currently implemented within the package can be found in the next Theory section.","category":"page"},{"location":"theory/moment_expansion_CME/#central_moment_eqs","page":"Moment Expansion (CME)","title":"Central Moment Equations","text":"","category":"section"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"As we have seen, the moment equations of P(mathbfn t) can be obtained in a straightforward manner if the kinetics of the system are governed by the law of mass action where all propensity functions are polynomials in mathbfn [1]. Similarly, given all propensities are rational functions, a polynomial form can also be recovered [2]. However, problems arise when the propensities take more complicated non-polynomial functions. This can nevertheless be overcome by considering a more general method of moment expansion that enables us to obtain mean and central moment equations up to arbitrary order for virtually any chemical reaction network with any type of smooth (infinitely differentiable) propensity functions. Such framework was first independently formulated by Lee [3] and Ale et al. [4]—our derivation below closely follows these works.","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"We start by Taylor-expanding the propensity functions around the mean mathbfμ = langle mathbfn rangle = (mu_1 dotsc mu_N). This allows us to consider any general propensity function under the assumption that it is infinitely differentiable (smooth). The expansion leads to","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign*\r\n a_r(mathbfn) = a_r(mathbfμ) + sum_j_1^N fracpartial a_r(mathbfμ)partial n_j_1(n_j_1-mu_j_1) \r\n + frac12sum_j_1 j_2 fracpartial^2 a_r(mathbfμ)partial n_j_1 partial n_j_2 (n_j_1-mu_j_1) (n_j_2-mu_j_2) + dotsb \r\n + frac1q sum_j_1 j_2 dotsc j_q fracpartial^q a_r(mathbfμ)partial n_j_1 partial n_j_2dotsmpartial n_j_q (n_j_1-mu_j_1) (n_j_2-mu_j_2) dotsm(n_j_q - mu_j_q) + dotsb \r\n = sum_mathbfj=0^q frac1mathbfj D^mathbfj a_r(mathbfμ) (mathbfn - mathbfμ)^mathbfj + dotsb \r\nendalign*","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"where q controls the expansion order and we have simplified the expression by using Eqs. (3-7) in addition to:","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign*\r\nmathbfj = j_1dotsm j_N \r\nD^mathbfj f = fracpartial^mathbfjpartial n_1^j_1 dotsm partial n_N^j_N f \r\nendalign*","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"Now we can obtain equations governing the time-evolution of the means μ_i and the central moments M_mathbfi = M_i_1 dotsc i_N = langle (n_1 - mu_1)^i_1dotsm(n_N - mu_N)^i_N rangle, where again mathbfi leq m. We first consider the equations for the means immediately starting from Eq. (2):","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign*\r\n fracdmu_idt = sum_r S_ir langle a_r(mathbfn) rangle \r\n = sum_r S_ir Big( sum_mathbfj=0^q frac1mathbfj D^ mathbfj a_r(mathbfμ) langle (mathbfn - mathbfμ)^mathbfj rangle + dotsb Big) \r\n = sum_r S_ir Big( sum_mathbfj=0^q frac1mathbfj D^ mathbfj a_r(mathbfμ) M_mathbfj + dotsb Big) \r\nendalign*","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"We can now derive the equations for central moments by taking the time derivative of M_mathbfi and using Eq. (1):","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign*\r\n fracdM_mathbfidt = sum_mathbfn (n_1 - mu_1)^i_1dotsm(n_N - mu_N)^i_N fracdP(mathbfn t)dt \r\n - sum_mathbfn sum_j=1^N i_j fracdmu_jdt (n_1-mu_1)^i_1 dotsm(n_j-mu_j)^i_j-1dotsm(n_N-mu_N)^i_NP(mathbfn t) \r\n = sum_r sum_mathbfn Big (n_1 - mu_1 + S_1r)^i_1 dotsm (n_N-mu_N+S_Nr)^i_N \r\n - (n_1-mu_1)^i_1dotsm(n_N-mu_N)^i_N Biga_r(mathbfn)P(mathbfn t) - sum_j i_j fracdmu_jdtM_i_1dotsci_j-1dotsc i_N \r\n = sum_r sum_mathbfn Bigg sum_mathbfj=0^mathbfi-1 binomi_1j_1 dotsm binomi_Nj_N S_1r^ i_1-j_1 dotsm S_Nr^ i_N-j_N(n_1-mu_1)^j_1dotsm(n_N-mu_N)^j_NBigg \r\n times Bigg sum_mathbfj=0^q frac1mathbfj D^mathbfj a_r(mathbfμ) (mathbfn - mathbfμ)^mathbfj + dotsb Bigg-sum_j i_j fracdmu_jdt M_mathbfi_j- \r\n = sum_r sum_mathbfj=0^mathbfi-1 Bigg binomi_1j_1 dotsm binomi_Nj_N S_1r^ i_1-j_1 dotsm S_Nr^ i_N-j_N sum_mathbfk=0^q-mathbfj frac1mathbfkD^mathbfk a_r(mathbfμ) M_mathbfj+mathbfk + dotsb Bigg - sum_j i_j fracdmu_jdt M_mathbfi_j- \r\n = sum_r sum_mathbfj=0^mathbfi-1 Bigg binommathbfimathbfj S_r^mathbfi-mathbfj sum_mathbfk=0^q-mathbfj frac1mathbfkD^mathbfk a_r(mathbfμ) M_mathbfj+mathbfk + dotsb Bigg - sum_j i_j fracdmu_jdt M_mathbfi_j- \r\nendalign*","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"where we have also defined","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign*\r\n M_mathbfi_j-=M_i_1dotsci_j-1dotsc i_N \r\n M_mathbfj+mathbfk = M_j_1+k_1dotscj_N+k_N \r\nendalign*","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"Although raw moment equations for non-linear mass-action systems already require approximate treatment using moment closure, here we have an additional complication: if a system contains non-polynomial propensity functions, the equations for both means and central moments will in principle depend on an infinite number of higher order central moments. Hence the Taylor expansion order q is of utmost importance as it controls the degree of approximation: the propensity functions are expanded up to q^textth order so that m^textth central moment equations will depend on central moments of order qm and lower. Finally, moment closure approximations can be applied similarly as in the case of raw moment equations.","category":"page"},{"location":"theory/moment_expansion_CME/#References","page":"Moment Expansion (CME)","title":"References","text":"","category":"section"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"[1]: D. Schnoerr, G. Sanguinetti, and R. Grima, \"Approximation and inference methods for stochastic biochemical kinetics - a tutorial review\", Journal of Physics A: Mathematical and Theoretical 50, 093001 (2017). https://doi.org/10.1088/1751-8121/aa54d9","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"[2]: P. Milner, C. S. Gillespie, and D. J. Wilkinson, \"Moment closure approximations for stochastic kinetic models with rational rate laws\", Mathematical Biosciences 231, 99-104 (2011). https://doi.org/10.1016/j.mbs.2011.02.006","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"[3]: A. Ale, P. Kirk, and M. P. H. Stumpf, \"A general moment expansion method for stochastic kinetic models\", The Journal of Chemical Physics 138, 174101 (2013). https://doi.org/10.1063/1.4802475","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"[4]: C. H. Lee, \"A Moment Closure Method for Stochastic Chemical Reaction Networks with General Kinetics\", MATCH Communications in Mathematical and in Computer Chemistry 70, 785-800 (2013). https://match.pmf.kg.ac.rs/electronicversions/Match70/n3/match70n3785-800.pdf","category":"page"},{"location":"theory/moment_closure_approximations/#moment_closure_approximations","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"In the previous section, we have shown that for a non-linear system an infinite hierarchy of coupled moment equations is obtained that cannot be solved directly and, therefore, needs to be truncated in an approximate way. This can be achieved using moment closure approximations (MAs), in which all moments above a certain order m are expressed in terms of m^textth and lower order moments using various (usually distributional) assumptions [1]. Doing so enables us to effectively close the moment hierarchy, leading to a finite set of ODEs which can then be solved numerically. In this section, we present some the commonly used MA methods that are implemented in MomentClosure. Please see the Tutorials section for examples showing different MAs applied to a variety of systems.","category":"page"},{"location":"theory/moment_closure_approximations/#zero_closure","page":"Moment Closure Approximations","title":"Zero Closure","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"The simplest MA is the \"central-moment-neglect\" MA (CMN-MA) [2], also referred to as \"zero-closure\" [3] or \"low dispersion moment closure\" [4], where CMN-MA at m^textth order means that the moment equations are truncated by setting all central moments above order m to zero. For example, in the simple case of 2nd order truncation, the moment equations for the means mu_i and covariances C_ij become:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n fracd mu_idt = sum_r S_ir Big( a_r(mathbfμ) + frac12sum_i_1 i_2 fracpartial^2 a_r(mathbfμ)partial n_i_1 partial n_i_2 M_i_1 i_2 Big) \r\n fracdC_ijdt = fracdM_mathbf0_i+ j+dt \r\n = fracdlangle (n_i-mu_i) (n_j-mu_j) rangledt = \r\n = sum_r Big S_ir sum_k fracpartial a_r(mathbfμ)partial n_k C_jk + S_jr sum_k fracpartial a_r(mathbfμ)partial n_k C_ik \r\n + S_irS_jr Big( a_r(mathbfμ) + frac12 sum_k l fracpartial^2 a_r(mathbfμ)partial n_k partial n_l C_kl Big) Big \r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/#normal_closure","page":"Moment Closure Approximations","title":"Normal Closure","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Another popular MA is the \"normal moment-closure\", pioneered by Goodman [5] and Whittle [6], where all cumulants kappa_mathbfi above order m are set to zero, approximating the probability distribution of the system with the normal distribution [2]:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n kappa_mathbfi = 0 quad textfor mathbfi m\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"In order to truncate the higher order central or raw moments M_mathbfi using normal closure we express them in terms of cumulants kappa_mathbfi using the multivariate moment and cumulant relationships formalised by Balakrishnan et al. [7].","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Note that a different implementation of normal closure can be found in literature [3], where the higher order central moments are expressed in terms of a sum of product of covariances using Isserlis' theorem. However, one could argue that such formulation is not advisable as it assumes stronger \"Gaussianity\" of the underlying distribution than setting the higher order cumulants to zero which is less of an approximation on the form of the distribution and hence is preferable in the development of MAs. For example, in case we are truncating the moment equations at 4th order, the truncation-order central moments would be expressed only in terms of covariances whereas our formulation using cumulants would explicitly include information about the computed values of third central moments, which is expected to improve numerical stability and lead to more accurate moment estimates.","category":"page"},{"location":"theory/moment_closure_approximations/#poisson_closure","page":"Moment Closure Approximations","title":"Poisson Closure","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Although the Poisson distribution lacks a general formulation for multiple variables [3], \"Poisson MA\" has been formulated [2, 8] assuming that the joint multivariate distribution is a product of univariate Poisson distributions, i.e., n_i sim textPoisson(mu_i). The cumulants of a univariate Poisson distribution are equal to the mean, hence in Poisson closure we set all higher order diagonal cumulants to the corresponding mean values and mixed cumulants to zero [2], which in our notation can be expressed as:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n kappa_mathbfi = mu_j quad textif i_j m textand i_jneq k = 0 quad textfor some j k in 1dotscN \r\n kappa_mathbfi = 0 quad textif mathbfi m textand i_j neq i_k (textwhere i_j neq 0 i_k neq 0) quad textfor some j k in 1dotscN\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Similarly to normal closure, the higher order central/raw moments can be expressed in terms of cumulants as described in [7].","category":"page"},{"location":"theory/moment_closure_approximations/#log-normal_closure","page":"Moment Closure Approximations","title":"Log-normal Closure","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"\"Log-normal\" MA, first applied by Keeling [9], allows one to truncate the moment equations under the assumption that the distribution of the underlying stochastic process is log-normal. A positive multi-dimensional random variable mathbfn follows a log-normal distribution if its logarithm is normally distributed, so that mathbfy = ln mathbfn, and mathbfy sim mathcalN(mathbfnu Sigma), where mathbfnu and Sigma denote the vector of means and the covariance matrix respectively. By considering the moment generating function of the normal distribution, mathcalN(mathbfnu Sigma), one can show that the raw moments are given by [3, 10]:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n mu_mathbfi = expleft(mathbfi^topmathbfnu + frac12mathbfi^topSigmamathbfiright)\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"It follows that","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n nu_i = ln mu_i - frac12 Sigma_ii \r\n Sigma_ij = ln left( 1 + fraclangle (n_i - mu_i)(n_j - mu_j) rangleexp left( nu_i + nu_j + frac12 left( Sigma_ii + Sigma_jj right) right) right) \r\n = ln left( 1 + fracC_ijexp left( nu_i + nu_j + frac12 left( Sigma_ii + Sigma_jj right) right) right) \r\n Sigma_ii = ln left( 1 + fracC_iimu_i^2 right) \r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Note that central moments can be obtained from raw moments by utilising their general multivariate relationship [11].","category":"page"},{"location":"theory/moment_closure_approximations/#gamma_closure","page":"Moment Closure Approximations","title":"Gamma Closure","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"The method of \"gamma closure\" was originally implemented by Lakatos et al. [3], where the authors acknowledged the ambiguity arising in defining multivariate gamma distributions, and, building upon previous definitions in the literature (e.g. [12] and [13]), proposed a new formulation of a multivariate gamma distribution. Here we reproduce the definition by closely following the description in [3] and elucidating some of the derivation steps.","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"We denote a random variable drawn from gamma distribution with shape alpha and scale beta as n sim textGamma(alpha beta). The probability density function of the univariate gamma distribution with the corresponding shape-scale parameterisation is","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n f(n alpha beta) = frac1Gamma(alpha)beta^alpha n^alpha-1e^-fracnbeta\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"where Gamma is the gamma function. The i^textth raw moment of n is given by","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n μ_i = fracGamma(alpha+i)beta^iGamma(alpha) = (alpha)_i beta^i taga\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"where (alpha)_i = alpha (alpha+1) dotsm (alpha+i-1). Note that the moment generating function of X is","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n G_n(k) = langle e^kn rangle = left( 1 - beta k right)^-alpha\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"In order to construct a multivariate gamma distribution, we start by considering independent gamma variables Y_kl, k l = 1 dotsc N, with shape and scale parameters alpha_kl and beta_kl respectively. Here we define Y_kl to be symmetric in indices, i.e., Y_kl = Y_lk. Now consider an N-dimensional random vector mathbfn = left( n_1 n_2 dotsc n_N right), where n_i is a linear combination of independent gamma variables:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n n_i = sum_j=1^N fracbeta_iibeta_ij Y_ij\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"The i^textth marginal moment generating function of the joint distribution of mathbfn is given by:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n G_n_i(k_i) = leftlangle e^k_i sum_j=1^N fracbeta_iibeta_ij rightrangle \r\n = G_Y_i1left(k_i fracbeta_iibeta_i1 right) G_Y_i2left(k_i fracbeta_iibeta_i2 right) dotsm G_Y_iNleft(k_i fracbeta_iibeta_iN right) \r\n = left(1-beta_ii k_i right)^sum_j=1^N alpha_ij\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"so that n_i sim textGamma(alpha_i beta_i), where alpha_i = sum_j=1^N alpha_ij and beta_i = beta_ii. Therefore, we have obtained an N-variate gamma distribution, which can be denoted as mathbfn sim MG(mathbfalpha mathbfbeta), where the vectors of shape and scale parameters are given by mathbfalpha = left( alpha_1 dotsc alpha_N right) and mathbfbeta = left( beta_1 beta_2 dotsc beta_N right) respectively.","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"We can now readily obtain the raw m^textth order moment of n_i:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n langle n_i^m rangle = leftlangle left( sum_j=1^N fracbeta_iibeta_ij Y_ij right)^m rightrangle \r\n = leftlangle sum_k_1+k_2+dotsb+k_N = m fracmk_1k_2 dotsm k_N prod_j=1^N left( fracbeta_iibeta_ij Y_ij right)^k_j rightrangle \r\n = sum_mathbfk=m fracmmathbfk prod_j=1^N leftlangle left( fracbeta_iibeta_ij Y_ij right)^k_j rightrangle \r\n = beta_i^m sum_mathbfk=m fracmmathbfk left(\r\n prod_j=1^N left( alpha_ij right)_k_j right)\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Note that we have used Eq. (a) to get to the last line. The mixed raw moments are computed in a similar fashion:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n mu_mathbfi = leftlangle left( sum_j=1^N fracbeta_11beta_1jY_1j right)^i_1 dotsm left( sum_j=1^N fracbeta_NNbeta_NjY_Nj right)^i_N rightrangle \r\n = mathbfbeta^mathbfi leftlangle sum_mathbfk_1=i_1 dotsm sum_mathbfk_N=i_N fracmathbfimathbfk_1dotsmmathbfk_N prod_j=1^N left( fracY_1jbeta_1j right)^k_1_j dotsm prod_j=1^N left( fracY_Njbeta_Nj right)^k_N_j rightrangle \r\n = mathbfbeta^mathbfi leftlangle sum_mathbfk_1=i_1 dotsm sum_mathbfk_N=i_N fracmathbfimathbfk_1dotsmmathbfk_N prod_q=1^N left( fracY_qqbeta_qq right)^k_q_q prod_r=q+1^N left( fracY_qrbeta_qr right)^k_q_r + k_r_q rightrangle \r\n = mathbfbeta^mathbfi sum_mathbfk_1=i_1 dotsm sum_mathbfk_N=i_N fracmathbfimathbfk_1dotsmmathbfk_N prod_q=1^N left( alpha_qq right)_k_q_q prod_r=q+1^N left( alpha_qr right)_k_q_r + k_r_q\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"where we have taken into account the symmetry in indices and defined each mathbfk_i as an N-dimensional vector mathbfk_i = left( k_i_1 dotsc k_i_N right) and mathbfbeta^mathbfi = beta_1^i_1 dotsm beta_N^i_N. Note that the mean and variance of n_i can be obtained from:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n mu_i = sum_j=1^N alpha_ij beta_i tagb \r\n C_ii = (alpha_i)_2 beta_i^2 - alpha_i^2beta_i^2 \r\n = sum_j=1^N alpha_ij beta_i^2\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Similarly, from Eq. (a) it follows that","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n langle n_i n_j rangle = beta_i beta_j left( sum_substackk l (k l) neq (j i)^N alpha_ik alpha_jl + (alpha_ij)_2 right)\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"which together with Eq. (b) allows us to express the covariance as:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n C_ij = langle n_i n_j rangle - beta_i beta_j left( sum_kl alpha_ik alpha_jl right) \r\n = alpha_ij beta_i beta_j\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Finally, from the equations above we can obtain all shape and scale parameters:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n beta_i = fracC_iimu_i \r\n alpha_ij = fracC_ijbeta_i beta_j \r\n alpha_ii = fracmu_ibeta_i - sum_substackk k neq i alpha_ik\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/#derivative_matching","page":"Moment Closure Approximations","title":"Derivative Matching","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"The derivative matching MA [14, 15] is based on expressing moments above order m in terms of lower order moments in such a way that their time derivatives match those of the exact moments at some initial time and initial conditions. We outline the approach below, closely following the complete exposition found in the original papers of Singh and Hespanha [14, 15].","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"The raw moment equations up to order m for any mass-action reaction network containing at most bimolecular (second order) reactions can be written down concisely in the matrix form:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n fracdmathbfμdt = hatmathbfa + Amathbfμ + B barmathbfμ \r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"where mathbfμ is a vector containing all raw moments of the system up to order m and barmathbfμ consists of all (m+1)^textth order raw moments which the equations depend on. The constant vector hatmathbfa and constant matrices A and B are chosen appropriately for the system at hand. In this case, an MA can be defined as a procedure where each moment in barmathbfμ, barμ_mathbfi, is approximated by a moment closure function varphi_mathbfi (mathbfμ) of moments up to order m. Then the moment equations can be rewritten as","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":" fracdmathbfνdt = hatmathbfa + Amathbfν + Bbarmathbfφ(mathbfν) ","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"where the state of the system is now denoted by mathbfν instead of mathbfμ, stressing the fact that we are considering the approximation of the true moment dynamics, and barmathbfφ(mathbfν) is the corresponding vector of moment closure functions.","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"The idea behind derivative matching is to determine a map barmathbfφ so that the time derivatives between the exact moments, mathbfμ(t), and the approximate moments, mathbfν(t), would match at some initial time t_0 under the initial condition mathbfμ(t_0) = mathbfν(t_0):","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n left fracd^i mathbfμdt rightrvert_t=t_0 = left fracd^i mathbfνdt rightrvert_t=t_0\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"If these conditions hold, one can expect from a Taylor series approximation argument that mathbfμ(t) and mathbfν(t) will stay close at least locally in time and hence the MA will be sufficiently accurate.","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"In order to move forward, Singh and Hespanha present what can be understood as essentially an ansatz. Firstly, moment closure functions for each mathbfi, where mathbfi m, are chosen to have a separable form given by","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n φ_mathbfi(mathbfμ) = prod_substack1 leq j_1+dotsb+j_N leq m left( μ_mathbfj right)^γ_mathbfj = prod_mathbfj=1^m left( μ_mathbfj right)^γ_mathbfj \r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"where γ_mathbfj are constants (unique for each vector mathbfi) that can be determined by solving the following linear equation system:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n C^mathbfi_mathbfj = sum_mathbfk=1^m gamma_mathbfk C^mathbfk_mathbfj quad textfor each mathbfj textwhere mathbfjleq m \r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"were we have introduced multi-index scalars","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n C^mathbfu_mathbfv = C^u_1_v_1C^u_2_v_2 dotsm C^u_N_v_N\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"with each element defined as","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\nC^a_b =\r\nbegincases\r\n fraca(a-b)b a geq b \r\n 0 a lt b\r\nendcases\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Using the specific construction of barmathbfφ described above, it can be shown [15] that for every deterministic initial condition, i.e., mathbfn(t_0) = mathbfn_0 with probability one, we will have","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n mathbfμ(t_0) = mathbfν(t_0) implies left fracd mathbfμdt rightrvert_t=t_0 = left fracd mathbfνdt rightrvert_t=t_0 \r\n implies left fracd^2mathbfμdt^2 rightrvert_t=t_0 = left fracd^2 mathbfνdt^2 rightrvert_t=t_0 + mathbfϵ(mathbfn_0) \r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"where all elements of mathbfϵ(mathbfn_0) are zero except the ones corresponding to m^textth order raw moments—these elements are second order polynomials in mathbfn_0. Note, however, that these results hold only for mass-action systems containing no higher than second order chemical reactions. While the derivative matching MA can be applied in the same way to systems containing higher order polynomial and non-polynomial propensity functions, it has not been rigorously analysed in such scenarios, where, naturally, we expect significantly larger approximation errors.","category":"page"},{"location":"theory/moment_closure_approximations/#conditional_closures","page":"Moment Closure Approximations","title":"Conditional Closures","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"As standard MAs often fail to provide sufficiently accurate approximations of chemical reaction networks involving both high- and low-abundance species, some novel approaches suggest using moments conditioned on the low-copy number species, which can lead to a more effective description of the system dynamics [1, 16]. Here we discuss the conditional moment closure proposed by Soltani et al. (2015) [16], applicable to networks containing molecular species which copy number can be either zero or one, i.e., a binary/Bernoulli random variable. Such conditional MA can be very useful in the study of gene networks where two-state gene systems are often considered—the gene state itself can be treated as a distinct species which molecule number is a Bernoulli variable.","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"The conditional MA is based on conditioning the higher order moments of high-abundance species on the binary species being in state 1 (instead of 0) and then applying standard MAs on the conditional moments. Closely following Soltani et al. [16], we use a two-state gene circuit to illustrate the conditional MAs, denoting the binary gene state by g and the protein number (high-abundance species) by p. Firstly, note that as g is a Bernoulli variable the following identities hold","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\nlangle g^j p rangle = langle g rangle quad j in 2 3 dotsc \r\nlangle g^j p^k rangle = langle g p^k rangle quad jk in 1 2 3 dotsc\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Therefore, we only need to concern ourselves with moments of the form langle p^k rangle and langle gp^k rangle. The former can be approximated using the standard MAs (no conditioning needed), whereas the latter can be written down as:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\nlangle gp^j rangle = langle p^j g=1 rangle langle g rangle quad jin 12 dotsc\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Now the conditional moment langle p^j g= 1 rangle can be expressed in terms of lower order conditional moments using one of the standard MAs, e.g., normal closure or derivative matching—the two methods (including the conditioning step) are respectively known as the conditional gaussian and conditional derivative matching MAs. For completeness, we show how the two methods are applied to approximate a specific higher order moment:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n langle gp^3 rangle = langle p^3 g=1 rangle langle g rangle\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/#conditional_gaussian_closure","page":"Moment Closure Approximations","title":"Conditional Gaussian Closure","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Under the conditional Gaussian MA, we assume that the number of protein molecules conditioned on the gene being active, p g = 1, follows a Gaussian distribution. In other words, we apply normal MA on the conditional moment langle p^j g=1 rangle. Hence we obtain (following the example above):","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\nlangle p^3 g= 1 rangle = 3 langle p^2 g = 1 rangle langle p g=1 rangle - 2 langle p g=1 rangle^3\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Using langle gp^j rangle = langle p^j g=1 rangle langle g rangle, we can rewrite the equation as:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\nlangle p^3 g= 1 rangle = 3 fraclangle gp^2 rangle langle gp ranglelangle g rangle^2 - 2 fraclangle gp rangle^3langle g rangle^3\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Plugging this into the previous expression of the higher-order moment langle gp^3 rangle we finally obtain:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\n langle gp^3 rangle = 3 fraclangle gp^2 rangle langle gp ranglelangle g rangle - 2 fraclangle gp rangle^3langle g rangle^2\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/#conditional_derivative_matching","page":"Moment Closure Approximations","title":"Conditional Derivative Matching","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"The conditional derivative matching boils down to approximating the higher order conditional moments in terms of lower order conditional moments using the standard derivative matching:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\nlangle p^3 g = 1 rangle = fraclangle p^2 g = 1 rangle^3langle p g= 1 rangle^3\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Using langle gp^j rangle = langle p^j g=1 rangle langle g rangle again, we find:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\nlangle gp^3 rangle = fraclangle gp^2 rangle^3 langle g ranglelangle gp rangle^3\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Note that conditional moment closure is fully applicable to systems containing multiple binary species. For example, given two two-state genes, g_1 and g_2, the same Bernoulli variable properties hold and the higher-order moments can be expressed as:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\r\nlangle g_1 g_2 p^j rangle = langle p^j g_1 = g_2 = 1 rangle langle g_1 g_2 rangle quad j in 12dotsc\r\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Such higher order conditional moments can again be closed using normal closure or derivative matching.","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Note that the description here is taken from [16] and we urge the reader to see the paper for more details. In addition, we have used MomentClosure to apply conditional closures on genetic feedback loops and reproduce some of the published results in this example.","category":"page"},{"location":"theory/moment_closure_approximations/#References","page":"Moment Closure Approximations","title":"References","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[1]: D. Schnoerr, G. Sanguinetti, and R. Grima, \"Approximation and inference methods for stochastic biochemical kinetics - a tutorial review\", Journal of Physics A: Mathematical and Theoretical 50, 093001 (2017). https://doi.org/10.1088/1751-8121/aa54d9","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[2]: D. Schnoerr, G. Sanguinetti, and R. Grima, \"Comparison of different moment-closure approximations for stochastic chemical kinetics\", The Journal of Chemical Physics 143, 185101 (2015). https://doi.org/10.1063/1.4934990","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[3]: E. Lakatos, A. Ale, P. D. W. Kirk, and M. P. H. Stumpf, \"Multivariate moment closure techniques for stochastic kinetic models\", The Journal of Chemical Physics 143, 094107 (2015). https://doi.org/10.1063/1.4929837","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[4]: J. Hespanha, \"Moment closure for biochemical networks\", in 2008 3rd International Symposium on Communications, Control and Signal Processing (Mar. 2008), pp. 142–147. https://doi.org/10.1109/ISCCSP.2008.4537208","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[5]: L. A. Goodman, \"Population Growth of the Sexes\", Biometrics 9, Publisher: [Wiley, International Biometric Society], 212–225 (1953). https://doi.org/10.2307/3001852","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[6]: P. Whittle, \"On the use of the normal approximation in the treatment of stochastic processes\", Journal of the Royal Statistical Society: Series B (Methodological) 19, 268–281 (1957). https://doi.org/10.1111/j.2517-6161.1957.tb00263.x","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[7]: N. Balakrishnan, N. L. Johnson, and S. Kotz, “A note on relationships between moments, central moments and cumulants from multivariate distributions”, Statistics & Probability Letters 39, 49–54 (1998). https://doi.org/10.1016/S0167-7152(98)00027-3","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[8]: I. Nasell, \"An extension of the moment closure method\", Theoretical Population Biology 64, 233–239 (2003). https://doi.org/10.1016/S0040-5809(03)00074-1","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[9]: M. J. Keeling, \"Multiplicative Moments and Measures of Persistence in Ecology\", Journal of Theoretical Biology 205, 269–281 (2000). https://doi.org/10.1006/jtbi.2000.2066","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[10]: E. L. Crow and K. Shimizu, eds., Lognormal Distributions: Theory and Applications (Marcel Dekker, 1988).","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[11]: N. L. Johnson, S. Kotz, and N. Balakrishnan, Discrete Multivariate Distributions (Wiley, Feb. 1997).","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[12]: A. M. Mathal and P. G. Moschopoulos, \"A form of multivariate gamma distribution\", Annals of the Institute of Statistical Mathematics 44, 97–106 (1992). https://doi.org/10.1007/BF00048672","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[13]: E. Furman, \"On a multivariate gamma distribution\", Statistics & Probability Letters 78, 2353–2360 (2008). https://doi.org/10.1016/j.spl.2008.02.012","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[14]: A. Singh and J. P. Hespanha, \"Lognormal Moment Closures for Biochemical Reactions\", in Proceedings of the 45th IEEE Conference on Decision and Control, ISSN:0191-2216 (Dec. 2006), pp. 2063–2068. https://doi.org/10.1109/CDC.2006.376994","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[15]: A. Singh and J. P. Hespanha, \"Approximate Moment Dynamics for Chemically Reacting Systems\", IEEE Transactions on Automatic Control 56, 414–418 (2011). https://doi.org/10.1109/TAC.2010.2088631","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[16]: M. Soltani, C. A. Vargas-Garcia, and A. Singh, \"Conditional Moment Closure Schemes for Studying Stochastic Dynamics of Genetic Circuits\", IEEE Transactions on Biomedical Circuits and Systems 9, 518–526 (2015). https://doi.org/10.1109/tbcas.2015.2453158","category":"page"},{"location":"tutorials/LMA_example/#linear_mapping_approximation_example","page":"LMA Example","title":"LMA Example","text":"","category":"section"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"In this example, we demonstrate how the Linear Mapping Approximation (LMA) can be applied on chemical reaction networks using MomentClosure. We illustrate the approach on models of a simple nonlinear feedback loop and a genetic toggle switch, in turn reproducing some of the results published in the original LMA paper by Cao and Grima [1].","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"We start by considering a simple nonlinear gene regulatory network (GRN) shown in the diagram below (adapted from [1]):","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"⠀","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"Here we have a two-state gene promoter which can be in either state G or G^*. As in a previous example tutorial, we interpret the gene as a distinct species modelled as a Bernoulli variable g, associating the states G and G^* with values g=1 and g=0 respectively. Protein P is produced from both gene states G and G^* (with different rates ρ_u and ρ_b) and can subsequently decay. The switch between G and G^* (or the feedback) is introduced via protein binding to the gene in state G.","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"The first step in applying the LMA is to transform the nonlinear GRN into a linear GRN. This can be done by removing the second-order reaction between P and G, so that the reversible reaction G+P undersetσ_ustackrelσ_brightleftharpoons G^* is replaced by G undersetσ_ustackrelbarσ_brightleftharpoons G^*. This equivalent linear GRN can be visualised as (adapted from [1]):","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"⠀","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"Note that MomentClosure cannot automate this linearisation step as the choice of how the other reactions in the network are changed due to the removal of nonlinear reactions is arbitrary. For this reason, we define both nonlinear and linear GRNs using Catalyst as follows:","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"using Catalyst\r\n\r\n# NOTE: both models MUST preserve the same ordering of reactions in order to detect\r\n# how the nonlinear reactions are to be transformed using LMA\r\n\r\nrn_nonlinear = @reaction_network begin\r\n @parameters σ_b σ_u ρ_b ρ_u\r\n σ_b, g + p → 0\r\n σ_u*(1-g), 0 ⇒ g + p\r\n ρ_u, g → g + p\r\n ρ_b*(1-g), 0 ⇒ p\r\n 1, p → 0\r\nend \r\n\r\nrn_linear = @reaction_network begin\r\n @parameters σ_b_LMA σ_u ρ_b ρ_u\r\n σ_b_LMA, g → 0 # typing ̄σ_b is not allowed it seems\r\n σ_u*(1-g), 0 ⇒ g\r\n ρ_u, g → g+p\r\n (ρ_b*(1-g)), 0 ⇒ p\r\n 1, p → 0\r\nend ","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"We can now apply the LMA to find the effective parameter barσ_b and generate the corresponding moment equations of the linear GRN using MomentClosure's linear_mapping_approximation:","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"using MomentClosure\r\n\r\n# NOTE: we have to provide the indices of binary variables in the system as they are ordered in the *nonlinear* GRN.\r\n# The distinction here between linear and nonlinear GRNs is important as in some cases the internal ordering of variables of the two Catalyst models can differ\r\n@parameters t\r\n@variables g(t)\r\nbinary_vars = [speciesmap(rn_nonlinear)[g]]\r\n\r\nLMA_eqs, effective_params = linear_mapping_approximation(rn_nonlinear, rn_linear, binary_vars, combinatoric_ratelaws=false)\r\ndisplay(effective_params)","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"OrderedDict{Any, Any} with 1 entry:\r\n σ_b_LMA => σ_b*μ₁₁(t)*(μ₁₀(t)^-1)","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"We can also print out the moment equations:","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"using Latexify\r\nlatexify(LMA_eqs)","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"beginalign*\r\nfracdmu_10dt = sigma_u - sigma_b mu_11 - sigma_u mu_10 \r\nfracdmu_01dt = rho_b + rho_u mu_10 - mu_01 - rho_b mu_10 \r\nfracdmu_11dt = rho_u mu_10 + sigma_u mu_01 - mu_11 - sigma_u mu_11 - sigma_b mu_10^-1 mu_11^2 \r\nfracdmu_02dt = rho_b + rho_u mu_10 + 2 rho_b mu_01 + 2 rho_u mu_11 + mu_01 - 2 mu_02 - rho_b mu_10 - 2 rho_b mu_11\r\nendalign*","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"Note that the results agree with Eqs. (1) and (2) (after a corresponding substitution) given in [1]. The moment equations are already closed, so we can solve them numerically and plot the mean protein number over time:","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"using OrdinaryDiffEq, Sundials, Plots\r\n\r\n# [g, p] as in `species(rn_nonlinear)`\r\nu₀ = [1.0, 0.001]\r\np = [0.004, 0.25, 25.0, 60.0]\r\ntspan = (0., 15.)\r\ndt = 0.1\r\n\r\nu₀map = deterministic_IC(u₀, LMA_eqs)\r\noprob_LMA = ODEProblem(LMA_eqs, u₀map, tspan, p)\r\nsol_LMA = solve(oprob_LMA, CVODE_BDF(), saveat=dt)\r\n\r\nplot(sol_LMA, idxs=[2], label=\"LMA\", ylabel=\"⟨p⟩\", xlabel=\"time\", fmt=\"svg\")","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"(Image: LMA feedback loop mean protein number)","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"To compare the LMA result to the true moment dynamics we use the Finite State Projection (FSP) algorithm implemented in FiniteStateProjection.jl. FSP can be much more efficient than SSA in accurately approximating the full time-dependent probability distribution of the given chemical system when the system's state space is small (hence it is particularly effective for the nonlinear GRN here). Having obtained the FSP solution, we can extract the time-evolution of moments using get_moments_FSP function and finally compare it to the LMA prediction. This can all be done as follows:","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"using FiniteStateProjection\r\n\r\nfsp_sys = FSPSystem(rn_nonlinear, combinatoric_ratelaw=false)\r\n# Truncate the state space of the system\r\n# The gene has two states (G or G*) whereas we consider protein number from 0 to 100\r\nstate_space = [2, 101]\r\n\r\n# The initial condition is the matrix of probabilities representing the state of the system\r\n# We assume zero protein and the gene to be in the state G, hence the probability of this\r\n# specific state should be set to 1 initially\r\nu0 = zeros(state_space...)\r\nu0[2, 1] = 1.0\r\n\r\n# construct an ODE problem from the FSPSystem and solve it\r\nfsp_prob = ODEProblem(fsp_sys, u0, tspan, p)\r\nsol_FSP = solve(fsp_prob, CVODE_BDF(), saveat=dt)\r\n\r\n# extract the 1st order raw moments from the FSP solution\r\nμ_FSP = get_moments_FSP(sol_FSP, 1, \"raw\")\r\nplot!(sol_FSP.t, μ_FSP[(0,1)], label=\"FSP\", legend=:bottomright)","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"(Image: LMA and FSP feedback loop mean protein number)","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"Using the LMA as implemented in MomentClosure, we can generate and solve the closed moment equations for any LMA-suitable nonlinear chemical reaction network, given that its linear equivalent is also provided. Proceeding further to obtain an approximate time-dependent probability distribution of the nonlinear network is more involved as only a handful of closed-form solutions of linear networks are known. Moreover, simply computing the solutions can be a challenge due to their complicated analytical form. For these reasons, MomentClosure does not provide an automated approach to computing the probability distributions of the relevant nonlinear systems using LMA—these steps have to performed manually on a case-by-case basis. Nevertheless, below we demonstrate how this could be done for the nonlinear GRN we have been considering so far.","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"The CME of the nonlinear feedback loop can be solved exactly as described in [1] and, for completeness, we write down the main result here. The probability distribution of the number of proteins n_p at time t is given by (assuming the initial conditions to be zero protein in state G):","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"P left( n_p t right) = frac1n_p fracd^n_pdw^n_pleft( G_0(w t) + G_1(w t) right) _w=-1","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"where","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"beginalign*\r\nG_0(w t) = exp(ρ_b w) left f(we^-t) (-rho_Delta w)^1-Sigma M(1-barsigma_b 2-Sigma -rho_Delta w) \r\n+ g(we^-t)M(1+sigma_uSigma-rho_Delta w) right\r\nG_1(w t) = sigma_u^-1 exp(rho_b w) left -sigma_u f(we^-t)(-rho_Delta w)^1-Sigma M(-barsigma_b 2-Sigma -rho_Delta w) \r\n+barsigma_b g(we^-t) M(sigma_u Sigma -rho_Delta w) right\r\nendalign*","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"where w=z-1 and the probability generating functions are given by G_i(z t) = sum_n_p=0^infty z^n_p P_i(n_p t). The function M(cdotcdotcdot) stands for the Kummer's (confluent hypergeometric) function and we also use the following definitions:","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"beginalign*\r\n rho_Delta = rho_b - rho_u \r\n Sigma = sigma_u + barsigma_b + 1 \r\n f(w) = fracbarsigma_bSigma-1(-rho_Delta w)^Sigma-1e^-rho_u wM(sigma_u Sigma -rho_Delta w) \r\n g(w) = fracsigma_uSigma-1e^-rho_u w M(-barsigma_b 2-Sigma -rho_Delta w)\r\nendalign*","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"One can observe that having a closed-form solution does not make life that much easier as now we have to find a way how to numerically evaluate these complicated mathematical expressions in a reasonably efficient manner. The main problem here is that in order to construct the probability distribution we have to take arbitrarily high n^th order derivatives. Doing that symbolically is possible in principle but can be extremely computationally expensive as the symbolic expressions will be expanding exponentially in size with each higher derivative order: keeping them in memory is expensive and the same terms would have to be evaluated repeatedly many times. Similarly, naively nesting numerical derivative operations using an automatic differentiation framework is possible but still many redundant operations would need to be performed.","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"As pointed out by the authors in [1], a more efficient way is to expand the generating functions G_0(w t) + G_1(w t) around w=-1 as then the n^th Taylor series coefficient will be equivalent to the probability of having n proteins at time t. This approach can be particularly effective: recursion relations for the Taylor coefficients of various elementary functions can be defined and in turn utilised to minimise the amount of redundant work which has to be performed when Taylor expanding any given mathematical expression. Such higher-order automatic differentiation framework in Julia is provided by TaylorSeries.jl.","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"However, TaylorSeries only supports elementary function operations at the time and hence evaluating the Kummer's function M(cdotcdotcdot) requires some more work (these specialised numerics are readily available in more established scientific computing frameworks such as Mathematica but there's no fun in that). We can extend the TaylorSeries framework by constructing a function t_pFq that implements a recurrence relation between the Taylor coefficients for the generalized hypergeometric function pFq as defined in HypergeometricFunctions.jl. This can be done as follows (note that our construction is valid only for a single-variable Taylor series Taylor1):","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"using TaylorSeries, HypergeometricFunctions\r\nusing HypergeometricFunctions: pFqweniger\r\n\r\n# please let me know if a simpler and more efficient way to do this exists!\r\nfunction t_pFq(α::AbstractVector, β::AbstractVector, a::Taylor1)\r\n order = a.order\r\n aux = pFqweniger(α, β, constant_term(a))\r\n c = Taylor1(aux, order)\r\n\r\n iszero(order) && return c\r\n\r\n coeffs = t_pFq(α.+1, β.+1, Taylor1(a[0:end-1], a.order-1))\r\n factor = prod(α)/prod(β)\r\n for k in 1:length(a)-1\r\n c[k] = sum(i * a[i] * coeffs[k-i] for i in 1:k) * factor / k\r\n end\r\n\r\n return c\r\n\r\nend","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"We can now move on with the LMA procedure to obtain the probability distribution of the nonlinear GRN for the number of proteins at a chosen time point t=4. Step 4 of the LMA involves obtaining the time-independent effective parameter barsigma_b which is given by its time-averaged value:","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"# calculate the raw moments up to time t at a fine temporal resolution\r\nT = 4.0\r\ntspan = (0., T)\r\ndt = 0.001\r\noprob_LMA = remake(oprob_LMA, tspan=tspan)\r\nsol_LMA = solve(oprob_LMA, CVODE_BDF(), saveat=dt)\r\n\r\n# rebuild the symbolic expression for the effective parameter as a function of raw moments\r\nμ_sym = [LMA_eqs.odes.states...]\r\np_sub = Dict.(Pair.(LMA_eqs.odes.ps, p)...)\r\navg_σ_b_sym = collect(values(effective_params))[1]\r\nfn = build_function(substitute(avg_σ_b_sym, p_sub), μ_sym)\r\navg_σ_b = eval(fn)\r\n# evaluate the time-averaged value of the effective parameter\r\n@time σ_b_avg = sum(avg_σ_b.(sol_LMA.u)) * dt / T","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"We proceed with the very last steps of the LMA to obtain the probability distribution:","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"# need higher-precision numerics as Float64 can be unstable here due to very small numbers\r\n# DoubleFloats is sufficient for this example and much more efficient than BigFloat\r\nusing DoubleFloats\r\n\r\n# define the numerical values of the parameters\r\nσ_u = p[2]; ρ_b = p[3]; ρ_u = p[4]\r\nΣ = 1 + σ_b_avg + σ_u\r\nρ_Δ = ρ_b - ρ_u\r\n\r\nn = 100 # expansion order (or max protein number to evaluate)\r\nw₀ = -1 # value around which to expand\r\n\r\n# compute the Taylor expansion (note the use of Double64)\r\nw = w₀ + Taylor1(Double64, n)\r\n@time f = σ_b_avg/(Σ-1)*exp(-T*(Σ-1))*exp(-ρ_u*w*exp(-T))*t_pFq([σ_u], [Σ], -ρ_Δ*w*exp(-T))\r\n@time g = σ_u/(Σ-1)*exp(-ρ_u*w*exp(-T))*t_pFq([-σ_b_avg], [2-Σ], -ρ_Δ*w*exp(-T))\r\n\r\n@time G00 = exp(ρ_b*w)*(f * t_pFq([1-σ_b_avg], [2-Σ], -ρ_Δ*w) +\r\n g * t_pFq([1+σ_u], [Σ], -ρ_Δ*w) )\r\n\r\n@time G11 = σ_u^(-1) * exp(ρ_b*w) * (-σ_u*f*t_pFq([-σ_b_avg], [2-Σ], -ρ_Δ*w) +\r\n σ_b_avg*g*t_pFq([σ_u], [Σ], -ρ_Δ*w))\r\n\r\nprobs = (G00+G11).coeffs\r\n\r\n# check that the probability distribution is more or less normalised to 1\r\n# need higher numerical precision if not\r\nisapprox(sum(probs), 1.0, rtol=1e-2)","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"0.009289 seconds (41.03 k allocations: 1.603 MiB)\r\n0.009126 seconds (41.03 k allocations: 1.603 MiB)\r\n0.067889 seconds (85.06 k allocations: 3.613 MiB)\r\n0.066194 seconds (85.07 k allocations: 3.618 MiB)\r\ntrue","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"Finally, we can plot the distribution and compare it to the FSP result:","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"plot(0:n, probs, xlabel=\"n\", ylabel=\"P(n, t=4)\", label=\"LMA\", fmt=\"svg\")\r\n# plot the FSP probability of protein number by marginalising over the gene states\r\nplot!(0:n, sum(sol_FSP[:, 41], dims=1)'[1:n+1], label=\"FSP\")","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"(Image: LMA FSP feedback loop distribution)","category":"page"},{"location":"tutorials/LMA_example/#References","page":"LMA Example","title":"References","text":"","category":"section"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"[1]: Z. Cao and R. Grima, \"Linear mapping approximation of gene regulatory networks with stochastic dynamics\", Nature Communications 9, 3305 (2018). https://doi.org/10.1038/s41467-018-05822-0","category":"page"},{"location":"tutorials/time-dependent_propensities/#time-dependent-propensities","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"","category":"section"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"Here we consider an example of using time-dependent propensities in modelling chemical reaction networks using MomentClosure and DifferentialEquations. Following Schnoerr et al. (2015), we modify the Brusellator introduced earlier to include entrainment:","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"beginalign*\r\n2X + Y stackrelc_1rightarrow 3X \r\nX stackrelc_2(t)rightarrow Y \r\n undersetc_4stackrelc_3rightleftharpoons X\r\nendalign*","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"The rate constant of the second reaction is now a sinusoidal function of time:","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"beginalign*\r\n c_2(t) = c_2^0left(1+frac12sin(omega t) right) quad textif t leq tau \r\n c_2(t) = c_2^0 quad textif t tau\r\nendalign*","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"where c_2^0 is a fixed value and the sinusoidal modulation with frequency omega is switched off after a certain time tau. We can define the model and generate the corresponding moment equations as follows:","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"using Catalyst, MomentClosure, Latexify\r\n\r\nrn = @reaction_network begin\r\n @parameters c₁ c₂ c₃ c₄ Ω ω τ\r\n (c₁/Ω^2), 2X + Y → 3X\r\n (c₂*(1+0.5*sin(ω*(t<τ)*t))), X → Y\r\n (c₃*Ω, c₄), 0 ↔ X\r\nend\r\n\r\nraw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=false)\r\nlatexify(raw_eqs)","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"beginalign*\r\nfracdmu_10dt = c_3 Omega + c_1 mu_21 Omega^-2 - c_2 mu_10 - c_4 mu_10 - c_1 mu_11 Omega^-2 - 05 c_2 mu_10 sinleft( t omega left( t tau right) right) \r\nfracdmu_01dt = c_2 mu_10 + c_1 mu_11 Omega^-2 + 05 c_2 mu_10 sinleft( t omega left( t tau right) right) - c_1 mu_21 Omega^-2 \r\nfracdmu_20dt = c_2 mu_10 + c_3 Omega + c_4 mu_10 + 2 c_1 mu_31 Omega^-2 + 05 c_2 mu_10 sinleft( t omega left( t tau right) right) + 2 c_3 Omega mu_10 - 2 c_2 mu_20 - 2 c_4 mu_20 - c_1 mu_11 Omega^-2 - c_1 mu_21 Omega^-2 - c_2 mu_20 sinleft( t omega left( t tau right) right) \r\nfracdmu_11dt = c_2 mu_20 + c_1 mu_11 Omega^-2 + c_1 mu_22 Omega^-2 + c_3 Omega mu_01 + 05 c_2 mu_20 sinleft( t omega left( t tau right) right) - c_2 mu_10 - c_2 mu_11 - c_4 mu_11 - c_1 mu_12 Omega^-2 - c_1 mu_31 Omega^-2 - 05 c_2 mu_10 sinleft( t omega left( t tau right) right) - 05 c_2 mu_11 sinleft( t omega left( t tau right) right) \r\nfracdmu_02dt = c_2 mu_10 + c_1 mu_21 Omega^-2 + c_2 mu_11 sinleft( t omega left( t tau right) right) + 2 c_2 mu_11 + 2 c_1 mu_12 Omega^-2 + 05 c_2 mu_10 sinleft( t omega left( t tau right) right) - c_1 mu_11 Omega^-2 - 2 c_1 mu_22 Omega^-2\r\nendalign*","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"We can now easily close the moment equations using normal closure and solve the resulting system of ODEs:","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"using OrdinaryDiffEq, Plots\r\n\r\nclosed_raw_eqs = moment_closure(raw_eqs, \"normal\")\r\n\r\n# parameter values [c₁, c₂, c₃, c₄, Ω, ω, τ]\r\np = [0.9, 2., 1., 1., 5., 1., 40.]\r\n\r\n# initial molecule numbers of species [X, Y]\r\nu₀ = [1., 1.]\r\n\r\n# deterministic initial conditions\r\nu₀map = deterministic_IC(u₀, closed_raw_eqs)\r\n\r\n# time interval to solve one on\r\ntspan = (0., 100.)\r\n\r\n# convert the closed raw moment equations into a DifferentialEquations ODEProblem\r\noprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)\r\n\r\n# solve using Tsit5 solver\r\nsol = solve(oprob, Tsit5(), saveat=0.2)\r\nplot(sol, idxs=[1,2], lw=2)","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"(Image: Time-dependent Brusselator normal)","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"It would be great to compare our results to the true dynamics. Using DifferentialEquations, we can run a modified SSA taking into account the time-dependent propensity functions (VariableRateJumps). This requires some care and is done by combining an ODEProblem with a JumpProblem:","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"using JumpProcesses\r\n\r\n# convert ReactionSystem into JumpSystem\r\njsys = convert(JumpSystem, rn, combinatoric_ratelaws=false)\r\n\r\n# Define an ODEProblem to integrate between reaction events\r\n# note that u₀ elements must be Floats (otherwise throws an error)\r\nf(du,u,p,t) = du .= 0\r\noprob = ODEProblem(f, u₀, tspan, p)\r\n\r\n# Create a modified SSA problem that now correctly incorporates VariableRateJumps\r\njprob = JumpProblem(jsys, oprob, Direct())","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"Finally, we can define a corresponding EnsembleProblem to simulate multiple SSA trajectories. However, the saveat argument does not work with VariableRateJumps (a known bug): without it, the solution is saved at each reaction event, in turn generating large data arrays that can get extremely memory-intensive when many trajectories are considered. Our workaround is to simply modify the output_func in EnsembleProblem so that each SSA trajectory is saved to the output array only at the specified timepoints (albeit a lot of garbage collection must be done):","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"# timestep at which the solution data is saved\r\ndt = 0.2\r\n# the corresponding time iterator (0:0.2:100 in our case)\r\nts = tspan[1]:dt:tspan[2]\r\n# save data for each trajectory only at the specified timepoints (interpolating the ODESolution)\r\nfout = (sol, i) -> (sol(ts), false)\r\nensembleprob = EnsembleProblem(jprob, output_func=fout)\r\n\r\n# simulate 10000 SSA trajectories (can get very slow...)\r\n@time sol_SSA = solve(ensembleprob, Tsit5(), trajectories=10000)","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"2975.249760 seconds (1.07 G allocations: 105.883 GiB, 81.30% gc time, 0.02% compilation time)","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"Finally, we can compute the mean SSA trajectories and compare to the moment closure estimates:","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"using SciMLBase.EnsembleAnalysis\r\n\r\nmeans_SSA = timeseries_steps_mean(sol_SSA)\r\nplot!(means_SSA.t, [means_SSA[1,:], means_SSA[2,:]], lw=1.5, labels=[\"SSA μ₁₀(t)\" \"SSA μ₀₁(t)\"], linestyle=:dash,\r\n linecolor=[1 2], background_color_legend=nothing, legend=:bottomright)","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"(Image: Time-dependent Brusselator SSA)","category":"page"},{"location":"tutorials/derivative_matching_example/#derivative-matching-example","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"","category":"section"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"In this example, we aim to reproduce a number of results from the original derivative matching paper by Singh and Hespanha [1]. We consider the bimolecular reaction system given by:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"beginalign*\r\nX_1 stackrelc_1rightarrow 2X_1 + X_2 \r\nX_1 + X_2stackrelc_2rightarrow X_2\r\nendalign*","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"The reaction network and its parameters can be defined as follows:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"using Catalyst\r\n\r\nrn = @reaction_network begin\r\n @parameters c₁ c₂\r\n (c₁), x₁ → 2x₁+x₂\r\n (c₂), x₁+x₂ → x₂\r\nend\r\n\r\n# parameter values\r\np = [1.0, 1.0]\r\n# initial conditions\r\nu0 = [20, 10]\r\n# time interval to solve on\r\ntspan = (0., 0.5)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"We are interested in extracting the time-evolution of a specific third order cumulant, κ_03, using second and third order moment expansions with derivative matching, and comparing the obtained estimates to the SSA prediction.","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"Let's start with a second order moment expansion and print out the third-order moment closure functions obtained with derivative matching:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"using MomentClosure, Latexify\r\n\r\neqs2 = generate_raw_moment_eqs(rn, 2)\r\ndm2_eqs = moment_closure(eqs2, \"derivative matching\")\r\nlatexify(dm2_eqs, :closure, print_all=true)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"beginalign*\r\nmu_30 = mu_10^-3 mu_20^3 \r\nmu_21 = mu_20 mu_01^-1 mu_10^-2 mu_11^2 \r\nmu_12 = mu_02 mu_01^-2 mu_10^-1 mu_11^2 \r\nmu_03 = mu_01^-3 mu_02^3\r\nendalign*","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"Note that all closure functions are consistent with the ones shown in Table II of [1]. We can then move on to solving the generated system of moment ODEs:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"using OrdinaryDiffEq\r\n\r\nu0map = deterministic_IC(u0, dm2_eqs) # assuming deterministic initial conditions\r\noprob = ODEProblem(dm2_eqs, u0map, tspan, p)\r\ndm2_sol = solve(oprob, Tsit5(), saveat=0.01)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"Now the question is how can we extract the time evolution of the cumulant kappa_03. Firstly, note that using the standard moment relationships it can be expressed in terms of raw moments as:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"beginalign*\r\nkappa_03 = 2 mu_01^3 - 3mu_02mu_01 + mu_03\r\nendalign*","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"As we were solving for moments up to second order, we do not have any direct information on the third order moment mu_03. Nevertheless, we can manually approximate it using the corresponding closure function given above, i.e., mu_03 = mu_01^-3 mu_02^3. The time trajectories of mu_01 and mu_02 can be extracted from dm2_sol and their order in the array can be checked with:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"dm2_eqs.odes.states","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"5-element Array{Term{Real,Nothing},1}:\r\n μ₁₀(t)\r\n μ₀₁(t)\r\n μ₂₀(t)\r\n μ₁₁(t)\r\n μ₀₂(t)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"Finally, we can combine all the steps to obtain the kappa_03 estimate:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"μ₀₁ = dm2_sol[2, :]\r\nμ₀₂ = dm2_sol[5, :]\r\nμ₀₃ = (μ₀₁ .^(-3)) .* (μ₀₂ .^3)\r\ndm2_κ₀₃ = 2 .* μ₀₁ .^3 .- 3 .* μ₀₂ .* μ₀₁ .+ μ₀₃","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"Next we consider a third order moment expansion:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"eqs3 = generate_raw_moment_eqs(rn, 3)\r\ndm3_eqs = moment_closure(eqs3, \"derivative matching\")\r\nlatexify(dm3_eqs, :closure, print_all=true)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"beginalign*\r\nmu_40 = mu_10^4 mu_20^-6 mu_30^4 \r\nmu_31 = mu_01 mu_30 mu_10^3 mu_11^-3 mu_20^-3 mu_21^3 \r\nmu_22 = mu_01^2 mu_02^-1 mu_10^2 mu_11^-4 mu_12^2 mu_20^-1 mu_21^2 \r\nmu_13 = mu_03 mu_10 mu_01^3 mu_02^-3 mu_11^-3 mu_12^3 \r\nmu_04 = mu_01^4 mu_02^-6 mu_03^4\r\nendalign*","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"As expected, the closure functions agree with those given in Table III of [1]. We again check the order of variables","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"dm3_eqs.odes.states","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"9-element Array{Term{Real,Nothing},1}:\r\n μ₁₀(t)\r\n μ₀₁(t)\r\n μ₂₀(t)\r\n μ₁₁(t)\r\n μ₀₂(t)\r\n μ₃₀(t)\r\n μ₂₁(t)\r\n μ₁₂(t)\r\n μ₀₃(t)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"and solve the moment equations, computing the required cumulant:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"u0map = deterministic_IC(u0, dm3_eqs)\r\noprob = ODEProblem(dm3_eqs, u0map, tspan, p)\r\ndm3_sol = solve(oprob, Tsit5(), saveat=0.01, abstol=1e-8, reltol=1e-8)\r\n\r\nμ₀₁ = dm3_sol[2,:]\r\nμ₀₂ = dm3_sol[5,:]\r\nμ₀₃ = dm3_sol[9,:]\r\ndm3_κ₀₃ = 2 .* μ₀₁ .^ 3 - 3 .* μ₀₂ .* μ₀₁ .+ μ₀₃","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"Note that we could have also obtained kappa_03 estimate in an easier way by using central moment equations, as third order central moments are equal to the corresponding third order cumulants:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"central_eqs3 = generate_central_moment_eqs(rn, 3)\r\ndm3_central_eqs = moment_closure(central_eqs3, \"derivative matching\")\r\n\r\nu0map = deterministic_IC(u0, dm3_central_eqs)\r\noprob = ODEProblem(dm3_central_eqs, u0map, tspan, p)\r\ndm3_central_sol = solve(oprob, Tsit5(), saveat=0.01, abstol=1e-8, reltol=1e-8)\r\n\r\n# check that the two estimates are equivalent\r\ndm3_κ₀₃ ≈ dm3_central_sol[9,:]","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"true","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"The last ingredient we need for a proper comparison between the second and third order moment expansions is a reference value predicted by the SSA. We can simulate 10^5 SSA trajectories as follows:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"using JumpProcesses\r\n\r\ndprob = DiscreteProblem(rn, u0, tspan, p)\r\njprob = JumpProblem(rn, dprob, Direct(), save_positions=(false, false))\r\n\r\nensembleprob = EnsembleProblem(jprob)\r\n@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.01, trajectories=100000)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"3.874558 seconds (7.45 M allocations: 714.845 MiB, 46.60% gc time)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"The time evolution of kappa_03 can be extracted from SSA data using the get_cumulants function:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"ssa_κ₀₃ = get_cumulants(sol_SSA, 3)[0, 3]","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"Finally, we plot the results:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"using Plots, LaTeXStrings\r\n\r\nplot(dm2_sol.t, dm2_κ₀₃, lw=2, label=\"2nd order DM\")\r\nplot!(dm2_sol.t, dm3_κ₀₃, lw=2, label=\"3rd order DM\")\r\nplot!(dm2_sol.t, ssa_κ₀₃, lw=2, label=\"SSA\")\r\nplot!(ylabel=L\"\\kappa_{03}\", xlabel=L\"t\", guidefontsize=14, legend=:bottomright)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"(Image: Derivative Matching cumulant)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"We observe that the third order moment truncation using derivative matching performs significantly better than the second order truncation, accurately matching the true SSA prediction (consistent with the figure in [1]).","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"It is also interesting to note that the closure functions of third order moments obtained using derivative matching and log-normal closures are equivalent. We can see that it is indeed the case by printing out the log-normal closure functions","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"ln2_eqs = moment_closure(eqs2, \"log-normal\")\r\nlatexify(ln2_eqs, :closure, print_all=true)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"beginalign*\r\nmu_30 = mu_10^-3 mu_20^3 \r\nmu_21 = mu_20 mu_01^-1 mu_10^-2 mu_11^2 \r\nmu_12 = mu_02 mu_01^-2 mu_10^-1 mu_11^2 \r\nmu_03 = mu_01^-3 mu_02^3\r\nendalign*","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"and the corresponding derivative matching functions obtained previously:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"latexify(dm2_eqs, :closure, print_all=true)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"beginalign*\r\nmu_30 = mu_10^-3 mu_20^3 \r\nmu_21 = mu_20 mu_01^-1 mu_10^-2 mu_11^2 \r\nmu_12 = mu_02 mu_01^-2 mu_10^-1 mu_11^2 \r\nmu_03 = mu_01^-3 mu_02^3\r\nendalign*","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"However, the equivalence holds only for third order moments. For example, the closure functions of fourth order moments differ:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"ln3_eqs = moment_closure(eqs3, \"log-normal\")\r\nlatexify(ln3_eqs, :closure, print_all=true)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"beginalign*\r\nmu_40 = mu_10^-8 mu_20^6 \r\nmu_31 = mu_01^-2 mu_10^-6 mu_11^3 mu_20^3 \r\nmu_22 = mu_02 mu_20 mu_01^-4 mu_10^-4 mu_11^4 \r\nmu_13 = mu_01^-6 mu_02^3 mu_10^-2 mu_11^3 \r\nmu_04 = mu_01^-8 mu_02^6\r\nendalign*","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"latexify(dm3_eqs, :closure, print_all=true)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"beginalign*\r\nmu_40 = mu_10^4 mu_20^-6 mu_30^4 \r\nmu_31 = mu_01 mu_30 mu_10^3 mu_11^-3 mu_20^-3 mu_21^3 \r\nmu_22 = mu_01^2 mu_02^-1 mu_10^2 mu_11^-4 mu_12^2 mu_20^-1 mu_21^2 \r\nmu_13 = mu_03 mu_10 mu_01^3 mu_02^-3 mu_11^-3 mu_12^3 \r\nmu_04 = mu_01^4 mu_02^-6 mu_03^4\r\nendalign*","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"This difference is expected as fourth order moments using log-normal closure are expressed exclusively in terms of first and second order moments, whereas derivative matching additionally incorporates third order moment information. Singh and Hespanha [1, 2] elaborate on this point: as there is no unique way to define higher order moment closure functions for log-normal distribution, both closures are consistent with the assumption that the population is jointly log-normally distributed. We urge the reader to consult the mentioned papers [1, 2] and the references therein for a more complete discussion comparing the two approaches.","category":"page"},{"location":"tutorials/derivative_matching_example/#References","page":"Derivative Matching Example","title":"References","text":"","category":"section"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"[1]: A. Singh and J. P. Hespanha, \"Lognormal Moment Closures for Biochemical Reactions\", in Proceedings of the 45th IEEE Conference on Decision and Control, ISSN:0191-2216 (Dec. 2006), pp. 2063–2068. https://doi.org/10.1109/CDC.2006.376994","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"[2]: A. Singh and J. P. Hespanha, \"Approximate Moment Dynamics for Chemically Reacting Systems\", IEEE Transactions on Automatic Control 56, 414–418 (2011). https://doi.org/10.1109/TAC.2010.2088631","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/#geometric-and-conditional","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"","category":"section"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"In this tutorial, we demonstrate using Catalyst how to define chemical systems involving reactions which products are geometrically distributed random variables. As an example, we consider an autoregulatory (repressive) genetic feedback loop where proteins are expressed in bursts with a geometric burst size distribution, as described by Soltani et al. [1]. Moreover, the state of the gene is modelled as a binary variable—we demonstrate how conditional derivative matching and conditional gaussian closures can be used to approximate such systems, in turn reproducing a number of results from Ref. [1].","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"We consider a negative feedback loop described by the following reactions:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"beginalign*\r\nG^* stackrelk_onrightarrow G \r\nG + stackrelk_off*P^2rightarrow G^* \r\nG stackrelk_prightarrow G + mP \r\nP stackrelgamma_prightarrow \r\nendalign*","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"A gene in the network switches between ON (G) and OFF (G^*) states: proteins are produced in the transcriptionally active ON state but the gene can be turned OFF by two protein molecules binding to the promoter region and thus blocking transcription (proteins decay at a constant rate irrespective of the gene state). Note that the gene state can be interpreted as a distinct species that have either zero or one copy number per cell. In other words, it is a Bernoulli random variable: 0 in the OFF state and 1 in the ON state.","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"The transcription (mRNA) dynamics are not modelled explicitly in this gene circuit. Instead, under the assumption of fast mRNA decay, proteins are taken to be produced in bursts of size m, where m is a random variable sampled from the geometric distribution phi(m) = b^m(1+b)^m+1 (with b denoting the mean burst size) [2]. Chemical reaction networks that include reactions which products are independent geometrically distributed random variables (or other symbolic variables) can be defined using Catalyst as demonstrated in this tutorial. Note that the referenced tutorial refers back to this tutorial because in the ancient times Catalyst did not provided such functionality and the previous iteration of MomentClosure implemented a ReactionSystemMod type that offered limited support for such systems (now deprecated as Catalyst does it better in a unified API).","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"Using Catalyst, our gene network model can be constructed as follows:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"# load all the packages we will need\r\nusing MomentClosure, Catalyst, Distributions, JumpProcesses, DiffEqBase, OrdinaryDiffEq, DiffEqBase.EnsembleAnalysis, Plots, Latexify\r\n\r\n# Proteins are produced in bursts of size m, where m is a geometric random variable with mean b.\r\n# Note that if b is the mean burst size, then p = 1/(1+b). \r\n# Implemented by first registering the distribution with Symbolics\r\n@register_symbolic Distributions.Geometric(b)\r\n@parameters b\r\nm = rand(Distributions.Geometric(1/(1+b)))\r\n\r\nrn = @reaction_network begin\r\n @parameters k_on k_off k_p γ_p\r\n k_on*(1-g), 0 --> g # G* -> G\r\n k_off*P^2, g --> 0 # G -> G*\r\n k_p, g --> g + $m*P # G -> G + mP, m ~ Geometric(p)\r\n γ_p, P --> 0 # P -> ∅\r\nend","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"We can now generate the raw moment equations up to third order:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"eqs = generate_raw_moment_eqs(rn, 3)\r\nlatexify(eqs)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"beginalign*\r\nfracdmu_1 0dt = k_on - k_off mu_1 2 - k_on mu_1 0 \r\nfracdmu_0 1dt = b k_p mu_1 0 - gamma_p mu_0 1 \r\nfracdmu_2 0dt = k_on + k_off mu_1 2 + k_on mu_1 0 - 2 k_on mu_2 0 - 2 k_off mu_2 2 \r\nfracdmu_1 1dt = k_on mu_0 1 + b k_p mu_2 0 - k_on mu_1 1 - gamma_p mu_1 1 - k_off mu_1 3 \r\nfracdmu_0 2dt = gamma_p mu_0 1 + b k_p mu_1 0 + 2 b k_p mu_1 1 + 2 k_p b^2 mu_1 0 - 2 gamma_p mu_0 2 \r\nfracdmu_3 0dt = k_on + 3 k_off mu_2 2 + 2 k_on mu_1 0 - k_off mu_1 2 - 3 k_off mu_3 2 - 3 k_on mu_3 0 \r\nfracdmu_2 1dt = k_on mu_0 1 + k_on mu_1 1 + k_off mu_1 3 + b k_p mu_3 0 - 2 k_on mu_2 1 - gamma_p mu_2 1 - 2 k_off mu_2 3 \r\nfracdmu_1 2dt = k_on mu_0 2 + gamma_p mu_1 1 + b k_p mu_2 0 + 2 k_p b^2 mu_2 0 + 2 b k_p mu_2 1 - k_off mu_1 4 - k_on mu_1 2 - 2 gamma_p mu_1 2 \r\nfracdmu_0 3dt = b k_p mu_1 0 + 3 gamma_p mu_0 2 + 3 b k_p mu_1 1 + 3 b k_p mu_1 2 + 6 k_p b^2 mu_1 0 + 6 k_p b^3 mu_1 0 + 6 k_p b^2 mu_1 1 - gamma_p mu_0 1 - 3 gamma_p mu_0 3\r\nendalign*","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"A lot of information in this system of ODEs is redundant as the gene state is a Bernoulli variable that (in our case) has the following properties:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"beginalign*\r\nμ_j0 = μ_10 quad j in 2 3 dotsc \r\nμ_jk = μ_1k quad jk in 1 2 3 dotsc\r\nendalign*","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"We can clean the moment equations accordingly by specifying which molecule numbers are Bernoulli variables and using the bernoulli_moment_eqs function:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"# specify the indices of species which molecule numbers are binary\r\nbinary_vars = [1]\r\n# simplify the moment equations using properties of Bernoulli variables\r\nclean_eqs = bernoulli_moment_eqs(eqs, binary_vars)\r\nlatexify(clean_eqs)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"beginalign*\r\nfracdmu_1 0dt = k_on - k_off mu_1 2 - k_on mu_1 0 \r\nfracdmu_0 1dt = b k_p mu_1 0 - gamma_p mu_0 1 \r\nfracdmu_1 1dt = k_on mu_0 1 + b k_p mu_1 0 - k_on mu_1 1 - gamma_p mu_1 1 - k_off mu_1 3 \r\nfracdmu_0 2dt = gamma_p mu_0 1 + b k_p mu_1 0 + 2 b k_p mu_1 1 + 2 k_p b^2 mu_1 0 - 2 gamma_p mu_0 2 \r\nfracdmu_1 2dt = k_on mu_0 2 + gamma_p mu_1 1 + b k_p mu_1 0 + 2 b k_p mu_1 1 + 2 k_p b^2 mu_1 0 - k_off mu_1 4 - k_on mu_1 2 - 2 gamma_p mu_1 2 \r\nfracdmu_0 3dt = b k_p mu_1 0 + 3 gamma_p mu_0 2 + 3 b k_p mu_1 1 + 3 b k_p mu_1 2 + 6 k_p b^2 mu_1 0 + 6 k_p b^3 mu_1 0 + 6 k_p b^2 mu_1 1 - gamma_p mu_0 1 - 3 gamma_p mu_0 3\r\nendalign*","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"The system of ODEs is now much simpler and we can see that there are two higher-order moments we need to truncate: mu_13 and μ_14. We consider normal, derivative matching, conditional gaussian and conditional derivative matching closures to see how well they compare. First we apply different closures and print out the corresponding higher-order moment expressions in order to check that our results are consistent with those published in [1].","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"For normal closure:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"normal_eqs = moment_closure(eqs, \"normal\", binary_vars)\r\nlatexify(normal_eqs, :closure)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"beginalign*\r\nmu_13 = mu_03 mu_10 + 3 mu_01 mu_12 + 3 mu_02 mu_11 + 6 mu_10 mu_01^3 - 6 mu_11 mu_01^2 - 6 mu_01 mu_02 mu_10 \r\nmu_14 = mu_04 mu_10 + 4 mu_01 mu_13 + 6 mu_02 mu_12 + 4 mu_03 mu_11 + 24 mu_11 mu_01^3 + 36 mu_02 mu_10 mu_01^2 - 24 mu_10 mu_01^4 - 6 mu_10 mu_02^2 - 12 mu_12 mu_01^2 - 24 mu_01 mu_02 mu_11 - 8 mu_01 mu_03 mu_10\r\nendalign*","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"Note that our expression for μ_14 is different from the equivalent langle gp^4 rangle in Eq. (8) of [1] as it seems that the authors introduced a mistake considering the central moment and cumulant relationship in Eq. (7).","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"Using derivative matching, we obtain:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"dm_eqs = moment_closure(eqs, \"derivative matching\", binary_vars)\r\nlatexify(dm_eqs, :closure)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"beginalign*\r\nmu_1 3 = fracmu_0 1^3 mu_1 2^3 mu_0 3 mu_1 0mu_0 2^3 mu_1 1^3 \r\nmu_1 4 = fracmu_0 2^6 mu_1 1^4 mu_1 3^4 mu_0 4mu_0 1^4 mu_0 3^4 mu_1 2^6 mu_1 0\r\nendalign*","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"For conditional gaussian closure:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"cond_gaussian_eqs = moment_closure(eqs, \"conditional gaussian\", binary_vars)\r\nlatexify(cond_gaussian_eqs, :closure)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"beginalign*\r\nmu_1 3 = frac-2 mu_1 1^3mu_1 0^2 + frac3 mu_1 1 mu_1 2mu_1 0 \r\nmu_1 4 = frac3 mu_1 2^2mu_1 0 + frac6 mu_1 1^4mu_1 0^3 + frac-12 mu_1 1^2 mu_1 2mu_1 0^2 + frac4 mu_1 1 mu_1 3mu_1 0\r\nendalign*","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"And, finally, for conditional derivative matching:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"cond_dm_eqs = moment_closure(eqs, \"conditional derivative matching\", binary_vars)\r\nlatexify(cond_dm_eqs, :closure)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"beginalign*\r\nmu_1 3 = fracmu_0 1^3 mu_1 2^3 mu_0 3 mu_1 0mu_0 2^3 mu_1 1^3 \r\nmu_1 4 = fracmu_0 2^6 mu_1 1^4 mu_1 3^4 mu_0 4mu_0 1^4 mu_0 3^4 mu_1 2^6 mu_1 0\r\nendalign*","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"All these results are consistent with [1], reassuring that the model and closures are implemented as intended. Finally, we can proceed to solve the resulting ODEs and compare the resulting means and standard deviations to the SSA. Following Soltani et al. [1], we define all model parameters as:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"mean_p = 200\r\nmean_b = 70\r\nγ_p_val = 1\r\nk_off_val = 0.001\r\nk_on_val = 0.05\r\n\r\nk_p_val = mean_p * γ_p_val * (k_off_val * mean_p^2 + k_on_val) / (k_on_val * mean_b)\r\n\r\nsymmap = [:k_on => k_on_val,\r\n :k_off => k_off_val,\r\n :k_p => k_p_val,\r\n :γ_p => γ_p_val,\r\n :b => mean_b]\r\npmap = symmap_to_varmap(rn, symmap)\r\n\r\n# initial gene state and protein number, order [g, p]\r\nu₀ = [1, 1]\r\n\r\n# time interval to solve on\r\ntspan = (0., 6.0)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"The reaction network with geometric bursts can be simulated using the SSA as usual:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"# convert the reaction network into a system of jump processes\r\njsys = convert(JumpSystem, rn; combinatoric_ratelaws=false)\r\n\r\n# create a discrete problem setting the simulation parameters\r\ndprob = DiscreteProblem(u₀, tspan, pmap)\r\n\r\n# create a JumpProblem compatible with ReactionSystemMod\r\njprob = JumpProblem(rn, dprob, Direct(), save_positions=(false, false))\r\n\r\n# simulate 2×10⁴ SSA trajectories\r\nensembleprob = EnsembleProblem(jprob)\r\n@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.1, trajectories=20000)\r\n# compute the means and variances\r\nmeans_ssa, vars_ssa = timeseries_steps_meanvar(sol_SSA)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"4.858357 seconds (14.30 M allocations: 901.032 MiB, 6.25% gc time, 63.45% compilation time)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"We continue to solve the moment equations for each closure:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"plt_m = plot() # plot mean protein number\r\nplt_std = plot() # plot ssd of protein number\r\n\r\n# construct the initial molecule number mapping\r\nu₀map = deterministic_IC(u₀, dm_eqs)\r\n\r\n# solve moment ODEs for each closure and plot the results\r\nfor closure in [\"normal\", \"derivative matching\",\r\n \"conditional gaussian\", \"conditional derivative matching\"]\r\n\r\n # it is very quick so we just apply all closures again\r\n closed_eqs = moment_closure(eqs, closure, binary_vars)\r\n\r\n # solve the system of moment ODEs\r\n oprob = ODEProblem(closed_eqs, u₀map, tspan, pmap)\r\n sol = solve(oprob, AutoTsit5(Rosenbrock23()), saveat=0.01)\r\n\r\n # μ₀₁ is 2nd and μ₀₂ is 4th element in sol\r\n # can check the order with `closed_eqs.odes.states`\r\n plt_m = plot!(plt_m, sol, idxs=[2], label=closure)\r\n plt_std = plot!(plt_std, sol.t, sqrt.(sol[4, :] .- sol[2, :].^2), label=closure)\r\n\r\nend\r\n\r\nplt_m = plot!(plt_m, xlabel=\"Time [hr]\", ylabel=\"Protein mean level\")\r\nplt_m = plot!(plt_m, means_ssa.t, means_ssa[2,:], label=\"SSA\", linestyle=:dash, color=\"gray\")\r\nplt_std = plot!(plt_std, xlabel=\"Time [hr]\", ylabel=\"Protein standard deviation\")\r\nplt_std = plot!(plt_std, vars_ssa.t, sqrt.(vars_ssa[2,:]), label=\"SSA\", linestyle=:dash, color=\"gray\")","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"plot(plt_m, lw=2)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"(Image: Gene 1 means)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"plot(plt_std, lw=2)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"(Image: Gene 2 stds)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"We observe that the two conditional closures give the most accurate results. Therefore, closing moments conditioned on the gene being active is an effective approximation in this case. Note that our results for normal closure are different from [1], most likely due to the incorrect fifth-order moment closure function given in the paper.","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"We now turn to a more complex network involving two genes (two Bernoulli variables), a repressor-activator circuit: an activator protein Y expressed by one gene can turn ON another gene which produces a repressor protein X, that subsequently can bind to the gene promoter region of the activator-producing gene turning it OFF (see [1] for more details). As before, X and Y proteins are expressed in geometrically-distributed bursts. The system can be specified as follows:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"@parameters b_x b_y\r\n# could redefine in terms of success probabilities p_x and p_y as above\r\nm = rand(Distributions.Geometric(1/(1+b_x)))\r\nl = rand(Distributions.Geometric(1/(1+b_y)))\r\n\r\n# g_x - gene state of X protein producing gene\r\n# g_y - gene state of Y protein producing gene\r\n# x, y - proteins X and Y\r\nrn = @reaction_network begin\r\n @parameters kx_on kx_off ky_on ky_off k_x γ_x k_y γ_y\r\n kx_on*(1-g_x)*y, 0 --> g_x # 0 -> g_x\r\n kx_off, g_x --> 0 # g_x -> 0\r\n ky_on*(1-g_y), 0 --> g_y # 0 -> g_y\r\n ky_off*x, g_y --> 0 # g_y -> 0\r\n k_x*g_x, 0 --> $m*x # 0 -> mx, m ~ Geometric(mean=b_x)\r\n γ_x, x --> 0 # x -> 0\r\n k_y*g_y, 0 --> $l*y # 0 -> ly, l ~ Geometric(mean_b_y)\r\n γ_y, y --> 0 # y -> 0\r\nend\r\n\r\n# both g_x and g_y are Bernoulli random variables\r\nbinary_vars = [1, 2]\r\n\r\n# Parameter initialisation\r\n\r\nmean_x = 100\r\nmean_y = 100\r\nmean_b_x = 5\r\nmean_b_y = 5\r\nγ_x_val = 1\r\nγ_y_val = 1\r\nkx_off_val = 4\r\nky_on_val = 0.3\r\nkx_on_val = 0.05\r\nky_off_val = 0.05\r\n\r\nk_x_val = mean_x * γ_x_val * (kx_off_val * mean_y^2 + kx_on_val) / (kx_on_val * mean_b_x)\r\nk_y_val = mean_y * γ_y_val * (ky_off_val * mean_x^2 + ky_on_val) / (ky_on_val * mean_b_y)\r\n\r\n# unclear if Soltani et al. (2015) actually used this parameter set as X numbers\r\n# jump to millions making SSA extremely slow...\r\n\r\n# introduce additional rescaling (otherwise rate coefficients are too high)\r\nk_x_val *= 0.00003\r\nk_y_val *= 0.01\r\n\r\n# parameter mapping\r\nsymmap = [:kx_on => kx_on_val,\r\n :kx_off => kx_off_val,\r\n :ky_on => ky_on_val,\r\n :ky_off => ky_off_val,\r\n :k_x => k_x_val,\r\n :k_y => k_y_val,\r\n :γ_x => γ_x_val,\r\n :γ_y => γ_y_val,\r\n :b_x => mean_b_x,\r\n :b_y => mean_b_y]\r\npmap = symmap_to_varmap(rn, symmap)\r\n\r\n# initial gene state and protein number, order [g_x, g_y, x, y]\r\nu₀ = [1, 1, 1, 1]\r\n\r\n# time interval to solve on\r\ntspan = (0., 12.0)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"Note that here we use a different parameter set from the one considered in [1] as otherwise the number of X proteins goes into millions, making the comparison between closure results difficult due to SSA being extremely slow—it appears that either we have included a mistake setting the parameter values or there is a typo in the paper.","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"We can run SSA as follows:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"jsys = convert(JumpSystem, rn, combinatoric_ratelaws=false)\r\ndprob = DiscreteProblem(jsys, u₀, tspan, pmap)\r\njprob = JumpProblem(jsys, dprob, Direct(), save_positions=(false, false))\r\n\r\nensembleprob = EnsembleProblem(jprob)\r\n@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.1, trajectories=10000)\r\nmeans_ssa, vars_ssa = timeseries_steps_meanvar(sol_SSA)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"13.712331 seconds (43.27 M allocations: 1.697 GiB, 6.56% gc time, 10.01% compilation time)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"We use fourth order moment expansion and apply different closure methods as done for the negative feedback loop, considering the number of activator proteins Y and its standard deviation:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"plt_m = plot() # plot mean activator protein number\r\nplt_std = plot() # plot ssd of activator protein number\r\n\r\nfor closure in [\"derivative matching\", \"conditional derivative matching\"]\r\n\r\n closed_eqs = moment_closure(eqs, closure, binary_vars)\r\n\r\n u₀map = deterministic_IC(u₀, closed_eqs)\r\n oprob = ODEProblem(closed_eqs, u₀map, tspan, pmap)\r\n sol = solve(oprob, Tsit5(), saveat=0.1)\r\n\r\n # μ₀₀₀₁ is the 4th and μ₀₀₀₂ is the 12th element in sol (can check with closed_eqs.odes.states)\r\n plt_m = plot!(plt_m, sol, idxs=[4], label=closure)\r\n plt_std = plot!(plt_std, sol.t, sqrt.(sol[12, :] .- sol[4, :].^2), label=closure)\r\nend\r\n\r\nplt_m = plot!(plt_m, xlabel=\"Time [hr]\", ylabel=\"Activator mean level\")\r\nplt_m = plot!(plt_m, means_ssa.t, means_ssa[4,:], label=\"SSA\", linestyle=:dash, color=\"gray\")\r\nplt_std = plot!(plt_std, xlabel=\"Time [hr]\", ylabel=\"Activator standard deviation\")\r\nplt_std = plot!(plt_std, vars_ssa.t, sqrt.(vars_ssa[4,:]), label=\"SSA\", linestyle=:dash, color=\"gray\")","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"Note that here we apply only derivative matching and conditional derivative matching, as both normal and conditional gaussian closures failed to be evaluated for the entire time course (irrespective of the solver used). Finally, we can plot the results:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"plot(plt_m, lw=2)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"(Image: Gene 2 means)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"plot(plt_std, lw=2, xlims=(0., 12.))","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"(Image: Gene 2 stds)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"The trajectories obtained with conditional derivative matching quite accurately match the true dynamics, showing that it is indeed a powerful closure method for reaction networks involving species with very low (binary) copy numbers.","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/#References","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"References","text":"","category":"section"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"[1]: M. Soltani, C. A. Vargas-Garcia, and A. Singh, \"Conditional Moment Closure Schemes for Studying Stochastic Dynamics of Genetic Circuits\", IEEE Transactions on Biomedical Circuits and Systems 9, 518–526 (2015). https://doi.org/10.1109/tbcas.2015.2453158","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"[2]: D. Schnoerr, G. Sanguinetti, and R. Grima, \"Approximation and inference methods for stochastic biochemical kinetics - a tutorial review\", Journal of Physics A: Mathematical and Theoretical 50, 093001 (2017). https://doi.org/10.1088/1751-8121/aa54d9","category":"page"},{"location":"tutorials/common_issues/#common_issues","page":"Common Issues","title":"Common Issues","text":"","category":"section"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"Moment closure approximations are based on ad hoc assumptions and no rigorous and general predictions can be made on whether the results will be accurate or even physically meaningful [1-2]. Moreover, the truncated moment equations are prone to numerical instabilities and it may not be possible to solve them for the entire time course [3]. In this tutorial, we walk through a number of such issues encountered in the analysis of the Brusselator model introduced in the previous tutorial.","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"We first redefine the system and its parameters for completeness:","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"using MomentClosure, Catalyst, OrdinaryDiffEq, Plots\r\n\r\nrn = @reaction_network begin\r\n @parameters c₁ c₂ c₃ c₄ Ω\r\n (c₁/Ω^2), 2X + Y → 3X\r\n (c₂), X → Y\r\n (c₃*Ω, c₄), 0 ↔ X\r\nend\r\n\r\np = [0.9, 2, 1, 1, 100]\r\nu₀ = [1, 1]\r\ntspan = (0., 100.)\r\n\r\nraw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=false)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"As we have seen earlier, second-order moment expansion using normal closure approximates the true system dynamics sufficiently accurately but it's interesting to see how other closures compare. Let's try applying zero closure:","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"closed_raw_eqs = moment_closure(raw_eqs, \"zero\")\r\n\r\nu₀map = deterministic_IC(u₀, closed_raw_eqs)\r\noprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)\r\nsol = solve(oprob, Tsit5(), saveat=0.1)\r\n\r\nplot(sol, idxs=[1,2], lw=2)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"(Image: Brusselator issue 1)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"The trajectory of μ₀₁ becomes negative and so zero closure fails to provide physically meaningful results for this parameter set. Note that is important to correctly choose the ODE solver depending on the stiffness of the system and the accuracy required. We tried a number of recommended DifferentialEquations solvers here but none seemed to improve the results.","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"Let's apply log-normal closure next:","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"closed_raw_eqs = moment_closure(raw_eqs, \"log-normal\")\r\n\r\nu₀map = deterministic_IC(u₀, closed_raw_eqs)\r\noprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)\r\nsol = solve(oprob, Tsit5(), saveat=0.1)\r\n\r\nplot(sol, idxs=[1,2], lw=2, legend=:bottomright)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"(Image: Brusselator issue 2)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"We observe sustained oscillatory behaviour instead of the expected damped oscillations. This result is unphysical: single SSA trajectories (that may display sustained oscillations) get dephased over time and hence the ensemble average should always show damped or overdamped oscillations [1].","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"Normal closure is also quite fragile. This can be seen by simply including the combinatorial scaling of the mass-action propensity functions with combinatoric_ratelaw=true which leads to unphysical sustained oscillatory trajectories:","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"raw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=true)\r\nclosed_raw_eqs = moment_closure(raw_eqs, \"normal\")\r\n\r\nu₀map = deterministic_IC(u₀, closed_raw_eqs)\r\noprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)\r\nsol = solve(oprob, Tsit5(), saveat=0.1)\r\n\r\nplot(sol, idxs=[1,2], lw=2)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"(Image: Brusselator issue 3)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"Nevertheless, this can be improved upon by increasing the order of moment expansion:","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"raw_eqs = generate_raw_moment_eqs(rn, 3, combinatoric_ratelaws=true)\r\nclosed_raw_eqs = moment_closure(raw_eqs, \"normal\")\r\n\r\nu₀map = deterministic_IC(u₀, closed_raw_eqs)\r\noprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)\r\nsol = solve(oprob, Tsit5(), saveat=0.1)\r\n\r\nplot(sol, idxs=[1,2], lw=2, legend=:bottomright)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"(Image: Brusselator issue 4)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"Some dampening in the system is now visible. Increasing the expansion order to 4 finally leads to physically sensible results:","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"raw_eqs = generate_raw_moment_eqs(rn, 4, combinatoric_ratelaws=true)\r\nclosed_raw_eqs = moment_closure(raw_eqs, \"normal\")\r\n\r\nu₀map = deterministic_IC(u₀, closed_raw_eqs)\r\noprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)\r\nsol = solve(oprob, Tsit5(), saveat=0.1)\r\n\r\nplot(sol, idxs=[1,2], lw=2)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"(Image: Brusselator issue 5)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"For dessert, we consider unphysical divergent trajectories—a frequent problem with moment equations [3]. A good example is the second-order moment expansion including the combinatorial scaling of propensities with log-normal closure applied:","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"raw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=true)\r\nclosed_raw_eqs = moment_closure(raw_eqs, \"log-normal\")\r\n\r\nu₀map = deterministic_IC(u₀, closed_raw_eqs)\r\noprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)\r\nsol = solve(oprob, Rodas4P(), saveat=0.1)\r\n\r\nplot(sol, idxs=[1,2], lw=2)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"(Image: Brusselator issue 6)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"In contrast to normal closure, increasing the expansion order makes the problem worse:","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"raw_eqs = generate_raw_moment_eqs(rn, 3, combinatoric_ratelaws=true)\r\nclosed_raw_eqs = moment_closure(raw_eqs, \"log-normal\")\r\n\r\nu₀map = deterministic_IC(u₀, closed_raw_eqs)\r\noprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)\r\nsol = solve(oprob, Rodas4P(), saveat=0.1)\r\n\r\nplot(sol, idxs=[1,2], lw=2)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"┌ Warning: Interrupted. Larger maxiters is needed.\r\n└ @ SciMLBase C:\\Users\\asukys\\.julia\\packages\\SciMLBase\\Afx1r\\src\\integrator_interface.jl:331","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"(Image: Brusselator issue 7)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"Note that the solver throws a warning being unable to evaluate the trajectories for the entire time course (other solvers perform similarly in this case). This usually implies that the moment ODE system is too stiff and cannot be solved: the time derivatives grow unboundedly and the solver timestep is being constantly reduced, requiring an ever-increasing number of the solver iterations (hence the maxiters warning).","category":"page"},{"location":"tutorials/common_issues/#References","page":"Common Issues","title":"References","text":"","category":"section"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"[1]: D. Schnoerr, G. Sanguinetti, and R. Grima, \"Comparison of different moment-closure approximations for stochastic chemical kinetics\", The Journal of Chemical Physics 143, 185101 (2015). https://doi.org/10.1063/1.4934990","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"[2]: D. Schnoerr, G. Sanguinetti, and R. Grima, \"Validity conditions for moment closure approximations in stochastic chemical kinetics\", The Journal of Chemical Physics 141, 084103 (2014). https://doi.org/10.1063/1.4892838","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"[3]: E. Lakatos, A. Ale, P. D. W. Kirk, and M. P. H. Stumpf, \"Multivariate moment closure techniques for stochastic kinetic models\", The Journal of Chemical Physics 143, 094107 (2015). https://doi.org/10.1063/1.4929837","category":"page"},{"location":"tutorials/parameter_estimation_SDE/#parameter_estimation_SDE","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"","category":"section"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"In this tutorial, we look at the problem of model parameter identification of a diffusion process given timeseries data of its moments. Namely, we use moment closure approximations (MAs) to make the optimisation process more efficient by reducing the model evaluation time. All credit for this tutorial goes to Flemming Holtorf!","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"We consider a noisy variation of the Lotka-Volterra model, describing the interaction between a predator and prey species:","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"beginalign*\n beginbmatrix dx dy endbmatrix = \n beginbmatrix gamma_1 x(t) - gamma_2 x(t) y(t) gamma_4 x(t) y(t) - gamma_3 y(t) - frac12 y(t) endbmatrix dt \n + beginbmatrix gamma_5 x(t) 0 endbmatrix dW_t\nendalign*","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"We can define this system of SDEs using ModelingToolkit as follows:","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"using ModelingToolkit\n\n@variables t, x(t), y(t)\n@parameters γ1, γ2, γ3, γ4, γ5\nγ = [γ1, γ2, γ3, γ4, γ5] \ndrift_eqs = [Differential(t)(x) ~ γ[1] * x - γ[2] * x * y ;\n Differential(t)(y) ~ γ[4] * x * y - γ[3] * y - y*0.5]\ndiff_eqs = [γ[5]*x; 0]\nLV = SDESystem(drift_eqs, diff_eqs, t, [x,y], γ, name = :LV)","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"Next, we generate some data used for the parameter estimation. Namely, we collect timeseries data of means and variances of both species:","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"using DifferentialEquations, DifferentialEquations.EnsembleAnalysis\n\nN_samples = 1000\nTf = 10\nt_data = 0:0.2:Tf\np_true = [γ[1] => 1, γ[2] => 2, γ[3] => 1, γ[4] => 2, γ[5] => 0.1]\nu0 = [1.0, 0.25]\nLV_data = solve(EnsembleProblem(SDEProblem(LV, u0, (0.0, Tf), p_true)), saveat = t_data, trajectories = N_samples)\nmeans, vars = timeseries_steps_meanvar(LV_data)","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"Now we are ready to test if we can estimate the model parameters gamma_1 dotsc gamma_5 solely from the data collected above. We first approach this parameter identification problem using the asymptotically exact approach of estimating the means and variances of the process with ensemble averages. Accordingly, we construct the following loss function:","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"using LinearAlgebra\n\nLV_sde = SDEProblem(LV, u0, (0.0, Tf), zeros(5))\nfunction obj(p)\n prob = remake(LV_sde, p = p)\n sol = solve(EnsembleProblem(prob), saveat = t_data, trajectories = 1000)\n sol_mean, sol_vars = timeseries_steps_meanvar(sol)\n obj = sum(norm(sol_mean[i] - means[i])^2 for i in 1:length(t_data))\n obj += 1e4*sum(norm(sol_vars[i] - vars[i])^2 for i in 1:length(t_data))\n return obj\nend","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"We can use this loss function with any suitable optimisation routine to identify a reasonable choice of the model parameters. For example, we can use a very simple derivative-free optimizer (Nelder-Mead method) implemented in the Optim.jl package. Since a single evaluation of the objective function requires sampling and hence is relatively expensive, we impose the constraint that the optimiser cannot run more than 2 minutes:","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"using Optim\n\npmap = Dict(i => findfirst(isequal(γ[i]), parameters(LV)) for i in 1:5)\np_init = Dict(γ[1] => 1.3, γ[2] => 1.5, γ[3] => 1.4, γ[4] => 2.2, γ[5] => 0.1)\np = [p_init[γ[pmap[i]]] for i in 1:5]\nopt_sampling = Optim.optimize(obj, p, Optim.Options(time_limit = 120))","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"* Status: failure (exceeded time limit of 120.0)\n\n * Candidate solution\n Final objective value: 3.550929e+00\n\n * Found with\n Algorithm: Nelder-Mead\n\n * Convergence measures\n √(Σ(yᵢ-ȳ)²)/n ≰ 1.0e-08\n\n * Work counters\n Seconds run: 121 (vs limit 120)\n Iterations: 139\n f(x) calls: 337","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"We can visualise the moment statistics obtained using the estimated parameters and compare to the true data:","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"using Plots\n\nt_detail = collect(0:0.01:Tf) \nopt_sol = solve(EnsembleProblem(SDEProblem(LV, u0, (0.0, Tf), opt_sampling.minimizer)), saveat = t_detail, trajectories = 1000)\nopt_means, opt_vars = timeseries_steps_meanvar(opt_sol)\n\nmean_comp = scatter(t_data, [m[1] for m in means], color = :blue,\n xlabel = \"time\", ylabel = \"population size\", \n grid = false, title = \"means\", label = \"⟨x⟩ data\")\nscatter!(mean_comp, t_data, [m[2] for m in means], color = :red, label = \"⟨y⟩ data\")\nplot!(mean_comp, t_detail, [m[1] for m in opt_means], linewidth = 2, color = :blue, label = \"⟨x⟩ SDE model\")\nplot!(mean_comp, t_detail, [m[2] for m in opt_means], linewidth = 2, color = :red, label = \"⟨y⟩ SDE model\")\n\nvar_comp = scatter(t_data, [v[1] for v in vars], color = :blue, grid = false,\n xlabel = \"time\", title = \"variances\", label = \"σ²(x) data\", legend = :topleft)\nscatter!(var_comp, t_data, [v[2] for v in vars], color = :red, label = \"σ²(y) data\")\nplot!(var_comp, t_detail, [v[1] for v in opt_vars], color = :blue, label = \"σ²(x) SDE model\")\nplot!(var_comp, t_detail, [v[2] for v in opt_vars], color = :red, label = \"σ²(y) SDE model\")\n\nplot(mean_comp, var_comp, size = (1200.0, 400.0))","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"(Image: LV SDE fig1)","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"We observe that the identified parameters match the data reasonably well. However, one may suspect that the optimiser is converging to a local minimum as the fit is not perfect.","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"Now we approach the same model identification problem via MAs in the hope of cutting down model evaluation cost, allowing us to identify better parameters in the same (or less) time. To that end, we construct an approximation of the moment dynamics of the process assuming that the distribution of the system state is approximately log-normal over the simulation horizon (using log-normal MA). Then we can implement a simple loss function by comparing the moments predicted by the approximate model with those obtained from data:","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"using MomentClosure\n\nLV_moments = moment_closure(generate_raw_moment_eqs(LV, 2), \"log-normal\")\nu0map = deterministic_IC(u0, LV_moments)\nclosed_moment_prob = ODEProblem(LV_moments, u0map, (0.0, Tf), zeros(5))\nfunction obj_MCA(p)\n prob = remake(closed_moment_prob; p=p)\n sol = solve(prob, Tsit5(), saveat = t_data)\n if sol.retcode == ReturnCode.Success\n obj = sum(norm(sol.u[i][1:2] - means[i])^2 for i in 1:length(t_data))\n obj += 1e4*sum((sol.u[i][3] - sol.u[i][1]^2 - vars[i][1])^2 for i in 1:length(t_data))\n obj += 1e4*sum((sol.u[i][5] - sol.u[i][2]^2 - vars[i][2])^2 for i in 1:length(t_data))\n else\n obj = 1e6\n end\n return obj\nend","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"As before, any suitable optimisation routine can now be used to identify parameter values that result in a match between data and model prediction:","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"pmap = Dict(i => parameters(LV_moments.odes)[i] for i in 1:5)\np_init = Dict(γ[1] => 1.3, γ[2] => 1.5, γ[3] => 1.4, γ[4] => 2.2, γ[5] => 0.1)\np = [p_init[pmap[i]] for i in 1:5]\nopt_MCA = Optim.optimize(obj_MCA, p, Optim.Options(time_limit = min(120, opt_sampling.time_run)))","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"* Status: success\n\n * Candidate solution\n Final objective value: 1.160452e+00\n\n * Found with\n Algorithm: Nelder-Mead\n\n * Convergence measures\n √(Σ(yᵢ-ȳ)²)/n ≤ 1.0e-08\n\n * Work counters\n Seconds run: 0 (vs limit 120)\n Iterations: 362\n f(x) calls: 751","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"By visualising the results we see that indeed the identified parameters now provide a better match between data and the model, even if the original SDE model is being evaluated (note that the moment equations using log-normal MA provide a reasonably accurate approximation to the ensemble averages):","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"p_opt = [pmap[i] => opt_MCA.minimizer[i] for i in 1:5]\nt_detail = collect(0:0.01:Tf) \nopt_sol = solve(EnsembleProblem(SDEProblem(LV, u0, (0.0, Tf), p_opt)), saveat = t_detail, trajectories = 1000)\nopt_means = [timestep_mean(opt_sol, i) for i in 1:length(t_detail)]\nopt_vars = [timestep_meanvar(opt_sol, i)[2] for i in 1:length(t_detail)]\n\nopt_sol_approx = solve(ODEProblem(LV_moments, u0map, (0.0, Tf), p_opt), saveat = t_detail)\n\nmean_comp = scatter(t_data, [m[1] for m in means], color = :blue,\n xlabel = \"time\", ylabel = \"population size\", \n grid = false, title = \"means\", label = \"⟨x⟩ data\")\nscatter!(mean_comp, t_data, [m[2] for m in means], color = :red, label = \"⟨y⟩ data\")\nplot!(mean_comp, t_detail, [m[1] for m in opt_means], linewidth = 2, color = :blue, label = \"⟨x⟩ SDE model\")\nplot!(mean_comp, t_detail, [m[2] for m in opt_means], linewidth = 2, color = :red, label = \"⟨y⟩ SDE model\")\nplot!(mean_comp, t_detail, [m[1] for m in opt_sol_approx.u], linewidth = 2, color = :black, linestyle = :dash, label = \"log-normal MA\")\nplot!(mean_comp, t_detail, [m[2] for m in opt_sol_approx.u], linewidth = 2, color = :black, linestyle = :dash, label = nothing)\n\nvar_comp = scatter(t_data, [v[1] for v in vars], color = :blue,\n xlabel = \"time\", title = \"variances\", grid = false, label = \"σ²(x) data\", legend = :topleft)\nscatter!(var_comp, t_data, [v[2] for v in vars], color = :red, label = \"σ²(y) data\")\nplot!(var_comp, t_detail, [v[1] for v in opt_vars], color = :blue, label = \"σ²(x) SDE model\")\nplot!(var_comp, t_detail, [v[2] for v in opt_vars], color = :red, label = \"σ²(y) SDE model\")\nplot!(var_comp, t_detail, [m[3] - m[1]^2 for m in opt_sol_approx.u], linewidth = 2, color = :black, linestyle = :dash, label = \"log-normal MA\")\nplot!(var_comp, t_detail, [m[5] - m[2]^2 for m in opt_sol_approx.u], linewidth = 2, color = :black, linestyle = :dash, label = nothing)\n\nplot(mean_comp, var_comp, size = (1200.0, 400.0))","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"(Image: LV SDE fig2)","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"Finally, note that the parameter estimation is much faster using moment equations (compare to 120 s using the basic approach)","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"opt_MCA.time_run","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"0.10686397552490234","category":"page"},{"location":"tutorials/using_momentclosure_SDE/#tutorial_SDE","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"","category":"section"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"In the previous tutorial, we have shown how to generate and close moment equations for chemical reaction networks. Similarly, MomentClosure can be applied to systems of stochastic differential equations (SDEs) and here we demonstrate this functionality by working through a couple of practical examples. Namely, we consider two specific models from a relevant paper by Ghusinga et al. (2017) [1], 1) the Van der Pol oscillator and 2) a swinging pendulum, and apply moment closure approximations (MA) to reproduce some of the published results. For the theory behind the SDE moment expansion see here.","category":"page"},{"location":"tutorials/using_momentclosure_SDE/#Model-1","page":"Moment Equations from SDEs","title":"Model 1","text":"","category":"section"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"The deterministic Van der Pol oscillator is described by [1]:","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"beginalign*\r\n fracd^2 xdt^2 - epsilon(1-x^2)fracdxdt + omega_n^2 x = Acos(omega_g t)\r\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"where epsilon is the bifurcation parameter, omega_n the natural frequency, omega_g the force frequency and A the force amplitude. We formulate a stochastic equivalent of this system by assuming that the force is noisy and taking x_1 = x and x_2 = fracdxdt, so that","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"beginalign*\r\n dx_1 = x_2 dt \r\n dx_2 = left( epsilon(1-x_1^2) x_2 - omega_n^2 x_1 right)dt + Acos(omega_g t)dt + A dw_t\r\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"In Julia, systems of SDEs can be conveniently described using ModelingToolkit.jl that provides an SDESystem type. Defining such models is straightforward (as in this example) and in our case is done as follows:","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"using ModelingToolkit\r\n\r\n@variables t, x₁(t), x₂(t)\r\n@parameters ϵ, ω_n, ω_g, A\r\n\r\ndrift_eqs = [Differential(t)(x₁) ~ x₂;\r\n Differential(t)(x₂) ~ ϵ*(1-x₁^2)*x₂ - ω_n^2*x₁ + A*cos(ω_g*t)]\r\ndiff_eqs = [0; A]\r\n\r\nvdp_model = SDESystem(drift_eqs, diff_eqs, t, [x₁, x₂], [ϵ, ω_n, ω_g, A], name = :VdP)\r\n\r\nps = [ϵ => 0.1, ω_n => 120*pi, ω_g => 120*pi, A => 2.5] # parameter values\r\nu0 = [0.1, 0.1] # initial conditions\r\ntspan = (0., 0.1) # simulation time limit","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"We can now easily extract the raw moment equations up to second order using MomentClosure","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"using MomentClosure, Latexify\r\n\r\nmoment_eqs = generate_raw_moment_eqs(vdp_model, 2) \r\nlatexify(moment_eqs)","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"beginalign*\r\nfracdmu_10dt = mu_01 \r\nfracdmu_01dt = A cosleft( t omega_g right) + epsilon mu_01 - epsilon mu_21 - omega_n^2 mu_10 \r\nfracdmu_20dt = 2 mu_11 \r\nfracdmu_11dt = epsilon mu_11 + A mu_10 cosleft( t omega_g right) + mu_02 - epsilon mu_31 - omega_n^2 mu_20 \r\nfracdmu_02dt = A^2 + 2 epsilon mu_02 + 2 A mu_01 cosleft( t omega_g right) - 2 omega_n^2 mu_11 - 2 epsilon mu_22\r\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"The obtained moment equations are equivalent to the published ones (except for a single term in mu_11 equation as there is a typo in the paper), giving some confidence that everything works as intended!","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"Note that the moment equations are not closed as there are two fourth order moments involved, mu_31 and mu_22, and hence we need to resort to MAs. We proceed to apply the derivative matching approximation and solve the system of ODEs as follows:","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"using DifferentialEquations\r\n\r\nclosed_eqs = moment_closure(moment_eqs, \"derivative matching\")\r\n\r\nu0map = deterministic_IC(u0, closed_eqs)\r\noprob = ODEProblem(closed_eqs, u0map, tspan, ps)\r\n\r\nsol_MA = solve(oprob, Tsit5(), saveat=0.0001)","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"Finally, we can also use DifferentialEquations to solve the SDEs for many trajectories and compare the ensemble statistics to the derivative matching approximation (getting a great match):","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"using DifferentialEquations.EnsembleAnalysis, Plots\r\n\r\nprob_SDE = SDEProblem(vdp_model, u0, tspan, ps)\r\n@time sol_SDE = solve(EnsembleProblem(prob_SDE), SRIW1(), saveat=0.0001, trajectories=100)\r\nmeans_SDE = timeseries_steps_mean(sol_SDE)\r\n\r\nplot(sol_MA.t, sol_MA[1, :], lw=2, label=\"MA\", ylabel=\"⟨x₁⟩\", xlabel=\"time\")\r\nplot!(sol_MA.t, means_SDE[1, :], lw=2, label=\"SDE\", linecolor=:red,\r\n linestyle=:dash, background_color_legend=nothing, legend=:topright, grid=false)","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"(Image: Model 1 SDE)","category":"page"},{"location":"tutorials/using_momentclosure_SDE/#Model-2","page":"Moment Equations from SDEs","title":"Model 2","text":"","category":"section"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"We next consider a simple pendulum, deterministically described as [1]","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"beginalign*\r\n fracd^2thetadt^2 + frackmfracdthetadt + fracgl sintheta = 0\r\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"where theta is the angular displacement, m the mass of the pendulum, g the gravitational acceleration constant, l the pendulum length and k the friction constant. The stochasticity is modelled as a white noise term arising due to pendulum randomly interacting with air molecules (assumed to be inversely proportional to m). Letting x_1 = theta and x_2 = fracdthetadt we write down the SDE as:","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"beginalign*\r\n dx_1 = x_2 dt \r\n dx_2 = left( -frackmx_2 - fracglsinx_1 right)dt + frac1mdw_t\r\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"Using ModelingToolkit again we can define the model as","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"@variables t, x₁(t), x₂(t)\r\n@parameters k, l, m, g\r\n\r\ndrift_eqs = [Differential(t)(x₁) ~ x₂;\r\n Differential(t)(x₂) ~ -k/m*x₂ - g/l*sin(x₁)]\r\ndiff_eqs = [0; 1/m]\r\n\r\npendulum_model = SDESystem(drift_eqs, diff_eqs, t, [x₁, x₂], [k, l, m, g], name = :pendulum)\r\nps = [k => 10, m => 10, l => 10, g => 10]\r\nu0 = [3, 3]\r\ntspan = (0., 15.)","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"As the drift term is non-polynomial, we can no longer write down the raw moment equations in a straightforward manner. Nevertheless, we can expand the expressions up to a certain Taylor expansion order q and generate the corresponding time-evolution equations for the means and higher order central moments—this situation is identical to moment expansion for chemical reaction networks with non-polynomial propensities. Hence we can obtain the equations for the means and variances with q=3:","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"moment_eqs = generate_central_moment_eqs(pendulum_model, 2, 3) \r\nlatexify(moment_eqs) # the output here is maybe not the most visually pleasing","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"beginalign*\r\nfracdmu_10dt = mu_01 \r\nfracdmu_01dt = fracleft( - k right) mu_01m + fracleft( - g right) sinleft( mu_10 right)l + fracfrac16 g M_30 cosleft( mu_10 right)l + fracfrac12 g M_20 sinleft( mu_10 right)l \r\nfracdM_20dt = 2 M_11 \r\nfracdM_11dt = fracleft( - k right) M_11m + fracleft( - g right) M_20 cosleft( mu_10 right)l + fracfrac12 g M_30 sinleft( mu_10 right)l + M_02 \r\nfracdM_02dt = fracfrac11m^2 + frac-2 k M_02m + fracg M_21 sinleft( mu_10 right)l + frac-2 g M_11 cosleft( mu_10 right)l\r\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"We can now approximate the moment equations using gamma closure, solve the ODEs numerically and compare the predictions to true SDE solution, finding good agreement:","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"closed_eqs = moment_closure(moment_eqs, \"gamma\")\r\n\r\nu0map = deterministic_IC(u0, closed_eqs)\r\noprob = ODEProblem(closed_eqs, u0map, tspan, ps)\r\nsol_MA = solve(oprob, Tsit5(), saveat=0.01)\r\n\r\nprob_SDE = SDEProblem(pendulum_model, u0, tspan, ps)\r\nsol_SDE = solve(EnsembleProblem(prob_SDE), SRIW1(), saveat=0.01, trajectories=100)\r\nmeans_SDE = timeseries_steps_mean(sol_SDE)\r\n\r\nplot(sol_MA.t, sin.(sol_MA[1, :]), lw=2, label=\"MA\", ylabel=\"sin(⟨x₁⟩)\", xlabel=\"time\")\r\nplot!(sol_MA.t, sin.(means_SDE[1, :]), lw=2, label=\"SDE\", linecolor=:red,\r\n linestyle=:dash, background_color_legend=nothing, legend=:topright, grid=false)","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"(Image: Model 2 SDE)","category":"page"},{"location":"tutorials/using_momentclosure_SDE/#References","page":"Moment Equations from SDEs","title":"References","text":"","category":"section"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"[1]: K. R. Ghusinga, M. Soltani, A. Lamperski, S. V. Dhople, and A. Singh, \"Approximate moment dynamics for polynomial and trigonometric stochastic systems\", IEEE 56th Annual Conference on Decision and Control (2017). https://doi.org/10.1109/CDC.2017.8263922","category":"page"},{"location":"tutorials/using_momentclosure/#main_tutorial","page":"Using MomentClosure","title":"Using MomentClosure","text":"","category":"section"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"This tutorial is an introduction to using MomentClosure to define chemical reaction network models, generate the corresponding moment equations, apply moment closure approximations and finally solve the resulting system of ODEs. To demonstrate this functionality, we will consider a specific case of an oscillatory chemical system known as the Brusselator, characterised by the reactions","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"beginalign*\r\n2X + Y stackrelc_1rightarrow 3X \r\nX stackrelc_2rightarrow Y \r\n undersetc_4stackrelc_3rightleftharpoons X\r\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"We have chosen this particular model to start with as it has been studied with different moment closures before by Schnoerr et al. (2015) and so it is useful as a reference point. The plots of moment trajectories we obtain in this tutorial fully reproduce some of the figures published in the paper, hence (partially) proving the validity of our implementation.","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The terminology and the notation used throughout is consistent with the Theory section of the docs and we advise giving it a skim-through.","category":"page"},{"location":"tutorials/using_momentclosure/#Model-Initialisation","page":"Using MomentClosure","title":"Model Initialisation","text":"","category":"section"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Catalyst.jl provides a comprehensive interface to modelling chemical reaction networks in Julia and can be used to construct models fully-compatible with MomentClosure. For more details on how to do so we recommend reading Catalyst's tutorial. This way, the Brusselator can be defined as:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"using Catalyst\r\nrn = @reaction_network begin\r\n # including system-size parameter Ω\r\n @parameters c₁ c₂ c₃ c₄ Ω\r\n (c₁/Ω^2), 2X + Y → 3X\r\n (c₂), X → Y\r\n (c₃*Ω, c₄), 0 ↔ X\r\nend","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The returned rn is an instance of ModelingToolkit.ReactionSystem. The net stoichiometry matrix and an array of the corresponding propensities, if needed, can be extracted directly from the model using Catalyst.netstoichmat and MomentClosure function propensities respectively.","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Note that MomentClosure also supports systems containing geometrically distributed reaction products that can be defined using Catalyst—see this tutorial for more details.","category":"page"},{"location":"tutorials/using_momentclosure/#Generating-Moment-Equations","page":"Using MomentClosure","title":"Generating Moment Equations","text":"","category":"section"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"We can now obtain the moment equations. The system follows the law of mass action, i.e., all propensity functions are polynomials in molecule numbers X(t) and Y(t), and so we can generate either raw or central moment equations, as described in the Theory section on moment expansion.","category":"page"},{"location":"tutorials/using_momentclosure/#Raw-Moment-Equations","page":"Using MomentClosure","title":"Raw Moment Equations","text":"","category":"section"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Let's start with the raw moment equations which we choose to generate up to second order (m=2):","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"using MomentClosure\r\nraw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=false)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Note that we have set combinatoric_ratelaw=false in order to ignore the factorial scaling factors which Catalyst adds to mass-action reactions. The function generate_raw_moment_eqs returns an instance of RawMomentEquations that contains a ModelingToolkit.ODESystem composed of all the moment equations (accessed by raw_eqs.odes).","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"We can use Latexify to look at the generated moment equations:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"using Latexify\r\nlatexify(raw_eqs)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"beginalign*\r\nfracdmu_1 0dt = c_3 Omega + c_1 Omega^-2 mu_2 1 - c_2 mu_1 0 - c_4 mu_1 0 - c_1 Omega^-2 mu_1 1 \r\nfracdmu_0 1dt = c_2 mu_1 0 + c_1 Omega^-2 mu_1 1 - c_1 Omega^-2 mu_2 1 \r\nfracdmu_2 0dt = c_2 mu_1 0 + c_3 Omega + c_4 mu_1 0 + 2 c_3 Omega mu_1 0 + 2 c_1 Omega^-2 mu_3 1 - 2 c_2 mu_2 0 - 2 c_4 mu_2 0 - c_1 Omega^-2 mu_1 1 - c_1 Omega^-2 mu_2 1 \r\nfracdmu_1 1dt = c_2 mu_2 0 + c_3 Omega mu_0 1 + c_1 Omega^-2 mu_1 1 + c_1 Omega^-2 mu_2 2 - c_2 mu_1 0 - c_2 mu_1 1 - c_4 mu_1 1 - c_1 Omega^-2 mu_1 2 - c_1 Omega^-2 mu_3 1 \r\nfracdmu_0 2dt = c_2 mu_1 0 + 2 c_2 mu_1 1 + c_1 Omega^-2 mu_2 1 + 2 c_1 Omega^-2 mu_1 2 - c_1 Omega^-2 mu_1 1 - 2 c_1 Omega^-2 mu_2 2\r\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The raw moments are defined as","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"mu_ij(t) = langle X(t)^i Y(t)^j rangle","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"where langle rangle denote the expectation value and we have explicitly included the time-dependence for completeness (made implicit in the formatted moment equations). Note that the ordering of species (X first and Y second) is consistent with the order these variables appear within the Catalyst.@reaction_network macro. The ordering can also be checked using Catalyst.speciesmap function:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"speciesmap(rn)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Dict{Term{Real},Int64} with 2 entries:\r\n X(t) => 1\r\n Y(t) => 2","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Coming back to the generated moment equations, we observe that they depend on higher-order moments. For example, the ODE for mu_02 depends on third order moments μ_12 and μ_21 and the fourth order moment mu_22. Consider the general case of raw moment equations: if a network involves reactions that are polynomials (in molecule numbers) of at most order k, then its m^textth order moment equations will depend on moments up to order m+k-1. Hence the relationship seen above is expected as the Brusselator involves a trimolecular reaction whose corresponding propensity function is a third order polynomial in X(t) and Y(t). The number denoting the highest order of moments encountered in the generated RawMomentEquations can also be accessed as raw_eqs.q_order (returning 4 in this case).","category":"page"},{"location":"tutorials/using_momentclosure/#Central-Moment-Equations","page":"Using MomentClosure","title":"Central Moment Equations","text":"","category":"section"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The corresponding central moment equations can also be easily generated:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"central_eqs = generate_central_moment_eqs(rn, 2, combinatoric_ratelaws=false)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Note that in case of non-polynomial propensity functions the Taylor expansion order q must also be specified, see the P53 system example for more details. Luckily, the Brusselator contains only mass-action reactions and hence q is automatically determined by the highest order (polynomial) propensity. The function generate_central_moment_eqs returns an instance of CentralMomentEquations. As before, we can visualise the central moment equations:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"latexify(central_eqs)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"beginalign*\r\nfracdmu_1 0dt = c_3 Omega + c_1 Omega^-2 M_2 1 + c_1 Omega^-2 mu_1 0^2 mu_0 1 + c_1 Omega^-2 M_2 0 mu_0 1 + 2 c_1 Omega^-2 M_1 1 mu_1 0 - c_2 mu_1 0 - c_4 mu_1 0 - c_1 Omega^-2 M_1 1 - c_1 Omega^-2 mu_0 1 mu_1 0 \r\nfracdmu_0 1dt = c_2 mu_1 0 + c_1 Omega^-2 M_1 1 + c_1 Omega^-2 mu_0 1 mu_1 0 - c_1 Omega^-2 M_2 1 - c_1 Omega^-2 mu_1 0^2 mu_0 1 - c_1 Omega^-2 M_2 0 mu_0 1 - frac21 c_1 Omega^-2 M_1 1 mu_1 0 \r\nfracdM_2 0dt = c_3 Omega + c_2 mu_1 0 + c_4 mu_1 0 + 2 c_1 Omega^-2 M_3 1 + c_1 Omega^-2 mu_1 0^2 mu_0 1 + 2 c_1 Omega^-2 mu_1 0^2 M_1 1 + 2 c_1 Omega^-2 M_3 0 mu_0 1 + 4 c_1 Omega^-2 M_2 1 mu_1 0 + 4 c_1 Omega^-2 M_2 0 mu_0 1 mu_1 0 - 2 c_2 M_2 0 - 2 c_4 M_2 0 - c_1 Omega^-2 M_1 1 - c_1 Omega^-2 M_2 1 - c_1 Omega^-2 M_2 0 mu_0 1 - c_1 Omega^-2 mu_0 1 mu_1 0 \r\nfracdM_1 1dt = c_2 M_2 0 + c_1 Omega^-2 M_1 1 + c_1 Omega^-2 M_2 2 + c_1 Omega^-2 mu_1 0^2 M_0 2 + c_1 Omega^-2 M_2 1 mu_0 1 + c_1 Omega^-2 mu_0 1 mu_1 0 + 2 c_1 Omega^-2 M_1 2 mu_1 0 + 2 c_1 Omega^-2 M_1 1 mu_0 1 mu_1 0 - c_2 M_1 1 - c_4 M_1 1 - c_2 mu_1 0 - c_1 Omega^-2 M_1 2 - c_1 Omega^-2 M_3 1 - c_1 Omega^-2 mu_1 0^2 M_1 1 - c_1 Omega^-2 mu_1 0^2 mu_0 1 - c_1 Omega^-2 M_0 2 mu_1 0 - c_1 Omega^-2 M_1 1 mu_0 1 - c_1 Omega^-2 M_3 0 mu_0 1 - c_1 Omega^-2 M_1 1 mu_1 0 - 2 c_1 Omega^-2 M_2 1 mu_1 0 - 2 c_1 Omega^-2 M_2 0 mu_0 1 mu_1 0 \r\nfracdM_0 2dt = c_2 mu_1 0 + 2 c_2 M_1 1 + c_1 Omega^-2 M_2 1 + 2 c_1 Omega^-2 M_1 2 + c_1 Omega^-2 mu_1 0^2 mu_0 1 + c_1 Omega^-2 M_2 0 mu_0 1 + 2 c_1 Omega^-2 M_0 2 mu_1 0 + 2 c_1 Omega^-2 M_1 1 mu_0 1 + 2 c_1 Omega^-2 M_1 1 mu_1 0 - c_1 Omega^-2 M_1 1 - 2 c_1 Omega^-2 M_2 2 - 2 c_1 Omega^-2 mu_1 0^2 M_0 2 - c_1 Omega^-2 mu_0 1 mu_1 0 - 2 c_1 Omega^-2 M_2 1 mu_0 1 - 4 c_1 Omega^-2 M_1 2 mu_1 0 - 4 c_1 Omega^-2 M_1 1 mu_0 1 mu_1 0\r\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Unfortunately, central moment equations often take a visually painful form. Note that the first two ODEs, as before, indicate the means, and the central moments are denoted as","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"M_ij(t) = langle (X(t)-mu_10(t))^i (Y(t)-mu_01(t))^j rangle","category":"page"},{"location":"tutorials/using_momentclosure/#Applying-Moment-Closure","page":"Using MomentClosure","title":"Applying Moment Closure","text":"","category":"section"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"As observed above, the moment equations of the Brusselator are coupled and depend on higher order moments—we have an infinite hierarchy of ODEs in our hands which cannot be solved directly and requires approximate treatment. One way of approaching the problem is to apply moment closure approximations (MAs), in which higher order moments are expressed as functions of lower order moments, thus effectively truncating the hierarchy and enabling a numerical solution. A variety of MAs have been proposed in literature and are implemented in MomentClosure.jl, see the Theory section on MAs for more details.","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Let's apply normal closure to the raw moment equations raw_eqs we have generated earlier using moment_closure function:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"closed_raw_eqs = moment_closure(raw_eqs, \"normal\")","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The function returns ClosedMomentEquations that consists of both the ModelingToolkit.ODESystem containing all closed moment equations as well as the specific closure functions for each higher order raw moments. We can use Latexify again to look at the closed ODEs:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"latexify(closed_raw_eqs)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"beginalign*\r\nfracdmu_10dt = c_3 Omega + c_1 mu_01 mu_20 Omega^-2 + 2 c_1 mu_10 mu_11 Omega^-2 - c_2 mu_10 - c_4 mu_10 - c_1 mu_11 Omega^-2 - 2 c_1 mu_01 Omega^-2 mu_10^2 \r\nfracdmu_01dt = c_2 mu_10 + c_1 mu_11 Omega^-2 + 2 c_1 mu_01 Omega^-2 mu_10^2 - c_1 mu_01 mu_20 Omega^-2 - 2 c_1 mu_10 mu_11 Omega^-2 \r\nfracdmu_20dt = c_2 mu_10 + c_3 Omega + c_4 mu_10 + 2 c_3 Omega mu_10 + 2 c_1 mu_01 Omega^-2 mu_10^2 + 6 c_1 mu_11 mu_20 Omega^-2 - 2 c_2 mu_20 - 2 c_4 mu_20 - c_1 mu_11 Omega^-2 - c_1 mu_01 mu_20 Omega^-2 - 4 c_1 mu_01 Omega^-2 mu_10^3 - 2 c_1 mu_10 mu_11 Omega^-2 \r\nfracdmu_11dt = c_2 mu_20 + c_1 mu_11 Omega^-2 + c_3 Omega mu_01 + c_1 mu_02 mu_20 Omega^-2 + 2 c_1 Omega^-2 mu_11^2 + 2 c_1 mu_01 Omega^-2 mu_10^3 + 2 c_1 mu_10 Omega^-2 mu_01^2 - c_2 mu_10 - c_2 mu_11 - c_4 mu_11 - 2 c_1 mu_01 mu_11 Omega^-2 - c_1 mu_02 mu_10 Omega^-2 - 3 c_1 mu_11 mu_20 Omega^-2 - 2 c_1 Omega^-2 mu_01^2 mu_10^2 \r\nfracdmu_02dt = c_2 mu_10 + 2 c_2 mu_11 + c_1 mu_01 mu_20 Omega^-2 + 4 c_1 mu_01 mu_11 Omega^-2 + 2 c_1 mu_02 mu_10 Omega^-2 + 2 c_1 mu_10 mu_11 Omega^-2 + 4 c_1 Omega^-2 mu_01^2 mu_10^2 - c_1 mu_11 Omega^-2 - 4 c_1 Omega^-2 mu_11^2 - 2 c_1 mu_01 Omega^-2 mu_10^2 - 2 c_1 mu_02 mu_20 Omega^-2 - 4 c_1 mu_10 Omega^-2 mu_01^2\r\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The closure functions can also be displayed by adding :closure argument:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"latexify(closed_raw_eqs, :closure)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"beginalign*\r\nmu_21 = mu_01 mu_20 + 2 mu_10 mu_11 - 2 mu_01 mu_10^2 \r\nmu_12 = mu_02 mu_10 + 2 mu_01 mu_11 - 2 mu_10 mu_01^2 \r\nmu_31 = mu_01 mu_30 + 6 mu_01 mu_10^3 + 3 mu_10 mu_21 + 3 mu_11 mu_20 - 6 mu_11 mu_10^2 - 6 mu_01 mu_10 mu_20 \r\nmu_22 = mu_02 mu_20 + 2 mu_11^2 + 2 mu_01 mu_21 + 2 mu_10 mu_12 + 6 mu_01^2 mu_10^2 - 2 mu_02 mu_10^2 - 2 mu_20 mu_01^2 - 8 mu_01 mu_10 mu_11\r\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Similarly, we can close central moment equations using","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"closed_central_eqs = moment_closure(central_eqs, \"normal\")","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"and print out the corresponding closure functions:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"latexify(closed_central_eqs, :closure)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"beginalign*\r\nM_30 = 0 \r\nM_21 = 0 \r\nM_12 = 0 \r\nM_31 = 3 M_11 M_20 \r\nM_22 = M_02 M_20 + 2 M_11^2\r\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Higher order central moments under normal closure take a rather simple form compared to their raw moment equivalents. That can be expected due to the relationship between central moments and cumulants, on which the closure is based.","category":"page"},{"location":"tutorials/using_momentclosure/#Solving-Moment-Equations","page":"Using MomentClosure","title":"Solving Moment Equations","text":"","category":"section"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The closed moment equations can be solved numerically using DifferentialEquations.jl that provides a variety of highly-efficient solvers and analysis tools. In order to do so, first we need to specify the values of all system parameters, the initial condition and the timespan to solve over. Then the ModelingToolkit.ODESystem corresponding to the moment equations can be directly converted into an ODEProblem which can finally be solved. Let's go through the procedure step-by-step for the closed raw moment equations (closed_raw_eqs). Most of what is covered below is closely based on this Catalyst tutorial.","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"We start with the parameters. Note that they are ordered as they appear after the end statement in the @reaction_network macro and this ordering can also be checked using the paramsmap function:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"paramsmap(rn)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Dict{Sym{ModelingToolkit.Parameter{Real}},Int64} with 5 entries:\r\n c₃ => 3\r\n Ω => 5\r\n c₄ => 4\r\n c₂ => 2\r\n c₁ => 1","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"We can now create a vector of parameter values as:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"# parameters [c₁, c₂, c₃, c₄, Ω]\r\np = [0.9, 2, 1, 1, 100]","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Next, we can specify the initial condition. Usually when working with moment equations we consider deterministic initial conditions so that the molecule numbers at initial time take the specified integer values with probability one. We can define the initial molecule numbers as X(t=0) = X_0 and Y(t=0) = Y_0. Probability one implies that initially the means will be equal to the molecule numbers, i.e., μ_10(t=0) = X_0 and μ_01(t=0) = Y_0, whereas all higher order raw moments will be products of the corresponding powers of the means, e.g., μ_21 = X_0^2 Y_0. Note that all central moments would be set to zero in this case. To make life easier we use deterministic_IC function which, given the initial molecule numbers, automatically constructs the variable mapping under deterministic initial conditions:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"# initial molecule numbers [X, Y] (order as in speciesmap(rn))\r\nu₀ = [1, 1]\r\nu₀map = deterministic_IC(u₀, closed_raw_eqs)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The next ingredient, the time interval to solve on, can be specified simply as:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"tspan = (0., 100.)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Now we are able to create the corresponding ODEProblem:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Finally, we have everything we need to solve the raw moment equations which can be done using any ODE solver implemented within DifferentialEquations.jl. We use the default Tsit5() solver and then plot the obtained mean molecule numbers:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"# using only ODE solvers from DifferentialEquations (faster to load)\r\nusing OrdinaryDiffEq\r\nsol = solve(oprob, Tsit5(), saveat=0.1)\r\n\r\nusing Plots\r\nplot(sol, idxs=[1,2], lw=2)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"(Image: Brusselator means 1)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The obtained moment dynamics show damped oscillations which is the expected averaged behaviour of the Brusselator in a vast swathe of parameter space [1]. However, to establish more clearly how well a second order moment expansion with normal moment closure performs for this system and this specific set of parameters, we can compare the resulting moment trajectories to the true moment estimates obtained using Gillespie's Stochastic Simulation Algorithm (SSA).","category":"page"},{"location":"tutorials/using_momentclosure/#Stochastic-Simulation","page":"Using MomentClosure","title":"Stochastic Simulation","text":"","category":"section"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"To run the SSA for a given reaction network, we build a JumpProcesses (formerly known as DiffEqJump) JumpProblem using Gillespie's Direct method. Note that other SSA variants are also available, see the documentation. Moreover, in order to run many realisations of the jump process, we define a corresponding EnsembleProblem. All of this can be done as follows:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"using JumpProcesses\r\n\r\n# convert ReactionSystem into JumpSystem\r\njsys = convert(JumpSystem, rn, combinatoric_ratelaws=false)\r\n\r\n# create a DiscreteProblem encoding that the molecule numbers are integer-valued\r\ndprob = DiscreteProblem(jsys, u₀, tspan, p) # same parameters as defined earlier\r\n\r\n# create a JumpProblem: specify Gillespie's Direct Method as the solver\r\n# and SET save_positions to (false, false) as otherwise time of each\r\n# reaction occurence would be saved (complicating moment estimates)\r\njprob = JumpProblem(jsys, dprob, Direct(), save_positions=(false, false))\r\n\r\n# define an EnsembleProblem to simulate multiple trajectories\r\nensembleprob = EnsembleProblem(jprob)\r\n\r\n# simulate 10000 SSA trajectories\r\n@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.1, trajectories=10000)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Now we use the DifferentialEquations ensemble statistics tools to calculate the SSA mean values and plot them:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"using DiffEqBase.EnsembleAnalysis\r\n\r\nmeans_SSA = timeseries_steps_mean(sol_SSA)\r\nplot!(means_SSA, lw=2, labels=[\"SSA μ₁₀(t)\" \"SSA μ₀₁(t)\"], linestyle=:dash,\r\n linecolor=[1 2], background_color_legend=nothing, legend=:bottomright)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"(Image: Brusselator SSA 1)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The comparison to the SSA reveals that the second-order moment expansion using normal closure captures the correct qualitative behaviour of the Brusselator and provides reasonably accurate moment estimates given this particular parameter set. Note, however, that moment closure approximations can lead to unphysical results and suffer from numerical instabilities, please see the Common Issues tutorial for more details.","category":"page"},{"location":"#MomentClosure","page":"Home","title":"MomentClosure","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"MomentClosure.jl is a tool to automatically obtain time-evolution equations of moments up to an arbitrary order for virtually any chemical reaction network or system of stochastic differential equations (SDEs), implementing a wide array of moment closure approximations commonly used in stochastic biochemical kinetics [1]. MomentClosure is (attempted to be) fairly well-integrated within the broader Julia ecosystem utilising a number of familiar packages:","category":"page"},{"location":"","page":"Home","title":"Home","text":"MomentClosure can be immediately applied to reaction network models defined using Catalyst and SDE systems built with ModelingToolkit.\nMoment equations are generated as a ModelingToolkit ODESystem (with some extra help from Symbolics and SymbolicUtils).\nThe resulting ODESystem can be solved using any DifferentialEquations ODE solvers, enabling further study of the system using parameter estimation, sensitivity analysis and bifurcation analysis tools.","category":"page"},{"location":"#Features","page":"Home","title":"Features","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Chemical reaction networks containing any number of molecular species and reactions with any type of smooth propensity functions are supported. Models can be defined using Catalyst as ModelingToolkit.ReactionSystem.\nAdded support for reaction networks involving reaction products that are geometrically distributed random variables. An example of such network is an autoregulatory gene network with bursty protein production where the burst size follows a geometric distribution, see this example for more details.\nEquations describing the time evolution of means and central moments of the number of molecules of each species in the system can be generated up to arbitrary order [2, 3]. Note that non-polynomial propensity functions are Taylor expanded to a specified order. Raw moment equations can also be generated for mass-action systems (where all propensity functions are polynomials). \nSDE systems defined as ModelingToolkit.SDESystem are supported (big thanks to @FHoltorf). Similarly to reaction networks with non-polynomial propensities, non-polynomial drift and diffusion coefficients are Taylor expanded.\nCurrently implemented moment closure approximations include:\nzero (central-moment neglect) closure [4, 5]\nnormal closure [4]\npoisson closure [4]\nlog-normal closure [5]\ngamma closure [5]\nderivative matching [6]\nconditional gaussian closure [7]\nconditional derivative matching [7]\nlinear mapping approximation [8]\nMoment equations are constructed as a ModelingToolkit.ODESystem that can be solved using any DifferentialEquations ODE solver. Moreover, parameter estimation, sensitivity analysis and bifurcation analysis tools can be applied to further study the resulting system of equations.\nLatexify can be used to generate LaTeX expressions of the corresponding moment equations.","category":"page"},{"location":"#Installation","page":"Home","title":"Installation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"MomentClosure can be installed through the Julia package manager:","category":"page"},{"location":"","page":"Home","title":"Home","text":"]add MomentClosure\nusing MomentClosure","category":"page"},{"location":"#Citation","page":"Home","title":"Citation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"If you use MomentClosure in your work, please cite our paper:","category":"page"},{"location":"","page":"Home","title":"Home","text":"@article{MomentClosure2021,\n author = {Sukys, Augustinas and Grima, Ramon},\n title = \"{MomentClosure.jl: automated moment closure approximations in Julia}\",\n journal = {Bioinformatics},\n volume = {38},\n number = {1},\n pages = {289-290},\n year = {2021},\n month = {06},\n issn = {1367-4803},\n doi = {10.1093/bioinformatics/btab469},\n url = {https://doi.org/10.1093/bioinformatics/btab469},\n eprint = {https://academic.oup.com/bioinformatics/article-pdf/38/1/289/41891091/btab469.pdf},\n}","category":"page"},{"location":"#References","page":"Home","title":"References","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"[1]: D. Schnoerr, G. Sanguinetti, and R. Grima, \"Approximation and inference methods for stochastic biochemical kinetics - a tutorial review\", Journal of Physics A: Mathematical and Theoretical 50, 093001 (2017). https://doi.org/10.1088/1751-8121/aa54d9","category":"page"},{"location":"","page":"Home","title":"Home","text":"[2]: A. Ale, P. Kirk, and M. P. H. Stumpf, \"A general moment expansion method for stochastic kinetic models\", The Journal of Chemical Physics 138, 174101 (2013). https://doi.org/10.1063/1.4802475","category":"page"},{"location":"","page":"Home","title":"Home","text":"[3]: C. H. Lee, \"A Moment Closure Method for Stochastic Chemical Reaction Networks with General Kinetics\", MATCH Communications in Mathematical and in Computer Chemistry 70, 785-800 (2013). https://match.pmf.kg.ac.rs/electronicversions/Match70/n3/match70n3785-800.pdf","category":"page"},{"location":"","page":"Home","title":"Home","text":"[4]: D. Schnoerr, G. Sanguinetti, and R. Grima, \"Comparison of different moment-closure approximations for stochastic chemical kinetics\", The Journal of Chemical Physics 143, 185101 (2015). https://doi.org/10.1063/1.4934990","category":"page"},{"location":"","page":"Home","title":"Home","text":"[5]: E. Lakatos, A. Ale, P. D. W. Kirk, and M. P. H. Stumpf, \"Multivariate moment closure techniques for stochastic kinetic models\", The Journal of Chemical Physics 143, 094107 (2015). https://doi.org/10.1063/1.4929837","category":"page"},{"location":"","page":"Home","title":"Home","text":"[6]: A. Singh and J. P. Hespanha, \"Lognormal Moment Closures for Biochemical Reactions\", in Proceedings of the 45th IEEE Conference on Decision and Control, ISSN: 0191-2216 (Dec. 2006), pp. 2063-2068. https://doi.org/10.1109/CDC.2006.376994","category":"page"},{"location":"","page":"Home","title":"Home","text":"[7]: M. Soltani, C. A. Vargas-Garcia, and A. Singh, \"Conditional Moment Closure Schemes for Studying Stochastic Dynamics of Genetic Circuits\", IEEE Transactions on Biomedical Circuits and Systems 9, 518-526 (2015). https://doi.org/10.1109/TBCAS.2015.2453158","category":"page"},{"location":"","page":"Home","title":"Home","text":"[8]: Z. Cao and R. Grima, \"Linear mapping approximation of gene regulatory networks with stochastic dynamics\", Nature Communications 9, 3305 (2018). https://doi.org/10.1038/s41467-018-05822-0","category":"page"},{"location":"api/momentclosure_api/#api","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"","category":"section"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"CurrentModule = MomentClosure","category":"page"},{"location":"api/momentclosure_api/#Model-definition","page":"MomentClosure.jl API","title":"Model definition","text":"","category":"section"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"MomentClosure is fully compatible with reaction network models defined using Catalyst and stored as a ModelingToolkit.ReactionSystem. Note that previously we had implemented our own ReactionSystemMod, that allowed us to consider systems containing reactions which products are independent geometrically distributed random variables. However, this is now deprecated as Catalyst has added support for such parameteric stoichiometries offering a much more complete and efficient feature set.","category":"page"},{"location":"api/momentclosure_api/#api-basic-network-properties","page":"MomentClosure.jl API","title":"Basic model properties","text":"","category":"section"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"Moreover, we include a couple of tiny extensions to the Catalyst API:","category":"page"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"propensities\r\nget_stoichiometry","category":"page"},{"location":"api/momentclosure_api/#MomentClosure.propensities","page":"MomentClosure.jl API","title":"MomentClosure.propensities","text":"propensities(rn::Union{ReactionSystem, ReactionSystemMod}; combinatoric_ratelaws=true)\n\nReturn a vector of propensity functions of all reactions in the given ReactionSystem.\n\nNotes:\n\ncombinatoric_ratelaws=true uses binomials in calculating the propensity functions of a ReactionSystem, see the notes for ModelingToolkit.jumpratelaw.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#MomentClosure.get_stoichiometry","page":"MomentClosure.jl API","title":"MomentClosure.get_stoichiometry","text":"get_stoichiometry(rn::ReactionSystem, smap::AbstractDict)\n\nReturn the net stoichiometry matrix using the specified mapping of species to their indices.\n\nNotes:\n\nThis is a modification of Catalyst.netstoichmat that is used internally to deal with reactions involving symbolic stoichiometry coefficients.\nThe function also allows custom smap, so it is not limited to the default Catalyst.speciesmap ordering.\nTODO: remove once this Catalyst issue is resolved.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#Moment-Equations","page":"MomentClosure.jl API","title":"Moment Equations","text":"","category":"section"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"generate_raw_moment_eqs\r\nRawMomentEquations\r\ngenerate_central_moment_eqs\r\nCentralMomentEquations\r\nbernoulli_moment_eqs","category":"page"},{"location":"api/momentclosure_api/#MomentClosure.generate_raw_moment_eqs","page":"MomentClosure.jl API","title":"MomentClosure.generate_raw_moment_eqs","text":"generate_raw_moment_eqs(rn::ReactionSystem, m_order::Int;\n langevin::Bool=false, combinatoric_ratelaws::Bool=true, smap=speciesmap(rn))\n\nGiven a ReactionSystem return the RawMomentEquations of the system generated up to m_order.\n\nNotes:\n\nThe expansion order q, denoted by q_order throughout the docs, is automatically determined from the given polynomial form of the propensity functions, see the tutorial and the theory section for more details on how q_order is obtained.\nif langevin=true, instead of the Chemical Master Equation the Chemical Langevin Equation (diffusion approximation) is considered, and the moment equations are constructed from the corresponding SDE formulation.\ncombinatoric_ratelaws=true uses binomials in calculating the propensity functions of a ReactionSystem, see the notes for ModelingToolkit.jumpratelaw. Note that this field is irrelevant using ReactionSystemMod as then the propensities are defined directly by the user.\nsmap sets the variable ordering in the moment equations (which index corresponds to which species in the reaction network). By default, this is consistent with the internal system ordering accessible with Catalyst.speciesmap.\n\n\n\n\n\ngenerate_raw_moment_eqs(sys::SDESystem, m_order::Int)\n\nGiven an SDESystem, return the RawMomentEquations of the system generated up to m_order.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#MomentClosure.RawMomentEquations","page":"MomentClosure.jl API","title":"MomentClosure.RawMomentEquations","text":"struct RawMomentEquations <: MomentClosure.MomentEquations\n\nRaw moment equations generated for the given system plus a number of helper parameters (used internally).\n\nFields\n\nodes: ModelingToolkit.ODESystem consisting of the time-evolution equations of raw moments.\nμ: Symbolic variables defining the raw moments.\nN: Number of species within the system.\nm_order: Order of moment equations.\nq_order: Expansion order.\niter_all: Vector of all index combinations up to q_order.\niter_m: Vector of all index combinations up to m_order.\niter_q: Vector of all index combinations of order greater than m_order up to q_order.\niter_1: Vector of index combinations of order 1.\n\n\n\n\n\n","category":"type"},{"location":"api/momentclosure_api/#MomentClosure.generate_central_moment_eqs","page":"MomentClosure.jl API","title":"MomentClosure.generate_central_moment_eqs","text":"generate_central_moment_eqs(rn::ReactionSystem, m_order::Int, q_order::Int=0;\n langevin::Bool=false, combinatoric_ratelaws::Bool=true, smap=speciesmap(rn))\n\nGiven a ReactionSystem return the CentralMomentEquations of the system generated up to m_order.\n\nNotes:\n\nif q_order is not specified by the user, it is assumed that the reaction network contains only polynomial propensity functions and hence q_order is determined automatically as in generate_raw_moment_eqs. However, q_order must be specified if non-polynomial propensities are included. Note that the expansion order q denotes the highest order of central moments which will be included in the ODEs (due to the Taylor expansion of propensity functions).\nif langevin=true, instead of the Chemical Master Equation the Chemical Langevin Equation (diffusion approximation) is considered, and the moment equations are constructed from the corresponding SDE formulation.\ncombinatoric_ratelaws=true uses binomials in calculating the propensity functions of a ReactionSystem, see the notes for ModelingToolkit.jumpratelaw. Note that this field is irrelevant using ReactionSystemMod as then the propensities are defined directly by the user.\nsmap sets the variable ordering in the moment equations (which index corresponds to which species in the reaction network). By default, this is consistent with the internal system ordering accessible with Catalyst.speciesmap.\n\n\n\n\n\ngenerate_central_moment_eqs(sys::SDESystem, m_order::Int, q_order::Int=0)\n\nGiven an SDESystem, return the CentralMomentEquations of the system generated up to m_order.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#MomentClosure.CentralMomentEquations","page":"MomentClosure.jl API","title":"MomentClosure.CentralMomentEquations","text":"struct CentralMomentEquations <: MomentClosure.MomentEquations\n\nCentral moment equations generated for the given system plus a number of helper parameters (used internally).\n\nFields\n\nodes: ModelingToolkit.ODESystem consisting of the time-evolution equations of central moments.\nμ: Symbolic variables defining the means.\nM: Symbolic variables defining the central moments.\nN: Number of species within the system.\nm_order: Order of moment equations.\nq_order: Expansion order.\niter_all: Vector of all index combinations up to q_order.\niter_m: Vector of all index combinations up to m_order.\niter_q: Vector of all index combinations of order greater than m_order up to q_order.\niter_1: Vector of index combinations of order 1.\n\n\n\n\n\n","category":"type"},{"location":"api/momentclosure_api/#MomentClosure.bernoulli_moment_eqs","page":"MomentClosure.jl API","title":"MomentClosure.bernoulli_moment_eqs","text":"bernoulli_moment_eqs(sys::MomentEquations, binary_vars::Array{Int,1})\n\nGiven MomentEquations and an array of indices specifying the species which molecule numbers are binary variables (either 0 or 1), apply identities of Bernoulli variables to remove the redundant ODEs and return the cleaned up MomentEquations. See here for example usage.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#Moment-Closure","page":"MomentClosure.jl API","title":"Moment Closure","text":"","category":"section"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"moment_closure\r\nClosedMomentEquations\r\ndeterministic_IC","category":"page"},{"location":"api/momentclosure_api/#MomentClosure.moment_closure","page":"MomentClosure.jl API","title":"MomentClosure.moment_closure","text":"moment_closure(sys::MomentEquations, closure::String, binary_vars::Array{Int,1}=Int[])\n\nGiven MomentEquations, apply the specified moment closure approximation and return the ClosedMomentEquations.\n\nThe supported closure options are:\n\n\"zero\"\n\"normal\"\n\"log-normal\"\n\"poisson\"\n\"gamma\"\n\"derivative matching\"\n\"conditional gaussian\"\n\"conditional derivative matching\"\n\nNotes\n\nbinary_vars must be specified for conditional closures as an array of indices of all species (as in Catalyst.speciesmap) which molecule number is a Bernoulli variable. Although not necessary for other closures, specifying binary_vars is recommended as the properties of Bernoulli variables will be used to remove the redundant moment equations and simplify the expressions, which can significantly improve numerical stability.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#MomentClosure.ClosedMomentEquations","page":"MomentClosure.jl API","title":"MomentClosure.ClosedMomentEquations","text":"struct ClosedMomentEquations <: MomentClosure.MomentEquations\n\nClosed moment equations and the corresponding closure functions.\n\nFields\n\nodes: ModelingToolkit.ODESystem consisting of the time-evolution equations of closed moments.\nclosure: Dictionary of moment closure functions for each higher order moment.\nopen_eqs: Original raw or central moment equations (before closure was applied).\n\n\n\n\n\n","category":"type"},{"location":"api/momentclosure_api/#MomentClosure.deterministic_IC","page":"MomentClosure.jl API","title":"MomentClosure.deterministic_IC","text":"deterministic_IC(u₀::Array{T, 1}, eqs::MomentEquations) where T<:Real\n\nGiven an array of initial molecule numbers and the corresponding moment equations, return a mapping of each moment to its initial value under deterministic initial conditions.\n\nNotes\n\nThe means are set to initial molecule numbers (as they take the values specified in u₀ with probability one). The higher order raw moments are products of the corresponding powers of the means whereas the higher order central moments are simply zero.\nThe ordering of u₀ elements must be consistent with the ordering of species in the corresponding reaction system (can be checked with the Catalyst.speciesmap function).\nAs higher-order moment functions under log-normal, gamma, derivative matching and the conditional closures involve moments raised to negative powers, setting initial molecule numbers of certain species to zeros will result in NaN errors when solving the ODEs (the specifics depend on the system at hand).\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#visualisation_api","page":"MomentClosure.jl API","title":"Displaying Equations and Closures","text":"","category":"section"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"The generated moment equations can be converted into LaTeX expressions using Latexify as:","category":"page"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"using Latexify\r\nlatexify(moment_eqs)","category":"page"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"A ModelingToolkit.ODESystem (saved as moment_eqs.odes) can also be passed to latexify function directly but the output will be different as we apply additional formatting to the symbolic expressions.","category":"page"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"Given ClosedMomentEquations, the closure functions can be visualised in the same way by adding a :closure argument:","category":"page"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"latexify(moment_eqs, :closure)","category":"page"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"Note that this will print out only those higher order moments which are found in the given moment equations. It is possible to print the closure functions of all higher order moments using print_all=true argument:","category":"page"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"latexify(moment_eqs, :closure, print_all=true)","category":"page"},{"location":"api/momentclosure_api/#Linear-Mapping-Approximation","page":"MomentClosure.jl API","title":"Linear Mapping Approximation","text":"","category":"section"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"linear_mapping_approximation","category":"page"},{"location":"api/momentclosure_api/#MomentClosure.linear_mapping_approximation","page":"MomentClosure.jl API","title":"MomentClosure.linear_mapping_approximation","text":" linear_mapping_approximation(rn_nonlinear::T, rn_linear::T, binary_vars::Array{Int,1}=Int[], m_order::Int=0;\n combinatoric_ratelaws = true) where T <: ReactionSystem\n\nGiven a nonlinear ReactionSystem and an equivalent linear ReactionSystem, perform the Linear Mapping Approximation (LMA) and return the corresponding linear RawMomentEquations of the system as well as a Dictionary of reaction parameter substitutions obtained using LMA that are used to generate the moment equations. See the LMA theory section for more details.\n\nNotes:\n\nrn_nonlinear and rn_linear must be identical in layout in order to be interpreted correctly, and the nonlinear reactions contained in rn_nonlinear must all be linearised in rn_linear with rate coefficients updated accordingly. Although this requires a lot of manual input, automating the linearisation further is difficult due to arbitrary choices that may be mane in constructing the reaction networks.\nbinary_vars must be specified for conditional closures as an array of indices of all species (as in Catalyst.speciesmap) which molecule number is a Bernoulli variable. Note that rn_nonlinear and rn_linear may internally order the species differently: binary_vars must be consistent with the ordering in the nonlinear network.\nBy default the moment equations will be generated up to the order determined by the degree of nonlinearity of the nonlinear system's reactions. However, if higher order moment information is required, the optional m_order argument may be provided to increase the expansion order manually.\ncombinatoric_ratelaws=true uses binomials in calculating the propensity functions of a ReactionSystem, see the notes for ModelingToolkit.jumpratelaw.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#stochastic_simulation_utilities","page":"MomentClosure.jl API","title":"Stochastic Simulation Utilities","text":"","category":"section"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"We provide provides functions for higher-order moment extraction from SSA and FSP data:","category":"page"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"get_raw_moments\r\nget_central_moments\r\nget_cumulants\r\nget_moments_FSP","category":"page"},{"location":"api/momentclosure_api/#MomentClosure.get_raw_moments","page":"MomentClosure.jl API","title":"MomentClosure.get_raw_moments","text":"get_raw_moments(sol::EnsembleSolution, order::Int; naive::Bool=true, b::Int=2)\n\nGiven an EnsembleSolution of DifferentialEquations ensemble simulation, return a Dictionary of raw moments computed up to the specified order at each time step.\n\nNotes\n\nFor example, the dictionary key (2,0,1) maps to an array containing the values of the raw moment μ_201 at each time step.\nIt is assumed that the time steps are all at the same time point for all trajectories (i.e., fixed dt used by the integrator or values were saved using saveat, as discussed here).\nMoments are computed using Cumulants.jl internally. The naive algorithm of moment tensor calculations (naive=true) is usually faster for small systems but the proposed novel algorithm (naive=false) should be more efficient in case of many marginal variables. The block size b can also be specified for the novel algorithm and may have a significant effect on its performance.\nOnly useful if higher order moments are needed: DifferentialEquations has a number of far more efficient and flexible ensemble statistics functions for means, variances and correlations, see this tutorial for more details.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#MomentClosure.get_central_moments","page":"MomentClosure.jl API","title":"MomentClosure.get_central_moments","text":"get_central_moments(sol::EnsembleSolution, order::Int; naive::Bool=true, b::Int=2)\n\nGiven an EnsembleSolution of DifferentialEquations ensemble simulation, return a Dictionary of central moment estimates computed up to the specified order at each time step. See the notes of get_raw_moments function for more information.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#MomentClosure.get_cumulants","page":"MomentClosure.jl API","title":"MomentClosure.get_cumulants","text":"get_cumulants(sol::EnsembleSolution, order::Int; naive::Bool=true, b::Int=2)\n\nGiven an EnsembleSolution of DifferentialEquations ensemble simulation, return a Dictionary of cumulant estimates computed up to the specified order at each time step. See the notes of get_raw_moments function for more information.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#MomentClosure.get_moments_FSP","page":"MomentClosure.jl API","title":"MomentClosure.get_moments_FSP","text":"get_moments_FSP(sol::ODESolution, order::Int, moment_type::String)\n\nGiven an ODESolution obtained using FiniteStateProjection.jl, return a Dictionary of moments computed up to the specified order at each time step. Here, moment_type specifies the type of moments to be computed: available options are raw, central or cumulant.\n\nNotes\n\nThe ODESolution represents the time-evolution of the probability density function that is the solution of the Chemical Master Equation approximated using Finite State Projection algorithms. See the documentation of FiniteStateProjection.jl for more information.\n\n\n\n\n\n","category":"function"}] +[{"location":"theory/linear_mapping_approximation/#linear_mapping_approximation","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"","category":"section"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"The Linear Mapping Approximation (LMA) provides a novel way of approximating the solution of the CME and has been shown to be accurate for a variety of models of gene regulatory networks (GRNs) [1]. It is based on mapping a nonlinear GRN onto an equivalent linear GRN so that the exact solution of the linear system gives an approximate solution of the nonlinear system. The LMA is restricted in its applicability to chemical reaction networks where one of the substrates in each nonlinear reaction is a molecular species which copy number can be either zero or one (a Bernoulli/binary random variable). Note that a network can contain an arbitrary number of such species but more than one of them cannot be involved in any nonlinear reaction. Below we provide a short overview of the LMA and urge the reader to see the original paper for a more comprehensive description [1].","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"To explain the LMA procedure, we start by considering a simple example of a two-state GRN as done in a previous section on conditional closures, denoting the binary gene state by g and the protein number by p. We assume that there is a single nonlinear reversible reaction in the network given by","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"beginalign*\nG+P undersetσ_ustackrelσ_brightleftharpoons G^*\nendalign*","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"where P denotes the protein and the gene can be in either state G (g=1) or G^* (g=0). Our aim is to find an approximate time-dependent probability distribution of protein numbers p at time t.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"The steps of performing the LMA can then be described as follows:","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"1. Find the linear network by replacing any reversible nonlinear reaction (it must involve one binary species) in the nonlinear network by a reversible pseudo first-order reaction between the binary species' states.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"In our example, we replace the reaction above with G undersetσ_ustackrelbarσ_brightleftharpoons G^*, noting that the rate parameter is changed from σ_b to barσ_b. Moreover, this approach is just as applicable in case of cooperativity, e.g., G+nP rightleftharpoons G^* (where n is an integer indicating the cooperative order) would be similarly replaced with G rightleftharpoons G^*.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"2. Approximate the changed rate parameters of the linearised reactions by their expectation values.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"As noted in [1], the first-order reaction G stackrelbarσ_brightarrow G^* maps onto the second-order reaction G+P stackrelσ_brightarrow G^* if we choose barσ_b = σ_b left(p g=1 right), where p g=1 indicates the instantaneous protein number given the gene is in the state G. In LMA, we use the mean-field approximation taking the expectation value of the rate so that\nbeginalign*\nbarσ_b = σ_b left langle p g=1 right rangle = σ_b fracleftlangle pg rightrangleleftlangle g rightrangle\nendalign*\nThe same procedure can be extended to the general nonlinear reaction where n proteins bind cooperatively. The effective parameter is then given by\nbarσ_b = σ_b fracleftlangle prod_i=0^n-1 left( p-iright)g rightrangleleftlangle g rightrangle","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"3. Write down the moment equations for the linear network using the approximated stochastic rates.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"Note that the moment equations must be generated up the order given by the highest order nonlinear reaction in the network. If the only nonlinear reaction is the second-order reaction G+P stackrelσ_brightarrow G^*, we need to consider only moments up to the second order (as hinted by the functional form of barσ_b above). However, the moment hierarchy is otherwise closed, no additional moment closure approximations need to be performed, and therefore we can solve the moment equations in a straightforward manner.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"4. Solve the moment equations numerically up to time t and plug the resulting moment values into the equations for the effective parameters. Proceed to calculate the time-average of these parameters over the time-interval 0 t.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"In our example, plugging the solved-for moment values into the equation for barσ_b allows us to interpret the effective parameter as a time-dependent function barσ_b(t). However, as the time-dependent probability distribution solution of the CME for the nonlinear network with a general time-dependent barσ_b is most likely intractable, we transform barσ_b(t) into a time-independent constant by taking its time-average barσ_b^* = int_0^t barσ_b(t) dt t. This approach is justified in [1] by considering the Magnus expansion.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"5. Obtain the time-dependent probability distribution solution of the CME of the linear network assuming that the rate parameters of the linearised reactions are time-independent constants.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"Note that this step is the major limitation of the LMA as closed-form solutions are available only for a handful of systems (consult [1] for more details).","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"6. Finally, construct the approximate probability distribution of the nonlinear network at time t by replacing the respective rate parameters with their time-averaged equivalents obtained in the previous step.","category":"page"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"MomentClosure.jl provides automated generation of the closed moment equations using LMA given a nonlinear chemical reaction network and its linear equivalent. This encapsulates the first three steps of the LMA procedure outlined above which are general and can be seen as an original moment closure approximation. We apply the LMA on simple models of nonlinear GRNs and also discuss how the subsequent LMA steps can be performed in Julia on a case-by-case basis in this tutorial example.","category":"page"},{"location":"theory/linear_mapping_approximation/#References","page":"Linear Mapping Approximation","title":"References","text":"","category":"section"},{"location":"theory/linear_mapping_approximation/","page":"Linear Mapping Approximation","title":"Linear Mapping Approximation","text":"[1]: Z. Cao and R. Grima, \"Linear mapping approximation of gene regulatory networks with stochastic dynamics\", Nature Communications 9, 3305 (2018). https://doi.org/10.1038/s41467-018-05822-0","category":"page"},{"location":"tutorials/P53_system_example/#P53-System-Example","page":"P53 System Example","title":"P53 System Example","text":"","category":"section"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"In this example tutorial, we consider the oscillatory p53-Mdm2 system which has been studied by Lakatos et al. (2015) using central moment expansion up to 5th order with zero, normal, log-normal and gamma closures. We attempt to reproduce a number of results published in their paper.","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"In contrast to the Brusselator we considered before, the p53-Mdm2 system contains non-polynomial propensities and hence is a good showcase for generating central moment equations using different values of q and comparing their accuracy. Note that this was not considered by Lakatos et al. who set q = m+1 throughout their study. We remind the reader that m denotes the moment expansion order and q is the order of Taylor expansion of the propensity functions: the moment equations are generated up to m^textth order and may include central moments up q^textth order so that all moments of orders m+1 dotsc q must be approximated using some moment closure method (see the Moment Expansion theory section for more details).","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"The p53-Mdm2 reaction network is described by the stoichiometric matrix","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"S = beginbmatrix\n 1 -1 -1 0 0 0\n 0 0 0 1 -1 0 \n 0 0 0 0 1 -1\n endbmatrix","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"and six reaction propensities","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"beginalign*\na_1 = k_1 \na_2 = k_2 x_ \na_3 = k_3 fracx yx + k_7 \na_4 = k_4 x \na_5 = k_5 y₀ \na_6 = k_6 y\nendalign*","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"where the variables are","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"number of p53 molecules x\nnumber of precursor of Mdm2 molecules y_0\nnumber of Mdm2 molecules y","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"with parameters","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"p53 production rate k_1\nMdm2-independent p53 degradation rate k_2\nsaturating p53 degradation rate k_3\np53-dependent Mdm2 production rate k_4\nMdm2 maturation rate k_5\nMdm2 degradation rate k_6\np53 threshold for degradation by Mdm2 k_7","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"We begin by loading all the packages we will need","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"using Catalyst, MomentClosure, OrdinaryDiffEq, JumpProcesses,\n DiffEqBase.EnsembleAnalysis, Plots, Plots.PlotMeasures","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"and then build the model using Catalyst and set its parameters as follows:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"# → for mass-actions rate\n# ⇒ for non mass-actions rate\nrn = @reaction_network begin\n @parameters k₁ k₂ k₃ k₄ k₅ k₆ k₇\n (k₁), 0 → x\n (k₂), x → 0\n (k₃*x*y/(x+k₇)), x ⇒ 0\n (k₄*x), 0 ⇒ y₀\n (k₅), y₀ → y\n (k₆), y → 0\nend\n\n# parameters [k₁, k₂, k₃, k₄, k₅, k₆, k₇]\np = [90, 0.002, 1.7, 1.1, 0.93, 0.96, 0.01]\n\n# initial molecule numbers [x, y₀, y]\nu₀ = [70, 30, 60]","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Let's first simulate the reaction network using SSA in order to have a reference point of the real system dynamics. We choose a relatively long simulation time span in order to clearly see how the molecule numbers converge to their steady-state values and opt for 5 times 10^4 SSA realisations:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"# time interval to solve one on\ntspan = (0., 200.)\n\n# constructing the discrete jump problem using DifferentialEquations\njsys = convert(JumpSystem, rn, combinatoric_ratelaws=false)\ndprob = DiscreteProblem(jsys, u₀, tspan, p)\n\njprob = JumpProblem(jsys, dprob, Direct(), save_positions=(false, false))\nensembleprob = EnsembleProblem(jprob)\n\n# @time is only a rough estimate and not a proper benchmark\n@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.2, trajectories=50000)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"1332.443829 seconds (2.90 G allocations: 69.838 GiB, 42.81% gc time)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Single SSA trajectories show sustained oscillations in molecule numbers:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"plot(sol_SSA[666], labels=[\"p53\" \"pre-Mdm2\" \"Mdm2\"], lw=2, tspan=(0., 100.),\n linecolor=[1 3 2], xlabel=\"Time [h]\", ylabel=\"Number of molecules\", size=(700, 400))","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 SSA one trajectory)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"The mean population dynamics show damped oscillations as the single trajectories get dephased over time and eventually reach steady-state values:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"means_SSA, vars_SSA = timeseries_steps_meanvar(sol_SSA)\nplot(means_SSA, labels=[\"p53\" \"pre-Mdm2\" \"Mdm2\"], lw=2, linecolor=[1 3 2],\n xlabel=\"Time [h]\", ylabel=\"Number of molecules\", size=(700, 400))","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 SSA mean trajectories)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Note that many more SSA runs are needed to completely denoise the mean trajectories (especially at later times).","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Finally, we can look at the marginal distributions noting a high level of asymmetry at the chosen time point t=25:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"data = componentwise_vectors_timepoint(sol_SSA, 25.0)\nh1 = histogram(data[1], normalize=true, xlabel=\"x\", ylabel=\"P(x)\")\nh2 = histogram(data[2], normalize=true, xlabel=\"y₀\", ylabel=\"P(y₀)\")\nh3 = histogram(data[3], normalize=true, xlabel=\"y\", ylabel=\"P(y)\")\nusing Plots.PlotMeasures\nplot(h1, h2, h3, legend=false, layout=(1,3), size = (1050, 250),\n left_margin = 5PlotMeasures.mm, bottom_margin = 7PlotMeasures.mm, guidefontsize=10)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 distribution)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Given the long runtime of the SSA above, it makes sense to turn to approximation methods such as moment closure which is usually much faster (suitable if only information about moments is needed). We start with the simplest second order, m =2, moment expansion and consider normal, log-normal and gamma closures. Our interest here is to see how the accuracy of each closure changes when the Taylor expansion order q is increased. Note that zero closure is equivalent to normal closure when q=3 (as third order central moments and cumulants are equivalent) and does not change when q is increased as all the higher order moments will be simply set to zero.","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"We can generate the corresponding plots of the mean p53 molecule number, x, as follows:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"closures = [\"normal\", \"log-normal\", \"gamma\"]\n\n# initialise separate plot for each closure\nplts = [plot() for i in 1:length(closures)]\n\nfor q in 3:6\n eqs = generate_central_moment_eqs(rn, 2, q, combinatoric_ratelaws=false)\n for (closure, plt) in zip(closures, plts)\n closed_eqs = moment_closure(eqs, closure)\n\n u₀map = deterministic_IC(u₀, closed_eqs)\n oprob = ODEProblem(closed_eqs, u₀map, tspan, p)\n\n sol = solve(oprob, Tsit5(), saveat=0.1)\n plt = plot!(plt, sol, idxs=[1], lw=3, label = \"q = \"*string(q))\n end\nend\n\nfor plt in plts\n plt = plot!(plt, xlabel = \"Time [h]\", ylabel = \"Mean number of p53 molecules\")\n plt = plot!(plt, means_SSA.t, means_SSA[1,:], lw=2, linestyle=:dash, label = \"SSA\", color=\"gray\")\nend","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Normal closure:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"plot(plts[1], size=(750, 450), leftmargin=2PlotMeasures.mm)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 normal means 2nd order expansion)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Log-normal closure:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"plot(plts[2], size=(750, 450), leftmargin=2PlotMeasures.mm)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 log-normal means 2nd order expansion)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Zoomed-in log-normal closure (to better see the initial dampening in trajectories):","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"plot(plts[2], xlims=(0., 50.), lw=3)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 log-normal means 2nd order expansion)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Gamma closure:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"plot(plts[3], size=(750, 450), leftmargin=2PlotMeasures.mm)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 gamma means 2nd order expansion)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"When using normal closure, including central moments all the way up to 6th order (q=6) is needed in order to obtain qualitatively correct system behaviour. As the true distribution (as plotted above) is highly asymmetric, one may expect that performing normal closure, i.e., assuming that the system has a (symmetric) Gaussian distribution, is not the most optimal choice. For log-normal and gamma closures, quite accurate predictions are obtained with q=4 whereas q=6 tends to overestimate the dampening initially but better captures the steady-state behaviour. Note that for odd values of q log-normal and gamma closures introduced numerical instabilities and the moments could not be evaluated for the entire time course.","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"We can also plot the variance predictions:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"# rerunning the same calculations as they are reasonably fast\nplt = plot()\nfor q in [4,6]\n eqs = generate_central_moment_eqs(rn, 2, q, combinatoric_ratelaws=false)\n for closure in closures\n closed_eqs = moment_closure(eqs, closure)\n\n u₀map = deterministic_IC(u₀, closed_eqs)\n oprob = ODEProblem(closed_eqs, u₀map, tspan, p)\n sol = solve(oprob, Tsit5(), saveat=0.1)\n\n # index of M₂₀₀ can be checked with `u₀map` or `closed_eqs.odes.states`\n plt = plot!(plt, sol, idxs=[4], lw=3, label = closure*\" q = \"*string(q))\n end\nend\n\nplt = plot!(plt, xlabel = \"Time [h]\", ylabel = \"Variance of p53 molecule number\", legend=:topleft)\nplt = plot!(plt, means_SSA.t, vars_SSA[1,:], lw=2, linestyle=:dash, label = \"SSA\", color=\"gray\")\nplot(plt, size=(750, 450))","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 variances 2nd order expansion)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Log-normal closure with q=6 clearly gives the best estimate of the variance. Therefore, including increasingly higher-order moment information in second-order moment expansion tends to leads to an overall more accurate statistical description of the P53-Mdm2 system.","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"We can extend the analysis further by considering higher order moment expansions (increasing m). Let's look at third-order expansion with q values 4 and 6 (odd q leads to heavy numerical instabilities as before):","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"closures = [\"zero\", \"normal\", \"log-normal\", \"gamma\"]\n\nplt_means = [plot() for i in 1:2]\nplt_vars = [plot() for i in 1:2]\n\nq_vals = [4, 6]\n\nfor (q, plt_m, plt_v) in zip(q_vals, plt_means, plt_vars)\n\n eqs = generate_central_moment_eqs(rn, 3, q, combinatoric_ratelaws=false)\n for closure in closures\n\n closed_eqs = moment_closure(eqs, closure)\n\n u₀map = deterministic_IC(u₀, closed_eqs)\n oprob = ODEProblem(closed_eqs, u₀map, tspan, p)\n\n sol = solve(oprob, Tsit5(), saveat=0.1)\n plt_m = plot!(plt_m, sol, idxs=[1], label = closure) \n plt_v = plot!(plt_v, sol, idxs=[4], label = closure)\n\n end\n\n plt_m = plot!(plt_m, means_SSA.t, means_SSA[1,:], title=\"m = 3, q = \"*string(q),\n linestyle=:dash, label = \"SSA\", color=\"gray\", legend=false)\n\n plt_v = plot!(plt_v, vars_SSA.t, vars_SSA[1,:], linestyle=:dash, label = \"SSA\", color=\"gray\", legend=false)\n\nend\n\nplt_means[1] = plot(plt_means[1], ylabel = \"Mean p53 molecule number\")\nplt_vars[1] = plot(plt_vars[1], ylabel = \"Variance of p53 molecule number\", legend=:topleft)\nplot(plt_means..., plt_vars..., size=(1250, 750), lw=1.5, xlabel=\"Time [h]\",\n guidefontsize=10, titlefontsize=12, legendfontsize=8, leftmargin=4mm, bottommargin=2mm)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 3rd order expansion)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"The results are rather interesting: the mean trajectories initially show the characteristic dampened oscillations, which, however, fail to converge to a steady-state value and instead start growing in amplitude as the time increases—this behaviour is also more pronounced for higher q. Surprisingly, log-normal and gamma closures still provide fairly accurate variance estimates. Note that zero closure ODEs fail to be evaluated for the entire time course at all, displaying strongly oscillatory mean trajectories and even exponentially growing variances. Therefore, third order moment expansion and all of the applied closure methods fail to give physically meaningful results.","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"This outcome seems concerning as Lakatos et al. (2015) state that the same closures reached steady-state at extended simulation time (using identical parameter set). In order to investigate this discrepancy further, we turn to Python MEANS package, the implementation of which is fully based on the technical details presented in Lakatos et al. (2015). Note that the package has not been maintained for years, only works on Python 2 and setting up its dependencies may be fiddly. Nevertheless, having done that, we can generate and solve the moment equations up to third order running the following code in a separate Python 2 notebook:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"import means\nimport means.examples\nimport numpy as np\nimport matplotlib.pyplot as plt\n\nsys = means.examples.MODEL_P53\n\nps = [90, 0.002, 1.7, 1.1, 0.93, 0.96, 0.01]\nic_values = [70, 30, 60]\n\ntspan = np.arange(0, 200, 0.1)\n\nplt.figure(figsize=(10,6))\n\nfor closure in [\"normal\", \"log-normal\", \"gamma\"]:\n odes = means.mea_approximation(sys, 3, closure=closure, multivariate=True)\n simulation = means.Simulation(odes)\n trajectories = simulation.simulate_system(ps, ic_values, tspan)\n trajectories[0].plot(label=closure)\n\nplt.margins(x=0)\nplt.xlabel('Time [h]', fontsize=12)\nplt.ylabel('Mean p53 molecule number', fontsize=12)\nplt.tick_params(axis='both', which='major', labelsize=10)\nplt.legend(fontsize=12)\nplt.show()","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 3rd order expansion MEANS)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"We observe that the mean trajectories fail to converge after all, hinting that some of the results published in Lakatos et al. (2015) may benefit from a more critical analysis. Note that MEANS does not allow arbitrary q values and automatically sets q = m+1, hence third-order moment expansion using MEANS is equivalent to our m=3 q=4 case.","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"We stress that the obtained mean trajectories using the two packages are not identical due to different implementations of the closure methods (different solvers do not have a significant effect in this case). Lakatos et al. (2015) (and hence MEANS) formulate the normal, log-normal and gamma closure functions exclusively in terms of first and second order moments—higher order moments, whose corresponding ODEs are being solved for simultaneously, are not included in the construction of closure functions. One could say that such formulation makes a stronger assumption about the underlying distribution and does not utilise all the information available about the system—our implementation takes that into account. For example, in case of m=3 q=4 moment expansion, we approximate the fourth order central moments in terms of third and lower order moments, whereas MEANS would approximate it using only first and second order moments. Curiously, MEANS formulation appears to be more numerically stable (shows weaker oscillations) at longer times in this particular case, as can be seen from the plots above. Nevertheless, as both approaches failed to produce physically meaningful results, we do not investigate the numerical differences further—one would still generally expect that the inclusion of the computed higher-order moment values will improve the numerical stability of the ODEs and the accuracy of moment estimates.","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Finally, we can check whether better estimates can be obtained using even higher, fifth, order expansion with q=6:","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"plt = plot()\nclosures = [\"zero\", \"normal\", \"log-normal\", \"gamma\"]\n\neqs = generate_central_moment_eqs(rn, 5, 6, combinatoric_ratelaws=false)\n# faster to store than recompute in case we want to try different solvers/params\noprobs = Dict()\n\nfor closure in closures\n closed_eqs = moment_closure(eqs, closure)\n\n u₀map = deterministic_IC(u₀, closed_eqs)\n oprobs[closure] = ODEProblem(closed_eqs, u₀map, tspan, p)\n sol = solve(oprobs[closure], Tsit5(), saveat=0.1)\n\n plt = plot!(plt, sol, idxs=[1], label = closure) \nend\n\nplt = plot!(plt, xlabel = \"Time [h]\", ylabel = \"Mean p53 molecule number\")\nplt = plot!(plt, means_SSA.t, means_SSA[1, :], linestyle=:dash, label = \"SSA\", color=\"gray\")\nplot(plt, size=(750, 450), lw=2)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 5th order expansion)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"All closures are highly numerically unstable and fail to provide physically meaningful results. Performing similar fifth order moment expansion using the MEANS package we obtain (full code can be found in the example Jupyter notebook):","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"(Image: P53-Mdm2 5th order expansion MEANS)","category":"page"},{"location":"tutorials/P53_system_example/","page":"P53 System Example","title":"P53 System Example","text":"Note that normal closure is not included in the plot as it failed to converge using MEANS while log-normal and gamma closures seem to be much more stable in comparison to MomentClosure results (albeit still unphysical). In contrast, normal closure is the only one which succeeded in being evaluated for the entire time course using MomentClosure (full time not shown in the plot) which again is a result of the implementational differences between the two packages.","category":"page"},{"location":"tutorials/SIR_example/#SIR_example","page":"SIR Model Example","title":"SIR Model Example","text":"","category":"section"},{"location":"tutorials/SIR_example/","page":"SIR Model Example","title":"SIR Model Example","text":"See here for an example application of MomentClosure to the SIR model (thanks to @sdwfrost).","category":"page"},{"location":"theory/moment_expansion_SDE/#moment_expansion_SDE","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"","category":"section"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"Moment equations can be also written down for models described by N-dimensional Stochastic Differential Equations (SDEs) of the form ","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\n dmathbfn = mathbff left(mathbfn t right) dt + mathbfGleft( mathbfn t right) dmathbfw_t\nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"where mathbfn=(n_1 dotsc n_N) is a N times 1 state vector, mathbff left(mathbfn t right) = left( f_1(mathbfn t) dotsc f_N(mathbfn t) right)^top is the deterministic (drift) term, mathbfG(mathbfn t) is a N times m (diffusion) matrix and mathbfw_t is a m times 1 vector of Wiener processes so that langle dmathbfw_t rangle = mathbf0 and dmathbfw_t dmathbfw_t^top = mathbfIdt, with mathbfI being an m times m identity matrix. Note that the notation used throughout is consistent with that of the previous section, and the state vector here is the same as for a chemical reaction network of N species (the only difference being that its elements are now continuous variables). The derivations below are based on Ghusinga et al. (2017) [1] and Bover (1978) [2].","category":"page"},{"location":"theory/moment_expansion_SDE/#raw_moment_eqs_SDE","page":"Moment Expansion (SDE)","title":"Raw Moment Equations","text":"","category":"section"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"To obtain the raw moment equations, we begin with Itô's lemma stating that for any smooth scalar function h(mathbfn) one has ","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\n dh(mathbfn) = left sum_i=1^N fracpartial h(mathbfn) partial n_i f_i + frac12 sum_i=1^N sum_j=1^N fracpartial^2 h(mathbfn) partial n_i partial n_j (mathbfGmathbfG^top)_ij rightdt + sum_i=1^N sum_j=1^N fracpartial h(mathbfn) partial n_i mathbfG_ij dw_j \nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"Taking the expectation of both sides we obtain","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\n fracd langle h(mathbfn) rangledt = sum_i=1^N leftlangle fracpartial h(mathbfn)partial n_i f_i rightrangle + frac12 sum_i=1^N sum_j=1^N leftlangle fracpartial^2 h(mathbfn)partial n_i partial n_j (mathbfGmathbfG^top)_ijrightrangle \nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"where we have used the fact that langle dmathbfw rangle = mathbf0. Finally, the general form of raw moment equations up to m^textth order is obtained by setting h(mathbfn) = mathbfn^mathbfi = n_1^i_1 dotsm n_N^i_N, so that langle h(mathbfn) rangle = mu_mathbfi and mathbfi = sum_j=1^N i_j leq m, leading to ","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\n fracdmu_mathbfidt = sum_j=1^N leftlangle fracpartial mathbfn^mathbfi partial n_j f_j rightrangle + frac12 sum_j=1^N sum_k=1^N leftlangle fracpartial^2 mathbfn^mathbfi partial n_j partial n_k (mathbfGmathbfG^top)_jkrightrangle \nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"The equation for the mean vector mathbfμ = langle mathbfn rangle = (mu_1 dotsc mu_N) take a particularly simple form (as the second derivatives are zero):","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\n fracdmathbfμdt = langle mathbff(mathbfn t) rangle\nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/#central_moment_eqs_SDE","page":"Moment Expansion (SDE)","title":"Central Moment Equations","text":"","category":"section"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"Note that the raw moment expansion formulated above is valid only when the SDE terms mathbff left(mathbfn t right) and mathbfG(mathbfn t) are polynomial functions. If these functions are non-polynomial, we have to consider central moment equations and Taylor expand both mathbff left(mathbfn t right) and mathbfG(mathbfn t) around the mean mathbfμ up to the expansion order q (as done in case of the CME with non-polynomial propensities).","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"The corresponding Taylor expansions can be written down as:","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\n f_j(mathbfn) = sum_mathbfk=0^q frac1mathbfkD^mathbfk f_j(mathbfμ) (mathbfn - mathbfμ)^mathbfk + dotsb \n left( mathbfG(mathbfn) mathbfG(mathbfn)^top right)_jk = sum_mathbfl=0^q frac1mathbfl D^mathbfl left( mathbfG(mathbfμ)mathbfG(mathbfμ)^top right)_jk (mathbfn - mathbfμ)^mathbfl + dotsb \nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"and we remind the reader that we have previously introduced the notation","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\nmathbfk = k_1dotsm k_N \nD^mathbfk f = fracpartial^mathbfkpartial n_1^k_1 dotsm partial n_N^k_N f\n(mathbfn - mathbfμ)^mathbfk = (n_1-mu_1)^k_1 dotsm (n_N-mu_N)^k_N \nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"It follows that the equations for the means can now be written down as:","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\n fracdmu_idt = langle f_i rangle = sum_mathbfj=0^q frac1mathbfj D^mathbfj f_i(mathbfμ) M_mathbfj + dotsb \nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"where M_mathbfj = langle (mathbfn-mathbfμ)^mathbfj rangle are central moments.","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"To obtain the central moment equations, we first perform a change of variables mathbfy = mathbfn - langle mathbfn rangle and note again that dlangle mathbfn rangledt = langle mathbff(mathbfn t) rangle, so that the SDE becomes","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\n dmathbfy = left mathbffleft(mathbfy + langlemathbfnrangle t right) - leftlangle mathbff left(mathbfy + langlemathbfnrangle t right) rightrangle right dt + mathbfGleft(mathbfy + langlemathbfnrangle t right) dmathbfw_t \nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"Then, using Itô's lemma for a smooth function h(mathbfy) and taking the expectation of both sides we find","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\n fracd langle h(mathbfy) rangledt = sum_i=1^N left leftlangle fracpartial h(mathbfy)partial y_i f_i rightrangle - leftlangle fracpartial h(mathbfy)partial y_i rightrangle leftlangle f_i rightrangle right + frac12 sum_i=1^N sum_j=1^N leftlangle fracpartial^2 h(mathbfy)partial y_i partial y_j (mathbfGmathbfG^top)_ijrightrangle \nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"Letting h(mathbfy) = (mathbfn - mathbfμ)^mathbfi and substituting in the needed Taylor expansions we obtain the final form of central moment equations:","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"beginalign*\n fracd M_mathbfidt = sum_j=1^N Bigg leftlangle fracpartial (mathbfn - mathbfμ)^mathbfi partial (n_j - mu_j) sum_mathbfk=0^q-mathbfi+1 frac1mathbfk D^mathbfk f_j(mathbfμ) (mathbfn-mathbfμ)^mathbfk + dotsb rightrangle \n - leftlangle fracpartial (mathbfn-mathbfμ)^mathbfi partial(n_j - μ_j) rightrangle leftlangle sum_mathbfk=0^q frac1mathbfk D^mathbfk f_j(mathbfμ) (mathbfn-mathbfμ)^mathbfk + dotsb rightrangle Bigg \n + frac12 sum_j=1^N sum_k=1^N leftlangle fracpartial^2 (mathbfn-mathbfμ)^mathbfipartial(n_j-mu_j)partial(n_k-mu_k) sum_mathbfl=0^q-mathbfi+2 frac1mathbfl D^mathbfl left( mathbfG(mathbfμ) mathbfG(mathbfμ)^top right)_jk (mathbfn-mathbfμ)^mathbfl + dotsc rightrangle\nendalign*","category":"page"},{"location":"theory/moment_expansion_SDE/#References","page":"Moment Expansion (SDE)","title":"References","text":"","category":"section"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"[1]: K. R. Ghusinga, M. Soltani, A. Lamperski, S. V. Dhople, and A. Singh, \"Approximate moment dynamics for polynomial and trigonometric stochastic systems\", IEEE 56th Annual Conference on Decision and Control (2017). https://doi.org/10.1109/CDC.2017.8263922","category":"page"},{"location":"theory/moment_expansion_SDE/","page":"Moment Expansion (SDE)","title":"Moment Expansion (SDE)","text":"[2]: D. C. C. Bover, \"Moment Equation Methods for Nonlinear Stochastic Systems\", Journal of Mathematical Analysis and Applications 65, 306-320 (1978). https://doi.org/10.1016/0022-247X(78)90182-8","category":"page"},{"location":"theory/moment_expansion_CME/#moment_expansion_CME","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"","category":"section"},{"location":"theory/moment_expansion_CME/#chemical_master_equation","page":"Moment Expansion (CME)","title":"The Chemical Master Equation","text":"","category":"section"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"Consider a chemical reaction network with N different molecular species X_i (i=1 dotsc N) and R chemical reactions, so that the system can be described by [1]:","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign*\n sum_i=1^N s_ij X_i xrightarrowk_j sum_i=1^N r_ij X_i quad j=1dotscR\nendalign*","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"where s_ij and r_ij respectively denote the numbers of reactant and product molecules of species i in the chemical reaction j. The stoichiometric matrix is defined as S_ij = r_ij - s_ij (the net change in the number of molecules of species X_i when the r^textth reaction occurs). The state of the system is determined by the state vector mathbfn=(n_1 dotsc n_N), where n_i is the number of X_i molecules. The time evolution of the probability distribution of mathbfn is described by the Chemical Master Equation (CME)","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginequation\n fracd P(mathbfn t)dt = sum^R_r=1 Big a_r(mathbfn-S_r)P(mathbfn-S_r t) - a_r(mathbfn) P(mathbfn t) Big tag1\nendequation","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"where a_r(mathbfn) is the propensity function of the r^textth reaction and S_r is the r^textth column of the stoichiometric matrix S.","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"Modelling using the CME framework is common in the study of biochemical and gene networks within cells. Although such master equations are rather simple in structure, for most systems there are no known analytical solutions and their stochastic simulations can be very computationally expensive. One possible approach to investigate the system at hand is to approximate the whole probability distribution solution of the CME in terms of its first few moments (e.g. mean and variance).","category":"page"},{"location":"theory/moment_expansion_CME/#raw_moment_eqs","page":"Moment Expansion (CME)","title":"Raw Moment Equations","text":"","category":"section"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"From Eq. (1) we can obtain a system of ordinary differential equations (ODEs) governing the time-evolution of the raw moments of the system up to specified moment expansion order m, given by mu_mathbfi = mu_i_1 dotsc i_N = langle n_1^i_1 dotsm n_N^i_N rangle, where the indices mathbfi=(i_1 dotsc i_N) are restricted such that mathbfi = sum_j=1^N i_j leq m. Note that first order raw moments are simply the means. For example, when N = 3, the mean molecule number of second species in the system is given by mu_2 = mu_0 1 0 = langle n_2 rangle (when N=3). We chose to relax the notation throughout so that the means can be indicated by a single index of the molecular species (used in this section) or by the corresponding one-hot vector (used in the code).","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"To find the first moment equations, we multiply the CME by n_i and sum over all possible states:","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign*\n sum_mathbfn n_i fracdP(mathbfnt)dt = sum_n_1^infty sum_n_2^infty dotsm sum_n_N^infty n_i fracdP(mathbfnt)dt \n = sum_r sum_mathbfn n_i a_r(mathbfn-S_r)P(mathbfn-S_r t) - n_i a_r(mathbfn) P(mathbfn t) \nendalign*","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"Applying a transformation mathbfn-S_r rightarrow mathbfn on the first term in the sum leads to","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign*\n fracdmu_idt = sum_r sum_mathbfn (n_i+S_ir) a_r(mathbfn)P(mathbfn t) - n_i a_r(mathbfn) P(mathbfn t) \n = sum_r sum_mathbfn S_ir a_r(mathbfn) P(mathbfn t) \n = sum_r S_ir langle a_r(mathbfn) rangle tag2\nendalign*","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"The derivation can be extended to the multivariate case of higher order moments mu_mathbfi with mathbfi leq m:","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign*\n fracdmu_mathbfidt = sum_mathbfn n_1^i_1dotsm n_N^i_N fracdP(mathbfn t)dt \n = sum_r sum_mathbfn left (n_1+S_1r)^i_1dotsm (n_N +S_2r)^i_N - n_1^i_1dotsm n_N^i_N right a_r(mathbfn)P(mathbfn t) \n = sum_r sum_mathbfn left sum^i_1_j_1=0 binomi_1j_1 n_1^j_1S_1r^i_1-j_1 dotsm sum^i_N_j_N=0 binomi_Nj_N n_N^j_NS_Nr^ i_N-j_N - n_1^i_1dotsm n_N^i_N right a_r(mathbfn)P(mathbfn t) \n = sum_r sum_mathbfn sum^mathbfi-1_mathbfj=0 binomi_1j_1 dotsm binomi_Nj_N S_1r^i_1-j_1 dotsm S_Nr^ i_N-j_N n_1^j_1 dotsm n_N^j_N a_r(mathbfn)P(mathbfn t) \n = sum_r sum^mathbfi-1_mathbfj=0 binom mathbfi mathbfj S_r^mathbfi-mathbfj langle mathbfn^mathbfj a_r(mathbfn) rangle \nendalign*","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"where we have introduced multi-index notation:","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign\n mathbfi = sum^N_j=1 i_j tag3 \n sum^mathbfi-1_mathbfj=0 = sum_substack0 leq j_1 leq i_1 dotsc 0 leq j_N leq i_N 0 leq j_1+dotsb+j_N leq mathbfi-1 tag4 \n binom mathbfi mathbfj = binomi_1j_1 dotsm binomi_Nj_N tag5 \n mathbfn^mathbfj = n_1^j_1dotsm n_N^j_N tag6 \n S_r^mathbfi-mathbfj = S_1r^ i_1-j_1 dotsm S_Nr^ i_N-j_N tag7\nendalign","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"It is crucial to stress three key points:","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"Throughout all derivations presented in this section we assume that the components of the net stoichiometry matrix S are constant values. However, in certain cases the reaction product may itself be a stochastic variable so that the corresponding expectation values, langle S_r^mathbfi-mathbfj rangle, must be taken into account. We have implemented a limited support for such systems where components of S can be independent geometrically distributed variables, see the specific gene network example.\nGeneration of raw moment equations is only possible if the kinetics of the system at hand are governed by the law of mass action where all propensity functions are polynomials in mathbfn, otherwise the expectation value terms langle a_r(mathbfn) rangle and langle n_i_1^j_1 dotsm n_i_N^j_N a_r(mathbfn) rangle are ill-defined. This key issue can be overcome by the general central moment expansion method presented below.\nThe order of the polynomials a_r(mathbfn) determines the order of moments encountered in the generated system of ODEs. If the system is linear (contains only zeroth and first order reactions), the m^textth order moments will depend only of moments of order m or lower, hence constituting a finite hierarchy of moment ODEs that can be readily solved numerically or otherwise without approximations. However, if the system is non-linear (involves second or higher order reactions), moment equations will depend on higher order moments. For example, if the reaction network contains bimolecular reactions, the corresponding propensity functions will be second order polynomials and hence m^textth order moment equations will now depend on (m+1)^th order moments. This leads to an infinite hierarchy of coupled moment equations where each moment will depend on higher order moments—it cannot be solved directly and needs to be truncated. This can be achieved using one of many moment closure approximations that express (m+1)^textth order moments in terms of m^textth and lower order moments using different distributional assumptions, effectively closing the hierarchy and enabling one to solve the moment equations up to m^textth order [1]. Details of all closure methods currently implemented within the package can be found in the next Theory section.","category":"page"},{"location":"theory/moment_expansion_CME/#central_moment_eqs","page":"Moment Expansion (CME)","title":"Central Moment Equations","text":"","category":"section"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"As we have seen, the moment equations of P(mathbfn t) can be obtained in a straightforward manner if the kinetics of the system are governed by the law of mass action where all propensity functions are polynomials in mathbfn [1]. Similarly, given all propensities are rational functions, a polynomial form can also be recovered [2]. However, problems arise when the propensities take more complicated non-polynomial functions. This can nevertheless be overcome by considering a more general method of moment expansion that enables us to obtain mean and central moment equations up to arbitrary order for virtually any chemical reaction network with any type of smooth (infinitely differentiable) propensity functions. Such framework was first independently formulated by Lee [3] and Ale et al. [4]—our derivation below closely follows these works.","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"We start by Taylor-expanding the propensity functions around the mean mathbfμ = langle mathbfn rangle = (mu_1 dotsc mu_N). This allows us to consider any general propensity function under the assumption that it is infinitely differentiable (smooth). The expansion leads to","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign*\n a_r(mathbfn) = a_r(mathbfμ) + sum_j_1^N fracpartial a_r(mathbfμ)partial n_j_1(n_j_1-mu_j_1) \n + frac12sum_j_1 j_2 fracpartial^2 a_r(mathbfμ)partial n_j_1 partial n_j_2 (n_j_1-mu_j_1) (n_j_2-mu_j_2) + dotsb \n + frac1q sum_j_1 j_2 dotsc j_q fracpartial^q a_r(mathbfμ)partial n_j_1 partial n_j_2dotsmpartial n_j_q (n_j_1-mu_j_1) (n_j_2-mu_j_2) dotsm(n_j_q - mu_j_q) + dotsb \n = sum_mathbfj=0^q frac1mathbfj D^mathbfj a_r(mathbfμ) (mathbfn - mathbfμ)^mathbfj + dotsb \nendalign*","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"where q controls the expansion order and we have simplified the expression by using Eqs. (3-7) in addition to:","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign*\nmathbfj = j_1dotsm j_N \nD^mathbfj f = fracpartial^mathbfjpartial n_1^j_1 dotsm partial n_N^j_N f \nendalign*","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"Now we can obtain equations governing the time-evolution of the means μ_i and the central moments M_mathbfi = M_i_1 dotsc i_N = langle (n_1 - mu_1)^i_1dotsm(n_N - mu_N)^i_N rangle, where again mathbfi leq m. We first consider the equations for the means immediately starting from Eq. (2):","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign*\n fracdmu_idt = sum_r S_ir langle a_r(mathbfn) rangle \n = sum_r S_ir Big( sum_mathbfj=0^q frac1mathbfj D^ mathbfj a_r(mathbfμ) langle (mathbfn - mathbfμ)^mathbfj rangle + dotsb Big) \n = sum_r S_ir Big( sum_mathbfj=0^q frac1mathbfj D^ mathbfj a_r(mathbfμ) M_mathbfj + dotsb Big) \nendalign*","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"We can now derive the equations for central moments by taking the time derivative of M_mathbfi and using Eq. (1):","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign*\n fracdM_mathbfidt = sum_mathbfn (n_1 - mu_1)^i_1dotsm(n_N - mu_N)^i_N fracdP(mathbfn t)dt \n - sum_mathbfn sum_j=1^N i_j fracdmu_jdt (n_1-mu_1)^i_1 dotsm(n_j-mu_j)^i_j-1dotsm(n_N-mu_N)^i_NP(mathbfn t) \n = sum_r sum_mathbfn Big (n_1 - mu_1 + S_1r)^i_1 dotsm (n_N-mu_N+S_Nr)^i_N \n - (n_1-mu_1)^i_1dotsm(n_N-mu_N)^i_N Biga_r(mathbfn)P(mathbfn t) - sum_j i_j fracdmu_jdtM_i_1dotsci_j-1dotsc i_N \n = sum_r sum_mathbfn Bigg sum_mathbfj=0^mathbfi-1 binomi_1j_1 dotsm binomi_Nj_N S_1r^ i_1-j_1 dotsm S_Nr^ i_N-j_N(n_1-mu_1)^j_1dotsm(n_N-mu_N)^j_NBigg \n times Bigg sum_mathbfj=0^q frac1mathbfj D^mathbfj a_r(mathbfμ) (mathbfn - mathbfμ)^mathbfj + dotsb Bigg-sum_j i_j fracdmu_jdt M_mathbfi_j- \n = sum_r sum_mathbfj=0^mathbfi-1 Bigg binomi_1j_1 dotsm binomi_Nj_N S_1r^ i_1-j_1 dotsm S_Nr^ i_N-j_N sum_mathbfk=0^q-mathbfj frac1mathbfkD^mathbfk a_r(mathbfμ) M_mathbfj+mathbfk + dotsb Bigg - sum_j i_j fracdmu_jdt M_mathbfi_j- \n = sum_r sum_mathbfj=0^mathbfi-1 Bigg binommathbfimathbfj S_r^mathbfi-mathbfj sum_mathbfk=0^q-mathbfj frac1mathbfkD^mathbfk a_r(mathbfμ) M_mathbfj+mathbfk + dotsb Bigg - sum_j i_j fracdmu_jdt M_mathbfi_j- \nendalign*","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"where we have also defined","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"beginalign*\n M_mathbfi_j-=M_i_1dotsci_j-1dotsc i_N \n M_mathbfj+mathbfk = M_j_1+k_1dotscj_N+k_N \nendalign*","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"Although raw moment equations for non-linear mass-action systems already require approximate treatment using moment closure, here we have an additional complication: if a system contains non-polynomial propensity functions, the equations for both means and central moments will in principle depend on an infinite number of higher order central moments. Hence the Taylor expansion order q is of utmost importance as it controls the degree of approximation: the propensity functions are expanded up to q^textth order so that m^textth central moment equations will depend on central moments of order qm and lower. Finally, moment closure approximations can be applied similarly as in the case of raw moment equations.","category":"page"},{"location":"theory/moment_expansion_CME/#References","page":"Moment Expansion (CME)","title":"References","text":"","category":"section"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"[1]: D. Schnoerr, G. Sanguinetti, and R. Grima, \"Approximation and inference methods for stochastic biochemical kinetics - a tutorial review\", Journal of Physics A: Mathematical and Theoretical 50, 093001 (2017). https://doi.org/10.1088/1751-8121/aa54d9","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"[2]: P. Milner, C. S. Gillespie, and D. J. Wilkinson, \"Moment closure approximations for stochastic kinetic models with rational rate laws\", Mathematical Biosciences 231, 99-104 (2011). https://doi.org/10.1016/j.mbs.2011.02.006","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"[3]: A. Ale, P. Kirk, and M. P. H. Stumpf, \"A general moment expansion method for stochastic kinetic models\", The Journal of Chemical Physics 138, 174101 (2013). https://doi.org/10.1063/1.4802475","category":"page"},{"location":"theory/moment_expansion_CME/","page":"Moment Expansion (CME)","title":"Moment Expansion (CME)","text":"[4]: C. H. Lee, \"A Moment Closure Method for Stochastic Chemical Reaction Networks with General Kinetics\", MATCH Communications in Mathematical and in Computer Chemistry 70, 785-800 (2013). https://match.pmf.kg.ac.rs/electronicversions/Match70/n3/match70n3785-800.pdf","category":"page"},{"location":"theory/moment_closure_approximations/#moment_closure_approximations","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"In the previous section, we have shown that for a non-linear system an infinite hierarchy of coupled moment equations is obtained that cannot be solved directly and, therefore, needs to be truncated in an approximate way. This can be achieved using moment closure approximations (MAs), in which all moments above a certain order m are expressed in terms of m^textth and lower order moments using various (usually distributional) assumptions [1]. Doing so enables us to effectively close the moment hierarchy, leading to a finite set of ODEs which can then be solved numerically. In this section, we present some the commonly used MA methods that are implemented in MomentClosure. Please see the Tutorials section for examples showing different MAs applied to a variety of systems.","category":"page"},{"location":"theory/moment_closure_approximations/#zero_closure","page":"Moment Closure Approximations","title":"Zero Closure","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"The simplest MA is the \"central-moment-neglect\" MA (CMN-MA) [2], also referred to as \"zero-closure\" [3] or \"low dispersion moment closure\" [4], where CMN-MA at m^textth order means that the moment equations are truncated by setting all central moments above order m to zero. For example, in the simple case of 2nd order truncation, the moment equations for the means mu_i and covariances C_ij become:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n fracd mu_idt = sum_r S_ir Big( a_r(mathbfμ) + frac12sum_i_1 i_2 fracpartial^2 a_r(mathbfμ)partial n_i_1 partial n_i_2 M_i_1 i_2 Big) \n fracdC_ijdt = fracdM_mathbf0_i+ j+dt \n = fracdlangle (n_i-mu_i) (n_j-mu_j) rangledt = \n = sum_r Big S_ir sum_k fracpartial a_r(mathbfμ)partial n_k C_jk + S_jr sum_k fracpartial a_r(mathbfμ)partial n_k C_ik \n + S_irS_jr Big( a_r(mathbfμ) + frac12 sum_k l fracpartial^2 a_r(mathbfμ)partial n_k partial n_l C_kl Big) Big \nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/#normal_closure","page":"Moment Closure Approximations","title":"Normal Closure","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Another popular MA is the \"normal moment-closure\", pioneered by Goodman [5] and Whittle [6], where all cumulants kappa_mathbfi above order m are set to zero, approximating the probability distribution of the system with the normal distribution [2]:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n kappa_mathbfi = 0 quad textfor mathbfi m\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"In order to truncate the higher order central or raw moments M_mathbfi using normal closure we express them in terms of cumulants kappa_mathbfi using the multivariate moment and cumulant relationships formalised by Balakrishnan et al. [7].","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Note that a different implementation of normal closure can be found in literature [3], where the higher order central moments are expressed in terms of a sum of product of covariances using Isserlis' theorem. However, one could argue that such formulation is not advisable as it assumes stronger \"Gaussianity\" of the underlying distribution than setting the higher order cumulants to zero which is less of an approximation on the form of the distribution and hence is preferable in the development of MAs. For example, in case we are truncating the moment equations at 4th order, the truncation-order central moments would be expressed only in terms of covariances whereas our formulation using cumulants would explicitly include information about the computed values of third central moments, which is expected to improve numerical stability and lead to more accurate moment estimates.","category":"page"},{"location":"theory/moment_closure_approximations/#poisson_closure","page":"Moment Closure Approximations","title":"Poisson Closure","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Although the Poisson distribution lacks a general formulation for multiple variables [3], \"Poisson MA\" has been formulated [2, 8] assuming that the joint multivariate distribution is a product of univariate Poisson distributions, i.e., n_i sim textPoisson(mu_i). The cumulants of a univariate Poisson distribution are equal to the mean, hence in Poisson closure we set all higher order diagonal cumulants to the corresponding mean values and mixed cumulants to zero [2], which in our notation can be expressed as:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n kappa_mathbfi = mu_j quad textif i_j m textand i_jneq k = 0 quad textfor some j k in 1dotscN \n kappa_mathbfi = 0 quad textif mathbfi m textand i_j neq i_k (textwhere i_j neq 0 i_k neq 0) quad textfor some j k in 1dotscN\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Similarly to normal closure, the higher order central/raw moments can be expressed in terms of cumulants as described in [7].","category":"page"},{"location":"theory/moment_closure_approximations/#log-normal_closure","page":"Moment Closure Approximations","title":"Log-normal Closure","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"\"Log-normal\" MA, first applied by Keeling [9], allows one to truncate the moment equations under the assumption that the distribution of the underlying stochastic process is log-normal. A positive multi-dimensional random variable mathbfn follows a log-normal distribution if its logarithm is normally distributed, so that mathbfy = ln mathbfn, and mathbfy sim mathcalN(mathbfnu Sigma), where mathbfnu and Sigma denote the vector of means and the covariance matrix respectively. By considering the moment generating function of the normal distribution, mathcalN(mathbfnu Sigma), one can show that the raw moments are given by [3, 10]:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n mu_mathbfi = expleft(mathbfi^topmathbfnu + frac12mathbfi^topSigmamathbfiright)\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"It follows that","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n nu_i = ln mu_i - frac12 Sigma_ii \n Sigma_ij = ln left( 1 + fraclangle (n_i - mu_i)(n_j - mu_j) rangleexp left( nu_i + nu_j + frac12 left( Sigma_ii + Sigma_jj right) right) right) \n = ln left( 1 + fracC_ijexp left( nu_i + nu_j + frac12 left( Sigma_ii + Sigma_jj right) right) right) \n Sigma_ii = ln left( 1 + fracC_iimu_i^2 right) \nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Note that central moments can be obtained from raw moments by utilising their general multivariate relationship [11].","category":"page"},{"location":"theory/moment_closure_approximations/#gamma_closure","page":"Moment Closure Approximations","title":"Gamma Closure","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"The method of \"gamma closure\" was originally implemented by Lakatos et al. [3], where the authors acknowledged the ambiguity arising in defining multivariate gamma distributions, and, building upon previous definitions in the literature (e.g. [12] and [13]), proposed a new formulation of a multivariate gamma distribution. Here we reproduce the definition by closely following the description in [3] and elucidating some of the derivation steps.","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"We denote a random variable drawn from gamma distribution with shape alpha and scale beta as n sim textGamma(alpha beta). The probability density function of the univariate gamma distribution with the corresponding shape-scale parameterisation is","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n f(n alpha beta) = frac1Gamma(alpha)beta^alpha n^alpha-1e^-fracnbeta\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"where Gamma is the gamma function. The i^textth raw moment of n is given by","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n μ_i = fracGamma(alpha+i)beta^iGamma(alpha) = (alpha)_i beta^i taga\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"where (alpha)_i = alpha (alpha+1) dotsm (alpha+i-1). Note that the moment generating function of X is","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n G_n(k) = langle e^kn rangle = left( 1 - beta k right)^-alpha\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"In order to construct a multivariate gamma distribution, we start by considering independent gamma variables Y_kl, k l = 1 dotsc N, with shape and scale parameters alpha_kl and beta_kl respectively. Here we define Y_kl to be symmetric in indices, i.e., Y_kl = Y_lk. Now consider an N-dimensional random vector mathbfn = left( n_1 n_2 dotsc n_N right), where n_i is a linear combination of independent gamma variables:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n n_i = sum_j=1^N fracbeta_iibeta_ij Y_ij\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"The i^textth marginal moment generating function of the joint distribution of mathbfn is given by:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n G_n_i(k_i) = leftlangle e^k_i sum_j=1^N fracbeta_iibeta_ij rightrangle \n = G_Y_i1left(k_i fracbeta_iibeta_i1 right) G_Y_i2left(k_i fracbeta_iibeta_i2 right) dotsm G_Y_iNleft(k_i fracbeta_iibeta_iN right) \n = left(1-beta_ii k_i right)^sum_j=1^N alpha_ij\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"so that n_i sim textGamma(alpha_i beta_i), where alpha_i = sum_j=1^N alpha_ij and beta_i = beta_ii. Therefore, we have obtained an N-variate gamma distribution, which can be denoted as mathbfn sim MG(mathbfalpha mathbfbeta), where the vectors of shape and scale parameters are given by mathbfalpha = left( alpha_1 dotsc alpha_N right) and mathbfbeta = left( beta_1 beta_2 dotsc beta_N right) respectively.","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"We can now readily obtain the raw m^textth order moment of n_i:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n langle n_i^m rangle = leftlangle left( sum_j=1^N fracbeta_iibeta_ij Y_ij right)^m rightrangle \n = leftlangle sum_k_1+k_2+dotsb+k_N = m fracmk_1k_2 dotsm k_N prod_j=1^N left( fracbeta_iibeta_ij Y_ij right)^k_j rightrangle \n = sum_mathbfk=m fracmmathbfk prod_j=1^N leftlangle left( fracbeta_iibeta_ij Y_ij right)^k_j rightrangle \n = beta_i^m sum_mathbfk=m fracmmathbfk left(\n prod_j=1^N left( alpha_ij right)_k_j right)\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Note that we have used Eq. (a) to get to the last line. The mixed raw moments are computed in a similar fashion:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n mu_mathbfi = leftlangle left( sum_j=1^N fracbeta_11beta_1jY_1j right)^i_1 dotsm left( sum_j=1^N fracbeta_NNbeta_NjY_Nj right)^i_N rightrangle \n = mathbfbeta^mathbfi leftlangle sum_mathbfk_1=i_1 dotsm sum_mathbfk_N=i_N fracmathbfimathbfk_1dotsmmathbfk_N prod_j=1^N left( fracY_1jbeta_1j right)^k_1_j dotsm prod_j=1^N left( fracY_Njbeta_Nj right)^k_N_j rightrangle \n = mathbfbeta^mathbfi leftlangle sum_mathbfk_1=i_1 dotsm sum_mathbfk_N=i_N fracmathbfimathbfk_1dotsmmathbfk_N prod_q=1^N left( fracY_qqbeta_qq right)^k_q_q prod_r=q+1^N left( fracY_qrbeta_qr right)^k_q_r + k_r_q rightrangle \n = mathbfbeta^mathbfi sum_mathbfk_1=i_1 dotsm sum_mathbfk_N=i_N fracmathbfimathbfk_1dotsmmathbfk_N prod_q=1^N left( alpha_qq right)_k_q_q prod_r=q+1^N left( alpha_qr right)_k_q_r + k_r_q\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"where we have taken into account the symmetry in indices and defined each mathbfk_i as an N-dimensional vector mathbfk_i = left( k_i_1 dotsc k_i_N right) and mathbfbeta^mathbfi = beta_1^i_1 dotsm beta_N^i_N. Note that the mean and variance of n_i can be obtained from:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n mu_i = sum_j=1^N alpha_ij beta_i tagb \n C_ii = (alpha_i)_2 beta_i^2 - alpha_i^2beta_i^2 \n = sum_j=1^N alpha_ij beta_i^2\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Similarly, from Eq. (a) it follows that","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n langle n_i n_j rangle = beta_i beta_j left( sum_substackk l (k l) neq (j i)^N alpha_ik alpha_jl + (alpha_ij)_2 right)\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"which together with Eq. (b) allows us to express the covariance as:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n C_ij = langle n_i n_j rangle - beta_i beta_j left( sum_kl alpha_ik alpha_jl right) \n = alpha_ij beta_i beta_j\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Finally, from the equations above we can obtain all shape and scale parameters:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n beta_i = fracC_iimu_i \n alpha_ij = fracC_ijbeta_i beta_j \n alpha_ii = fracmu_ibeta_i - sum_substackk k neq i alpha_ik\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/#derivative_matching","page":"Moment Closure Approximations","title":"Derivative Matching","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"The derivative matching MA [14, 15] is based on expressing moments above order m in terms of lower order moments in such a way that their time derivatives match those of the exact moments at some initial time and initial conditions. We outline the approach below, closely following the complete exposition found in the original papers of Singh and Hespanha [14, 15].","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"The raw moment equations up to order m for any mass-action reaction network containing at most bimolecular (second order) reactions can be written down concisely in the matrix form:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n fracdmathbfμdt = hatmathbfa + Amathbfμ + B barmathbfμ \nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"where mathbfμ is a vector containing all raw moments of the system up to order m and barmathbfμ consists of all (m+1)^textth order raw moments which the equations depend on. The constant vector hatmathbfa and constant matrices A and B are chosen appropriately for the system at hand. In this case, an MA can be defined as a procedure where each moment in barmathbfμ, barμ_mathbfi, is approximated by a moment closure function varphi_mathbfi (mathbfμ) of moments up to order m. Then the moment equations can be rewritten as","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":" fracdmathbfνdt = hatmathbfa + Amathbfν + Bbarmathbfφ(mathbfν) ","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"where the state of the system is now denoted by mathbfν instead of mathbfμ, stressing the fact that we are considering the approximation of the true moment dynamics, and barmathbfφ(mathbfν) is the corresponding vector of moment closure functions.","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"The idea behind derivative matching is to determine a map barmathbfφ so that the time derivatives between the exact moments, mathbfμ(t), and the approximate moments, mathbfν(t), would match at some initial time t_0 under the initial condition mathbfμ(t_0) = mathbfν(t_0):","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n left fracd^i mathbfμdt rightrvert_t=t_0 = left fracd^i mathbfνdt rightrvert_t=t_0\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"If these conditions hold, one can expect from a Taylor series approximation argument that mathbfμ(t) and mathbfν(t) will stay close at least locally in time and hence the MA will be sufficiently accurate.","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"In order to move forward, Singh and Hespanha present what can be understood as essentially an ansatz. Firstly, moment closure functions for each mathbfi, where mathbfi m, are chosen to have a separable form given by","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n φ_mathbfi(mathbfμ) = prod_substack1 leq j_1+dotsb+j_N leq m left( μ_mathbfj right)^γ_mathbfj = prod_mathbfj=1^m left( μ_mathbfj right)^γ_mathbfj \nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"where γ_mathbfj are constants (unique for each vector mathbfi) that can be determined by solving the following linear equation system:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n C^mathbfi_mathbfj = sum_mathbfk=1^m gamma_mathbfk C^mathbfk_mathbfj quad textfor each mathbfj textwhere mathbfjleq m \nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"were we have introduced multi-index scalars","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n C^mathbfu_mathbfv = C^u_1_v_1C^u_2_v_2 dotsm C^u_N_v_N\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"with each element defined as","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\nC^a_b =\nbegincases\n fraca(a-b)b a geq b \n 0 a lt b\nendcases\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Using the specific construction of barmathbfφ described above, it can be shown [15] that for every deterministic initial condition, i.e., mathbfn(t_0) = mathbfn_0 with probability one, we will have","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n mathbfμ(t_0) = mathbfν(t_0) implies left fracd mathbfμdt rightrvert_t=t_0 = left fracd mathbfνdt rightrvert_t=t_0 \n implies left fracd^2mathbfμdt^2 rightrvert_t=t_0 = left fracd^2 mathbfνdt^2 rightrvert_t=t_0 + mathbfϵ(mathbfn_0) \nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"where all elements of mathbfϵ(mathbfn_0) are zero except the ones corresponding to m^textth order raw moments—these elements are second order polynomials in mathbfn_0. Note, however, that these results hold only for mass-action systems containing no higher than second order chemical reactions. While the derivative matching MA can be applied in the same way to systems containing higher order polynomial and non-polynomial propensity functions, it has not been rigorously analysed in such scenarios, where, naturally, we expect significantly larger approximation errors.","category":"page"},{"location":"theory/moment_closure_approximations/#conditional_closures","page":"Moment Closure Approximations","title":"Conditional Closures","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"As standard MAs often fail to provide sufficiently accurate approximations of chemical reaction networks involving both high- and low-abundance species, some novel approaches suggest using moments conditioned on the low-copy number species, which can lead to a more effective description of the system dynamics [1, 16]. Here we discuss the conditional moment closure proposed by Soltani et al. (2015) [16], applicable to networks containing molecular species which copy number can be either zero or one, i.e., a binary/Bernoulli random variable. Such conditional MA can be very useful in the study of gene networks where two-state gene systems are often considered—the gene state itself can be treated as a distinct species which molecule number is a Bernoulli variable.","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"The conditional MA is based on conditioning the higher order moments of high-abundance species on the binary species being in state 1 (instead of 0) and then applying standard MAs on the conditional moments. Closely following Soltani et al. [16], we use a two-state gene circuit to illustrate the conditional MAs, denoting the binary gene state by g and the protein number (high-abundance species) by p. Firstly, note that as g is a Bernoulli variable the following identities hold","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\nlangle g^j p rangle = langle g rangle quad j in 2 3 dotsc \nlangle g^j p^k rangle = langle g p^k rangle quad jk in 1 2 3 dotsc\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Therefore, we only need to concern ourselves with moments of the form langle p^k rangle and langle gp^k rangle. The former can be approximated using the standard MAs (no conditioning needed), whereas the latter can be written down as:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\nlangle gp^j rangle = langle p^j g=1 rangle langle g rangle quad jin 12 dotsc\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Now the conditional moment langle p^j g= 1 rangle can be expressed in terms of lower order conditional moments using one of the standard MAs, e.g., normal closure or derivative matching—the two methods (including the conditioning step) are respectively known as the conditional gaussian and conditional derivative matching MAs. For completeness, we show how the two methods are applied to approximate a specific higher order moment:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n langle gp^3 rangle = langle p^3 g=1 rangle langle g rangle\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/#conditional_gaussian_closure","page":"Moment Closure Approximations","title":"Conditional Gaussian Closure","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Under the conditional Gaussian MA, we assume that the number of protein molecules conditioned on the gene being active, p g = 1, follows a Gaussian distribution. In other words, we apply normal MA on the conditional moment langle p^j g=1 rangle. Hence we obtain (following the example above):","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\nlangle p^3 g= 1 rangle = 3 langle p^2 g = 1 rangle langle p g=1 rangle - 2 langle p g=1 rangle^3\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Using langle gp^j rangle = langle p^j g=1 rangle langle g rangle, we can rewrite the equation as:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\nlangle p^3 g= 1 rangle = 3 fraclangle gp^2 rangle langle gp ranglelangle g rangle^2 - 2 fraclangle gp rangle^3langle g rangle^3\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Plugging this into the previous expression of the higher-order moment langle gp^3 rangle we finally obtain:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\n langle gp^3 rangle = 3 fraclangle gp^2 rangle langle gp ranglelangle g rangle - 2 fraclangle gp rangle^3langle g rangle^2\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/#conditional_derivative_matching","page":"Moment Closure Approximations","title":"Conditional Derivative Matching","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"The conditional derivative matching boils down to approximating the higher order conditional moments in terms of lower order conditional moments using the standard derivative matching:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\nlangle p^3 g = 1 rangle = fraclangle p^2 g = 1 rangle^3langle p g= 1 rangle^3\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Using langle gp^j rangle = langle p^j g=1 rangle langle g rangle again, we find:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\nlangle gp^3 rangle = fraclangle gp^2 rangle^3 langle g ranglelangle gp rangle^3\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Note that conditional moment closure is fully applicable to systems containing multiple binary species. For example, given two two-state genes, g_1 and g_2, the same Bernoulli variable properties hold and the higher-order moments can be expressed as:","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"beginalign*\nlangle g_1 g_2 p^j rangle = langle p^j g_1 = g_2 = 1 rangle langle g_1 g_2 rangle quad j in 12dotsc\nendalign*","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Such higher order conditional moments can again be closed using normal closure or derivative matching.","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"Note that the description here is taken from [16] and we urge the reader to see the paper for more details. In addition, we have used MomentClosure to apply conditional closures on genetic feedback loops and reproduce some of the published results in this example.","category":"page"},{"location":"theory/moment_closure_approximations/#References","page":"Moment Closure Approximations","title":"References","text":"","category":"section"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[1]: D. Schnoerr, G. Sanguinetti, and R. Grima, \"Approximation and inference methods for stochastic biochemical kinetics - a tutorial review\", Journal of Physics A: Mathematical and Theoretical 50, 093001 (2017). https://doi.org/10.1088/1751-8121/aa54d9","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[2]: D. Schnoerr, G. Sanguinetti, and R. Grima, \"Comparison of different moment-closure approximations for stochastic chemical kinetics\", The Journal of Chemical Physics 143, 185101 (2015). https://doi.org/10.1063/1.4934990","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[3]: E. Lakatos, A. Ale, P. D. W. Kirk, and M. P. H. Stumpf, \"Multivariate moment closure techniques for stochastic kinetic models\", The Journal of Chemical Physics 143, 094107 (2015). https://doi.org/10.1063/1.4929837","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[4]: J. Hespanha, \"Moment closure for biochemical networks\", in 2008 3rd International Symposium on Communications, Control and Signal Processing (Mar. 2008), pp. 142–147. https://doi.org/10.1109/ISCCSP.2008.4537208","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[5]: L. A. Goodman, \"Population Growth of the Sexes\", Biometrics 9, Publisher: [Wiley, International Biometric Society], 212–225 (1953). https://doi.org/10.2307/3001852","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[6]: P. Whittle, \"On the use of the normal approximation in the treatment of stochastic processes\", Journal of the Royal Statistical Society: Series B (Methodological) 19, 268–281 (1957). https://doi.org/10.1111/j.2517-6161.1957.tb00263.x","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[7]: N. Balakrishnan, N. L. Johnson, and S. Kotz, “A note on relationships between moments, central moments and cumulants from multivariate distributions”, Statistics & Probability Letters 39, 49–54 (1998). https://doi.org/10.1016/S0167-7152(98)00027-3","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[8]: I. Nasell, \"An extension of the moment closure method\", Theoretical Population Biology 64, 233–239 (2003). https://doi.org/10.1016/S0040-5809(03)00074-1","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[9]: M. J. Keeling, \"Multiplicative Moments and Measures of Persistence in Ecology\", Journal of Theoretical Biology 205, 269–281 (2000). https://doi.org/10.1006/jtbi.2000.2066","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[10]: E. L. Crow and K. Shimizu, eds., Lognormal Distributions: Theory and Applications (Marcel Dekker, 1988).","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[11]: N. L. Johnson, S. Kotz, and N. Balakrishnan, Discrete Multivariate Distributions (Wiley, Feb. 1997).","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[12]: A. M. Mathal and P. G. Moschopoulos, \"A form of multivariate gamma distribution\", Annals of the Institute of Statistical Mathematics 44, 97–106 (1992). https://doi.org/10.1007/BF00048672","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[13]: E. Furman, \"On a multivariate gamma distribution\", Statistics & Probability Letters 78, 2353–2360 (2008). https://doi.org/10.1016/j.spl.2008.02.012","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[14]: A. Singh and J. P. Hespanha, \"Lognormal Moment Closures for Biochemical Reactions\", in Proceedings of the 45th IEEE Conference on Decision and Control, ISSN:0191-2216 (Dec. 2006), pp. 2063–2068. https://doi.org/10.1109/CDC.2006.376994","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[15]: A. Singh and J. P. Hespanha, \"Approximate Moment Dynamics for Chemically Reacting Systems\", IEEE Transactions on Automatic Control 56, 414–418 (2011). https://doi.org/10.1109/TAC.2010.2088631","category":"page"},{"location":"theory/moment_closure_approximations/","page":"Moment Closure Approximations","title":"Moment Closure Approximations","text":"[16]: M. Soltani, C. A. Vargas-Garcia, and A. Singh, \"Conditional Moment Closure Schemes for Studying Stochastic Dynamics of Genetic Circuits\", IEEE Transactions on Biomedical Circuits and Systems 9, 518–526 (2015). https://doi.org/10.1109/tbcas.2015.2453158","category":"page"},{"location":"tutorials/LMA_example/#linear_mapping_approximation_example","page":"LMA Example","title":"LMA Example","text":"","category":"section"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"In this example, we demonstrate how the Linear Mapping Approximation (LMA) can be applied on chemical reaction networks using MomentClosure. We illustrate the approach on models of a simple nonlinear feedback loop and a genetic toggle switch, in turn reproducing some of the results published in the original LMA paper by Cao and Grima [1].","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"We start by considering a simple nonlinear gene regulatory network (GRN) shown in the diagram below (adapted from [1]):","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"⠀","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"Here we have a two-state gene promoter which can be in either state G or G^*. As in a previous example tutorial, we interpret the gene as a distinct species modelled as a Bernoulli variable g, associating the states G and G^* with values g=1 and g=0 respectively. Protein P is produced from both gene states G and G^* (with different rates ρ_u and ρ_b) and can subsequently decay. The switch between G and G^* (or the feedback) is introduced via protein binding to the gene in state G.","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"The first step in applying the LMA is to transform the nonlinear GRN into a linear GRN. This can be done by removing the second-order reaction between P and G, so that the reversible reaction G+P undersetσ_ustackrelσ_brightleftharpoons G^* is replaced by G undersetσ_ustackrelbarσ_brightleftharpoons G^*. This equivalent linear GRN can be visualised as (adapted from [1]):","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"⠀","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"Note that MomentClosure cannot automate this linearisation step as the choice of how the other reactions in the network are changed due to the removal of nonlinear reactions is arbitrary. For this reason, we define both nonlinear and linear GRNs using Catalyst as follows:","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"using Catalyst\n\n# NOTE: both models MUST preserve the same ordering of reactions in order to detect\n# how the nonlinear reactions are to be transformed using LMA\n\nrn_nonlinear = @reaction_network begin\n @parameters σ_b σ_u ρ_b ρ_u\n σ_b, g + p → 0\n σ_u*(1-g), 0 ⇒ g + p\n ρ_u, g → g + p\n ρ_b*(1-g), 0 ⇒ p\n 1, p → 0\nend \n\nrn_linear = @reaction_network begin\n @parameters σ_b_LMA σ_u ρ_b ρ_u\n σ_b_LMA, g → 0 # typing ̄σ_b is not allowed it seems\n σ_u*(1-g), 0 ⇒ g\n ρ_u, g → g+p\n (ρ_b*(1-g)), 0 ⇒ p\n 1, p → 0\nend ","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"We can now apply the LMA to find the effective parameter barσ_b and generate the corresponding moment equations of the linear GRN using MomentClosure's linear_mapping_approximation:","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"using MomentClosure\n\n# NOTE: we have to provide the indices of binary variables in the system as they are ordered in the *nonlinear* GRN.\n# The distinction here between linear and nonlinear GRNs is important as in some cases the internal ordering of variables of the two Catalyst models can differ\n@parameters t\n@variables g(t)\nbinary_vars = [speciesmap(rn_nonlinear)[g]]\n\nLMA_eqs, effective_params = linear_mapping_approximation(rn_nonlinear, rn_linear, binary_vars, combinatoric_ratelaws=false)\ndisplay(effective_params)","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"OrderedDict{Any, Any} with 1 entry:\n σ_b_LMA => σ_b*μ₁₁(t)*(μ₁₀(t)^-1)","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"We can also print out the moment equations:","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"using Latexify\nlatexify(LMA_eqs)","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"beginalign*\nfracdmu_10dt = sigma_u - sigma_b mu_11 - sigma_u mu_10 \nfracdmu_01dt = rho_b + rho_u mu_10 - mu_01 - rho_b mu_10 \nfracdmu_11dt = rho_u mu_10 + sigma_u mu_01 - mu_11 - sigma_u mu_11 - sigma_b mu_10^-1 mu_11^2 \nfracdmu_02dt = rho_b + rho_u mu_10 + 2 rho_b mu_01 + 2 rho_u mu_11 + mu_01 - 2 mu_02 - rho_b mu_10 - 2 rho_b mu_11\nendalign*","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"Note that the results agree with Eqs. (1) and (2) (after a corresponding substitution) given in [1]. The moment equations are already closed, so we can solve them numerically and plot the mean protein number over time:","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"using OrdinaryDiffEq, Sundials, Plots\n\n# [g, p] as in `species(rn_nonlinear)`\nu₀ = [1.0, 0.001]\np = [0.004, 0.25, 25.0, 60.0]\ntspan = (0., 15.)\ndt = 0.1\n\nu₀map = deterministic_IC(u₀, LMA_eqs)\noprob_LMA = ODEProblem(LMA_eqs, u₀map, tspan, p)\nsol_LMA = solve(oprob_LMA, CVODE_BDF(), saveat=dt)\n\nplot(sol_LMA, idxs=[2], label=\"LMA\", ylabel=\"⟨p⟩\", xlabel=\"time\", fmt=\"svg\")","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"(Image: LMA feedback loop mean protein number)","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"To compare the LMA result to the true moment dynamics we use the Finite State Projection (FSP) algorithm implemented in FiniteStateProjection.jl. FSP can be much more efficient than SSA in accurately approximating the full time-dependent probability distribution of the given chemical system when the system's state space is small (hence it is particularly effective for the nonlinear GRN here). Having obtained the FSP solution, we can extract the time-evolution of moments using get_moments_FSP function and finally compare it to the LMA prediction. This can all be done as follows:","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"using FiniteStateProjection\n\nfsp_sys = FSPSystem(rn_nonlinear, combinatoric_ratelaw=false)\n# Truncate the state space of the system\n# The gene has two states (G or G*) whereas we consider protein number from 0 to 100\nstate_space = [2, 101]\n\n# The initial condition is the matrix of probabilities representing the state of the system\n# We assume zero protein and the gene to be in the state G, hence the probability of this\n# specific state should be set to 1 initially\nu0 = zeros(state_space...)\nu0[2, 1] = 1.0\n\n# construct an ODE problem from the FSPSystem and solve it\nfsp_prob = ODEProblem(fsp_sys, u0, tspan, p)\nsol_FSP = solve(fsp_prob, CVODE_BDF(), saveat=dt)\n\n# extract the 1st order raw moments from the FSP solution\nμ_FSP = get_moments_FSP(sol_FSP, 1, \"raw\")\nplot!(sol_FSP.t, μ_FSP[(0,1)], label=\"FSP\", legend=:bottomright)","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"(Image: LMA and FSP feedback loop mean protein number)","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"Using the LMA as implemented in MomentClosure, we can generate and solve the closed moment equations for any LMA-suitable nonlinear chemical reaction network, given that its linear equivalent is also provided. Proceeding further to obtain an approximate time-dependent probability distribution of the nonlinear network is more involved as only a handful of closed-form solutions of linear networks are known. Moreover, simply computing the solutions can be a challenge due to their complicated analytical form. For these reasons, MomentClosure does not provide an automated approach to computing the probability distributions of the relevant nonlinear systems using LMA—these steps have to performed manually on a case-by-case basis. Nevertheless, below we demonstrate how this could be done for the nonlinear GRN we have been considering so far.","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"The CME of the nonlinear feedback loop can be solved exactly as described in [1] and, for completeness, we write down the main result here. The probability distribution of the number of proteins n_p at time t is given by (assuming the initial conditions to be zero protein in state G):","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"P left( n_p t right) = frac1n_p fracd^n_pdw^n_pleft( G_0(w t) + G_1(w t) right) _w=-1","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"where","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"beginalign*\nG_0(w t) = exp(ρ_b w) left f(we^-t) (-rho_Delta w)^1-Sigma M(1-barsigma_b 2-Sigma -rho_Delta w) \n+ g(we^-t)M(1+sigma_uSigma-rho_Delta w) right\nG_1(w t) = sigma_u^-1 exp(rho_b w) left -sigma_u f(we^-t)(-rho_Delta w)^1-Sigma M(-barsigma_b 2-Sigma -rho_Delta w) \n+barsigma_b g(we^-t) M(sigma_u Sigma -rho_Delta w) right\nendalign*","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"where w=z-1 and the probability generating functions are given by G_i(z t) = sum_n_p=0^infty z^n_p P_i(n_p t). The function M(cdotcdotcdot) stands for the Kummer's (confluent hypergeometric) function and we also use the following definitions:","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"beginalign*\n rho_Delta = rho_b - rho_u \n Sigma = sigma_u + barsigma_b + 1 \n f(w) = fracbarsigma_bSigma-1(-rho_Delta w)^Sigma-1e^-rho_u wM(sigma_u Sigma -rho_Delta w) \n g(w) = fracsigma_uSigma-1e^-rho_u w M(-barsigma_b 2-Sigma -rho_Delta w)\nendalign*","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"One can observe that having a closed-form solution does not make life that much easier as now we have to find a way how to numerically evaluate these complicated mathematical expressions in a reasonably efficient manner. The main problem here is that in order to construct the probability distribution we have to take arbitrarily high n^th order derivatives. Doing that symbolically is possible in principle but can be extremely computationally expensive as the symbolic expressions will be expanding exponentially in size with each higher derivative order: keeping them in memory is expensive and the same terms would have to be evaluated repeatedly many times. Similarly, naively nesting numerical derivative operations using an automatic differentiation framework is possible but still many redundant operations would need to be performed.","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"As pointed out by the authors in [1], a more efficient way is to expand the generating functions G_0(w t) + G_1(w t) around w=-1 as then the n^th Taylor series coefficient will be equivalent to the probability of having n proteins at time t. This approach can be particularly effective: recursion relations for the Taylor coefficients of various elementary functions can be defined and in turn utilised to minimise the amount of redundant work which has to be performed when Taylor expanding any given mathematical expression. Such higher-order automatic differentiation framework in Julia is provided by TaylorSeries.jl.","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"However, TaylorSeries only supports elementary function operations at the time and hence evaluating the Kummer's function M(cdotcdotcdot) requires some more work (these specialised numerics are readily available in more established scientific computing frameworks such as Mathematica but there's no fun in that). We can extend the TaylorSeries framework by constructing a function t_pFq that implements a recurrence relation between the Taylor coefficients for the generalized hypergeometric function pFq as defined in HypergeometricFunctions.jl. This can be done as follows (note that our construction is valid only for a single-variable Taylor series Taylor1):","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"using TaylorSeries, HypergeometricFunctions\nusing HypergeometricFunctions: pFqweniger\n\n# please let me know if a simpler and more efficient way to do this exists!\nfunction t_pFq(α::AbstractVector, β::AbstractVector, a::Taylor1)\n order = a.order\n aux = pFqweniger(α, β, constant_term(a))\n c = Taylor1(aux, order)\n\n iszero(order) && return c\n\n coeffs = t_pFq(α.+1, β.+1, Taylor1(a[0:end-1], a.order-1))\n factor = prod(α)/prod(β)\n for k in 1:length(a)-1\n c[k] = sum(i * a[i] * coeffs[k-i] for i in 1:k) * factor / k\n end\n\n return c\n\nend","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"We can now move on with the LMA procedure to obtain the probability distribution of the nonlinear GRN for the number of proteins at a chosen time point t=4. Step 4 of the LMA involves obtaining the time-independent effective parameter barsigma_b which is given by its time-averaged value:","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"# calculate the raw moments up to time t at a fine temporal resolution\nT = 4.0\ntspan = (0., T)\ndt = 0.001\noprob_LMA = remake(oprob_LMA, tspan=tspan)\nsol_LMA = solve(oprob_LMA, CVODE_BDF(), saveat=dt)\n\n# rebuild the symbolic expression for the effective parameter as a function of raw moments\nμ_sym = [LMA_eqs.odes.states...]\np_sub = Dict.(Pair.(LMA_eqs.odes.ps, p)...)\navg_σ_b_sym = collect(values(effective_params))[1]\nfn = build_function(substitute(avg_σ_b_sym, p_sub), μ_sym)\navg_σ_b = eval(fn)\n# evaluate the time-averaged value of the effective parameter\n@time σ_b_avg = sum(avg_σ_b.(sol_LMA.u)) * dt / T","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"We proceed with the very last steps of the LMA to obtain the probability distribution:","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"# need higher-precision numerics as Float64 can be unstable here due to very small numbers\n# DoubleFloats is sufficient for this example and much more efficient than BigFloat\nusing DoubleFloats\n\n# define the numerical values of the parameters\nσ_u = p[2]; ρ_b = p[3]; ρ_u = p[4]\nΣ = 1 + σ_b_avg + σ_u\nρ_Δ = ρ_b - ρ_u\n\nn = 100 # expansion order (or max protein number to evaluate)\nw₀ = -1 # value around which to expand\n\n# compute the Taylor expansion (note the use of Double64)\nw = w₀ + Taylor1(Double64, n)\n@time f = σ_b_avg/(Σ-1)*exp(-T*(Σ-1))*exp(-ρ_u*w*exp(-T))*t_pFq([σ_u], [Σ], -ρ_Δ*w*exp(-T))\n@time g = σ_u/(Σ-1)*exp(-ρ_u*w*exp(-T))*t_pFq([-σ_b_avg], [2-Σ], -ρ_Δ*w*exp(-T))\n\n@time G00 = exp(ρ_b*w)*(f * t_pFq([1-σ_b_avg], [2-Σ], -ρ_Δ*w) +\n g * t_pFq([1+σ_u], [Σ], -ρ_Δ*w) )\n\n@time G11 = σ_u^(-1) * exp(ρ_b*w) * (-σ_u*f*t_pFq([-σ_b_avg], [2-Σ], -ρ_Δ*w) +\n σ_b_avg*g*t_pFq([σ_u], [Σ], -ρ_Δ*w))\n\nprobs = (G00+G11).coeffs\n\n# check that the probability distribution is more or less normalised to 1\n# need higher numerical precision if not\nisapprox(sum(probs), 1.0, rtol=1e-2)","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"0.009289 seconds (41.03 k allocations: 1.603 MiB)\n0.009126 seconds (41.03 k allocations: 1.603 MiB)\n0.067889 seconds (85.06 k allocations: 3.613 MiB)\n0.066194 seconds (85.07 k allocations: 3.618 MiB)\ntrue","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"Finally, we can plot the distribution and compare it to the FSP result:","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"plot(0:n, probs, xlabel=\"n\", ylabel=\"P(n, t=4)\", label=\"LMA\", fmt=\"svg\")\n# plot the FSP probability of protein number by marginalising over the gene states\nplot!(0:n, sum(sol_FSP[:, 41], dims=1)'[1:n+1], label=\"FSP\")","category":"page"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"(Image: LMA FSP feedback loop distribution)","category":"page"},{"location":"tutorials/LMA_example/#References","page":"LMA Example","title":"References","text":"","category":"section"},{"location":"tutorials/LMA_example/","page":"LMA Example","title":"LMA Example","text":"[1]: Z. Cao and R. Grima, \"Linear mapping approximation of gene regulatory networks with stochastic dynamics\", Nature Communications 9, 3305 (2018). https://doi.org/10.1038/s41467-018-05822-0","category":"page"},{"location":"tutorials/time-dependent_propensities/#time-dependent-propensities","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"","category":"section"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"Here we consider an example of using time-dependent propensities in modelling chemical reaction networks using MomentClosure and DifferentialEquations. Following Schnoerr et al. (2015), we modify the Brusellator introduced earlier to include entrainment:","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"beginalign*\n2X + Y stackrelc_1rightarrow 3X \nX stackrelc_2(t)rightarrow Y \n undersetc_4stackrelc_3rightleftharpoons X\nendalign*","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"The rate constant of the second reaction is now a sinusoidal function of time:","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"beginalign*\n c_2(t) = c_2^0left(1+frac12sin(omega t) right) quad textif t leq tau \n c_2(t) = c_2^0 quad textif t tau\nendalign*","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"where c_2^0 is a fixed value and the sinusoidal modulation with frequency omega is switched off after a certain time tau. We can define the model and generate the corresponding moment equations as follows:","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"using Catalyst, MomentClosure, Latexify\n\nrn = @reaction_network begin\n @parameters c₁ c₂ c₃ c₄ Ω ω τ\n (c₁/Ω^2), 2X + Y → 3X\n (c₂*(1+0.5*sin(ω*(t<τ)*t))), X → Y\n (c₃*Ω, c₄), 0 ↔ X\nend\n\nraw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=false)\nlatexify(raw_eqs)","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"beginalign*\nfracdmu_10dt = c_3 Omega + c_1 mu_21 Omega^-2 - c_2 mu_10 - c_4 mu_10 - c_1 mu_11 Omega^-2 - 05 c_2 mu_10 sinleft( t omega left( t tau right) right) \nfracdmu_01dt = c_2 mu_10 + c_1 mu_11 Omega^-2 + 05 c_2 mu_10 sinleft( t omega left( t tau right) right) - c_1 mu_21 Omega^-2 \nfracdmu_20dt = c_2 mu_10 + c_3 Omega + c_4 mu_10 + 2 c_1 mu_31 Omega^-2 + 05 c_2 mu_10 sinleft( t omega left( t tau right) right) + 2 c_3 Omega mu_10 - 2 c_2 mu_20 - 2 c_4 mu_20 - c_1 mu_11 Omega^-2 - c_1 mu_21 Omega^-2 - c_2 mu_20 sinleft( t omega left( t tau right) right) \nfracdmu_11dt = c_2 mu_20 + c_1 mu_11 Omega^-2 + c_1 mu_22 Omega^-2 + c_3 Omega mu_01 + 05 c_2 mu_20 sinleft( t omega left( t tau right) right) - c_2 mu_10 - c_2 mu_11 - c_4 mu_11 - c_1 mu_12 Omega^-2 - c_1 mu_31 Omega^-2 - 05 c_2 mu_10 sinleft( t omega left( t tau right) right) - 05 c_2 mu_11 sinleft( t omega left( t tau right) right) \nfracdmu_02dt = c_2 mu_10 + c_1 mu_21 Omega^-2 + c_2 mu_11 sinleft( t omega left( t tau right) right) + 2 c_2 mu_11 + 2 c_1 mu_12 Omega^-2 + 05 c_2 mu_10 sinleft( t omega left( t tau right) right) - c_1 mu_11 Omega^-2 - 2 c_1 mu_22 Omega^-2\nendalign*","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"We can now easily close the moment equations using normal closure and solve the resulting system of ODEs:","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"using OrdinaryDiffEq, Plots\n\nclosed_raw_eqs = moment_closure(raw_eqs, \"normal\")\n\n# parameter values [c₁, c₂, c₃, c₄, Ω, ω, τ]\np = [0.9, 2., 1., 1., 5., 1., 40.]\n\n# initial molecule numbers of species [X, Y]\nu₀ = [1., 1.]\n\n# deterministic initial conditions\nu₀map = deterministic_IC(u₀, closed_raw_eqs)\n\n# time interval to solve one on\ntspan = (0., 100.)\n\n# convert the closed raw moment equations into a DifferentialEquations ODEProblem\noprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)\n\n# solve using Tsit5 solver\nsol = solve(oprob, Tsit5(), saveat=0.2)\nplot(sol, idxs=[1,2], lw=2)","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"(Image: Time-dependent Brusselator normal)","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"It would be great to compare our results to the true dynamics. Using DifferentialEquations, we can run a modified SSA taking into account the time-dependent propensity functions (VariableRateJumps). This requires some care and is done by combining an ODEProblem with a JumpProblem:","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"using JumpProcesses\n\n# convert ReactionSystem into JumpSystem\njsys = convert(JumpSystem, rn, combinatoric_ratelaws=false)\n\n# Define an ODEProblem to integrate between reaction events\n# note that u₀ elements must be Floats (otherwise throws an error)\nf(du,u,p,t) = du .= 0\noprob = ODEProblem(f, u₀, tspan, p)\n\n# Create a modified SSA problem that now correctly incorporates VariableRateJumps\njprob = JumpProblem(jsys, oprob, Direct())","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"Finally, we can define a corresponding EnsembleProblem to simulate multiple SSA trajectories. However, the saveat argument does not work with VariableRateJumps (a known bug): without it, the solution is saved at each reaction event, in turn generating large data arrays that can get extremely memory-intensive when many trajectories are considered. Our workaround is to simply modify the output_func in EnsembleProblem so that each SSA trajectory is saved to the output array only at the specified timepoints (albeit a lot of garbage collection must be done):","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"# timestep at which the solution data is saved\ndt = 0.2\n# the corresponding time iterator (0:0.2:100 in our case)\nts = tspan[1]:dt:tspan[2]\n# save data for each trajectory only at the specified timepoints (interpolating the ODESolution)\nfout = (sol, i) -> (sol(ts), false)\nensembleprob = EnsembleProblem(jprob, output_func=fout)\n\n# simulate 10000 SSA trajectories (can get very slow...)\n@time sol_SSA = solve(ensembleprob, Tsit5(), trajectories=10000)","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"2975.249760 seconds (1.07 G allocations: 105.883 GiB, 81.30% gc time, 0.02% compilation time)","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"Finally, we can compute the mean SSA trajectories and compare to the moment closure estimates:","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"using SciMLBase.EnsembleAnalysis\n\nmeans_SSA = timeseries_steps_mean(sol_SSA)\nplot!(means_SSA.t, [means_SSA[1,:], means_SSA[2,:]], lw=1.5, labels=[\"SSA μ₁₀(t)\" \"SSA μ₀₁(t)\"], linestyle=:dash,\n linecolor=[1 2], background_color_legend=nothing, legend=:bottomright)","category":"page"},{"location":"tutorials/time-dependent_propensities/","page":"Time-dependent Propensity Functions","title":"Time-dependent Propensity Functions","text":"(Image: Time-dependent Brusselator SSA)","category":"page"},{"location":"tutorials/derivative_matching_example/#derivative-matching-example","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"","category":"section"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"In this example, we aim to reproduce a number of results from the original derivative matching paper by Singh and Hespanha [1]. We consider the bimolecular reaction system given by:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"beginalign*\nX_1 stackrelc_1rightarrow 2X_1 + X_2 \nX_1 + X_2stackrelc_2rightarrow X_2\nendalign*","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"The reaction network and its parameters can be defined as follows:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"using Catalyst\n\nrn = @reaction_network begin\n @parameters c₁ c₂\n (c₁), x₁ → 2x₁+x₂\n (c₂), x₁+x₂ → x₂\nend\n\n# parameter values\np = [1.0, 1.0]\n# initial conditions\nu0 = [20, 10]\n# time interval to solve on\ntspan = (0., 0.5)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"We are interested in extracting the time-evolution of a specific third order cumulant, κ_03, using second and third order moment expansions with derivative matching, and comparing the obtained estimates to the SSA prediction.","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"Let's start with a second order moment expansion and print out the third-order moment closure functions obtained with derivative matching:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"using MomentClosure, Latexify\n\neqs2 = generate_raw_moment_eqs(rn, 2)\ndm2_eqs = moment_closure(eqs2, \"derivative matching\")\nlatexify(dm2_eqs, :closure, print_all=true)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"beginalign*\nmu_30 = mu_10^-3 mu_20^3 \nmu_21 = mu_20 mu_01^-1 mu_10^-2 mu_11^2 \nmu_12 = mu_02 mu_01^-2 mu_10^-1 mu_11^2 \nmu_03 = mu_01^-3 mu_02^3\nendalign*","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"Note that all closure functions are consistent with the ones shown in Table II of [1]. We can then move on to solving the generated system of moment ODEs:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"using OrdinaryDiffEq\n\nu0map = deterministic_IC(u0, dm2_eqs) # assuming deterministic initial conditions\noprob = ODEProblem(dm2_eqs, u0map, tspan, p)\ndm2_sol = solve(oprob, Tsit5(), saveat=0.01)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"Now the question is how can we extract the time evolution of the cumulant kappa_03. Firstly, note that using the standard moment relationships it can be expressed in terms of raw moments as:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"beginalign*\nkappa_03 = 2 mu_01^3 - 3mu_02mu_01 + mu_03\nendalign*","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"As we were solving for moments up to second order, we do not have any direct information on the third order moment mu_03. Nevertheless, we can manually approximate it using the corresponding closure function given above, i.e., mu_03 = mu_01^-3 mu_02^3. The time trajectories of mu_01 and mu_02 can be extracted from dm2_sol and their order in the array can be checked with:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"dm2_eqs.odes.states","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"5-element Array{Term{Real,Nothing},1}:\n μ₁₀(t)\n μ₀₁(t)\n μ₂₀(t)\n μ₁₁(t)\n μ₀₂(t)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"Finally, we can combine all the steps to obtain the kappa_03 estimate:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"μ₀₁ = dm2_sol[2, :]\nμ₀₂ = dm2_sol[5, :]\nμ₀₃ = (μ₀₁ .^(-3)) .* (μ₀₂ .^3)\ndm2_κ₀₃ = 2 .* μ₀₁ .^3 .- 3 .* μ₀₂ .* μ₀₁ .+ μ₀₃","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"Next we consider a third order moment expansion:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"eqs3 = generate_raw_moment_eqs(rn, 3)\ndm3_eqs = moment_closure(eqs3, \"derivative matching\")\nlatexify(dm3_eqs, :closure, print_all=true)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"beginalign*\nmu_40 = mu_10^4 mu_20^-6 mu_30^4 \nmu_31 = mu_01 mu_30 mu_10^3 mu_11^-3 mu_20^-3 mu_21^3 \nmu_22 = mu_01^2 mu_02^-1 mu_10^2 mu_11^-4 mu_12^2 mu_20^-1 mu_21^2 \nmu_13 = mu_03 mu_10 mu_01^3 mu_02^-3 mu_11^-3 mu_12^3 \nmu_04 = mu_01^4 mu_02^-6 mu_03^4\nendalign*","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"As expected, the closure functions agree with those given in Table III of [1]. We again check the order of variables","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"dm3_eqs.odes.states","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"9-element Array{Term{Real,Nothing},1}:\n μ₁₀(t)\n μ₀₁(t)\n μ₂₀(t)\n μ₁₁(t)\n μ₀₂(t)\n μ₃₀(t)\n μ₂₁(t)\n μ₁₂(t)\n μ₀₃(t)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"and solve the moment equations, computing the required cumulant:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"u0map = deterministic_IC(u0, dm3_eqs)\noprob = ODEProblem(dm3_eqs, u0map, tspan, p)\ndm3_sol = solve(oprob, Tsit5(), saveat=0.01, abstol=1e-8, reltol=1e-8)\n\nμ₀₁ = dm3_sol[2,:]\nμ₀₂ = dm3_sol[5,:]\nμ₀₃ = dm3_sol[9,:]\ndm3_κ₀₃ = 2 .* μ₀₁ .^ 3 - 3 .* μ₀₂ .* μ₀₁ .+ μ₀₃","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"Note that we could have also obtained kappa_03 estimate in an easier way by using central moment equations, as third order central moments are equal to the corresponding third order cumulants:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"central_eqs3 = generate_central_moment_eqs(rn, 3)\ndm3_central_eqs = moment_closure(central_eqs3, \"derivative matching\")\n\nu0map = deterministic_IC(u0, dm3_central_eqs)\noprob = ODEProblem(dm3_central_eqs, u0map, tspan, p)\ndm3_central_sol = solve(oprob, Tsit5(), saveat=0.01, abstol=1e-8, reltol=1e-8)\n\n# check that the two estimates are equivalent\ndm3_κ₀₃ ≈ dm3_central_sol[9,:]","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"true","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"The last ingredient we need for a proper comparison between the second and third order moment expansions is a reference value predicted by the SSA. We can simulate 10^5 SSA trajectories as follows:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"using JumpProcesses\n\ndprob = DiscreteProblem(rn, u0, tspan, p)\njprob = JumpProblem(rn, dprob, Direct(), save_positions=(false, false))\n\nensembleprob = EnsembleProblem(jprob)\n@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.01, trajectories=100000)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"3.874558 seconds (7.45 M allocations: 714.845 MiB, 46.60% gc time)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"The time evolution of kappa_03 can be extracted from SSA data using the get_cumulants function:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"ssa_κ₀₃ = get_cumulants(sol_SSA, 3)[0, 3]","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"Finally, we plot the results:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"using Plots, LaTeXStrings\n\nplot(dm2_sol.t, dm2_κ₀₃, lw=2, label=\"2nd order DM\")\nplot!(dm2_sol.t, dm3_κ₀₃, lw=2, label=\"3rd order DM\")\nplot!(dm2_sol.t, ssa_κ₀₃, lw=2, label=\"SSA\")\nplot!(ylabel=L\"\\kappa_{03}\", xlabel=L\"t\", guidefontsize=14, legend=:bottomright)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"(Image: Derivative Matching cumulant)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"We observe that the third order moment truncation using derivative matching performs significantly better than the second order truncation, accurately matching the true SSA prediction (consistent with the figure in [1]).","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"It is also interesting to note that the closure functions of third order moments obtained using derivative matching and log-normal closures are equivalent. We can see that it is indeed the case by printing out the log-normal closure functions","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"ln2_eqs = moment_closure(eqs2, \"log-normal\")\nlatexify(ln2_eqs, :closure, print_all=true)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"beginalign*\nmu_30 = mu_10^-3 mu_20^3 \nmu_21 = mu_20 mu_01^-1 mu_10^-2 mu_11^2 \nmu_12 = mu_02 mu_01^-2 mu_10^-1 mu_11^2 \nmu_03 = mu_01^-3 mu_02^3\nendalign*","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"and the corresponding derivative matching functions obtained previously:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"latexify(dm2_eqs, :closure, print_all=true)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"beginalign*\nmu_30 = mu_10^-3 mu_20^3 \nmu_21 = mu_20 mu_01^-1 mu_10^-2 mu_11^2 \nmu_12 = mu_02 mu_01^-2 mu_10^-1 mu_11^2 \nmu_03 = mu_01^-3 mu_02^3\nendalign*","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"However, the equivalence holds only for third order moments. For example, the closure functions of fourth order moments differ:","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"ln3_eqs = moment_closure(eqs3, \"log-normal\")\nlatexify(ln3_eqs, :closure, print_all=true)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"beginalign*\nmu_40 = mu_10^-8 mu_20^6 \nmu_31 = mu_01^-2 mu_10^-6 mu_11^3 mu_20^3 \nmu_22 = mu_02 mu_20 mu_01^-4 mu_10^-4 mu_11^4 \nmu_13 = mu_01^-6 mu_02^3 mu_10^-2 mu_11^3 \nmu_04 = mu_01^-8 mu_02^6\nendalign*","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"latexify(dm3_eqs, :closure, print_all=true)","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"beginalign*\nmu_40 = mu_10^4 mu_20^-6 mu_30^4 \nmu_31 = mu_01 mu_30 mu_10^3 mu_11^-3 mu_20^-3 mu_21^3 \nmu_22 = mu_01^2 mu_02^-1 mu_10^2 mu_11^-4 mu_12^2 mu_20^-1 mu_21^2 \nmu_13 = mu_03 mu_10 mu_01^3 mu_02^-3 mu_11^-3 mu_12^3 \nmu_04 = mu_01^4 mu_02^-6 mu_03^4\nendalign*","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"This difference is expected as fourth order moments using log-normal closure are expressed exclusively in terms of first and second order moments, whereas derivative matching additionally incorporates third order moment information. Singh and Hespanha [1, 2] elaborate on this point: as there is no unique way to define higher order moment closure functions for log-normal distribution, both closures are consistent with the assumption that the population is jointly log-normally distributed. We urge the reader to consult the mentioned papers [1, 2] and the references therein for a more complete discussion comparing the two approaches.","category":"page"},{"location":"tutorials/derivative_matching_example/#References","page":"Derivative Matching Example","title":"References","text":"","category":"section"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"[1]: A. Singh and J. P. Hespanha, \"Lognormal Moment Closures for Biochemical Reactions\", in Proceedings of the 45th IEEE Conference on Decision and Control, ISSN:0191-2216 (Dec. 2006), pp. 2063–2068. https://doi.org/10.1109/CDC.2006.376994","category":"page"},{"location":"tutorials/derivative_matching_example/","page":"Derivative Matching Example","title":"Derivative Matching Example","text":"[2]: A. Singh and J. P. Hespanha, \"Approximate Moment Dynamics for Chemically Reacting Systems\", IEEE Transactions on Automatic Control 56, 414–418 (2011). https://doi.org/10.1109/TAC.2010.2088631","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/#geometric-and-conditional","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"","category":"section"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"In this tutorial, we demonstrate using Catalyst how to define chemical systems involving reactions which products are geometrically distributed random variables. As an example, we consider an autoregulatory (repressive) genetic feedback loop where proteins are expressed in bursts with a geometric burst size distribution, as described by Soltani et al. [1]. Moreover, the state of the gene is modelled as a binary variable—we demonstrate how conditional derivative matching and conditional gaussian closures can be used to approximate such systems, in turn reproducing a number of results from Ref. [1].","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"We consider a negative feedback loop described by the following reactions:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"beginalign*\nG^* stackrelk_onrightarrow G \nG + stackrelk_off*P^2rightarrow G^* \nG stackrelk_prightarrow G + mP \nP stackrelgamma_prightarrow \nendalign*","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"A gene in the network switches between ON (G) and OFF (G^*) states: proteins are produced in the transcriptionally active ON state but the gene can be turned OFF by two protein molecules binding to the promoter region and thus blocking transcription (proteins decay at a constant rate irrespective of the gene state). Note that the gene state can be interpreted as a distinct species that have either zero or one copy number per cell. In other words, it is a Bernoulli random variable: 0 in the OFF state and 1 in the ON state.","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"The transcription (mRNA) dynamics are not modelled explicitly in this gene circuit. Instead, under the assumption of fast mRNA decay, proteins are taken to be produced in bursts of size m, where m is a random variable sampled from the geometric distribution phi(m) = b^m(1+b)^m+1 (with b denoting the mean burst size) [2]. Chemical reaction networks that include reactions which products are independent geometrically distributed random variables (or other symbolic variables) can be defined using Catalyst as demonstrated in this tutorial. Note that the referenced tutorial refers back to this tutorial because in the ancient times Catalyst did not provided such functionality and the previous iteration of MomentClosure implemented a ReactionSystemMod type that offered limited support for such systems (now deprecated as Catalyst does it better in a unified API).","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"Using Catalyst, our gene network model can be constructed as follows:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"# load all the packages we will need\nusing MomentClosure, Catalyst, Distributions, JumpProcesses, DiffEqBase, OrdinaryDiffEq, DiffEqBase.EnsembleAnalysis, Plots, Latexify\n\n# Proteins are produced in bursts of size m, where m is a geometric random variable with mean b.\n# Note that if b is the mean burst size, then p = 1/(1+b). \n# Implemented by first registering the distribution with Symbolics\n@register_symbolic Distributions.Geometric(b)\n@parameters b\nm = rand(Distributions.Geometric(1/(1+b)))\n\nrn = @reaction_network begin\n @parameters k_on k_off k_p γ_p\n k_on*(1-g), 0 --> g # G* -> G\n k_off*P^2, g --> 0 # G -> G*\n k_p, g --> g + $m*P # G -> G + mP, m ~ Geometric(p)\n γ_p, P --> 0 # P -> ∅\nend","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"We can now generate the raw moment equations up to third order:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"eqs = generate_raw_moment_eqs(rn, 3)\nlatexify(eqs)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"beginalign*\nfracdmu_1 0dt = k_on - k_off mu_1 2 - k_on mu_1 0 \nfracdmu_0 1dt = b k_p mu_1 0 - gamma_p mu_0 1 \nfracdmu_2 0dt = k_on + k_off mu_1 2 + k_on mu_1 0 - 2 k_on mu_2 0 - 2 k_off mu_2 2 \nfracdmu_1 1dt = k_on mu_0 1 + b k_p mu_2 0 - k_on mu_1 1 - gamma_p mu_1 1 - k_off mu_1 3 \nfracdmu_0 2dt = gamma_p mu_0 1 + b k_p mu_1 0 + 2 b k_p mu_1 1 + 2 k_p b^2 mu_1 0 - 2 gamma_p mu_0 2 \nfracdmu_3 0dt = k_on + 3 k_off mu_2 2 + 2 k_on mu_1 0 - k_off mu_1 2 - 3 k_off mu_3 2 - 3 k_on mu_3 0 \nfracdmu_2 1dt = k_on mu_0 1 + k_on mu_1 1 + k_off mu_1 3 + b k_p mu_3 0 - 2 k_on mu_2 1 - gamma_p mu_2 1 - 2 k_off mu_2 3 \nfracdmu_1 2dt = k_on mu_0 2 + gamma_p mu_1 1 + b k_p mu_2 0 + 2 k_p b^2 mu_2 0 + 2 b k_p mu_2 1 - k_off mu_1 4 - k_on mu_1 2 - 2 gamma_p mu_1 2 \nfracdmu_0 3dt = b k_p mu_1 0 + 3 gamma_p mu_0 2 + 3 b k_p mu_1 1 + 3 b k_p mu_1 2 + 6 k_p b^2 mu_1 0 + 6 k_p b^3 mu_1 0 + 6 k_p b^2 mu_1 1 - gamma_p mu_0 1 - 3 gamma_p mu_0 3\nendalign*","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"A lot of information in this system of ODEs is redundant as the gene state is a Bernoulli variable that (in our case) has the following properties:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"beginalign*\nμ_j0 = μ_10 quad j in 2 3 dotsc \nμ_jk = μ_1k quad jk in 1 2 3 dotsc\nendalign*","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"We can clean the moment equations accordingly by specifying which molecule numbers are Bernoulli variables and using the bernoulli_moment_eqs function:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"# specify the indices of species which molecule numbers are binary\nbinary_vars = [1]\n# simplify the moment equations using properties of Bernoulli variables\nclean_eqs = bernoulli_moment_eqs(eqs, binary_vars)\nlatexify(clean_eqs)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"beginalign*\nfracdmu_1 0dt = k_on - k_off mu_1 2 - k_on mu_1 0 \nfracdmu_0 1dt = b k_p mu_1 0 - gamma_p mu_0 1 \nfracdmu_1 1dt = k_on mu_0 1 + b k_p mu_1 0 - k_on mu_1 1 - gamma_p mu_1 1 - k_off mu_1 3 \nfracdmu_0 2dt = gamma_p mu_0 1 + b k_p mu_1 0 + 2 b k_p mu_1 1 + 2 k_p b^2 mu_1 0 - 2 gamma_p mu_0 2 \nfracdmu_1 2dt = k_on mu_0 2 + gamma_p mu_1 1 + b k_p mu_1 0 + 2 b k_p mu_1 1 + 2 k_p b^2 mu_1 0 - k_off mu_1 4 - k_on mu_1 2 - 2 gamma_p mu_1 2 \nfracdmu_0 3dt = b k_p mu_1 0 + 3 gamma_p mu_0 2 + 3 b k_p mu_1 1 + 3 b k_p mu_1 2 + 6 k_p b^2 mu_1 0 + 6 k_p b^3 mu_1 0 + 6 k_p b^2 mu_1 1 - gamma_p mu_0 1 - 3 gamma_p mu_0 3\nendalign*","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"The system of ODEs is now much simpler and we can see that there are two higher-order moments we need to truncate: mu_13 and μ_14. We consider normal, derivative matching, conditional gaussian and conditional derivative matching closures to see how well they compare. First we apply different closures and print out the corresponding higher-order moment expressions in order to check that our results are consistent with those published in [1].","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"For normal closure:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"normal_eqs = moment_closure(eqs, \"normal\", binary_vars)\nlatexify(normal_eqs, :closure)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"beginalign*\nmu_13 = mu_03 mu_10 + 3 mu_01 mu_12 + 3 mu_02 mu_11 + 6 mu_10 mu_01^3 - 6 mu_11 mu_01^2 - 6 mu_01 mu_02 mu_10 \nmu_14 = mu_04 mu_10 + 4 mu_01 mu_13 + 6 mu_02 mu_12 + 4 mu_03 mu_11 + 24 mu_11 mu_01^3 + 36 mu_02 mu_10 mu_01^2 - 24 mu_10 mu_01^4 - 6 mu_10 mu_02^2 - 12 mu_12 mu_01^2 - 24 mu_01 mu_02 mu_11 - 8 mu_01 mu_03 mu_10\nendalign*","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"Note that our expression for μ_14 is different from the equivalent langle gp^4 rangle in Eq. (8) of [1] as it seems that the authors introduced a mistake considering the central moment and cumulant relationship in Eq. (7).","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"Using derivative matching, we obtain:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"dm_eqs = moment_closure(eqs, \"derivative matching\", binary_vars)\nlatexify(dm_eqs, :closure)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"beginalign*\nmu_1 3 = fracmu_0 1^3 mu_1 2^3 mu_0 3 mu_1 0mu_0 2^3 mu_1 1^3 \nmu_1 4 = fracmu_0 2^6 mu_1 1^4 mu_1 3^4 mu_0 4mu_0 1^4 mu_0 3^4 mu_1 2^6 mu_1 0\nendalign*","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"For conditional gaussian closure:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"cond_gaussian_eqs = moment_closure(eqs, \"conditional gaussian\", binary_vars)\nlatexify(cond_gaussian_eqs, :closure)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"beginalign*\nmu_1 3 = frac-2 mu_1 1^3mu_1 0^2 + frac3 mu_1 1 mu_1 2mu_1 0 \nmu_1 4 = frac3 mu_1 2^2mu_1 0 + frac6 mu_1 1^4mu_1 0^3 + frac-12 mu_1 1^2 mu_1 2mu_1 0^2 + frac4 mu_1 1 mu_1 3mu_1 0\nendalign*","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"And, finally, for conditional derivative matching:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"cond_dm_eqs = moment_closure(eqs, \"conditional derivative matching\", binary_vars)\nlatexify(cond_dm_eqs, :closure)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"beginalign*\nmu_1 3 = fracmu_0 1^3 mu_1 2^3 mu_0 3 mu_1 0mu_0 2^3 mu_1 1^3 \nmu_1 4 = fracmu_0 2^6 mu_1 1^4 mu_1 3^4 mu_0 4mu_0 1^4 mu_0 3^4 mu_1 2^6 mu_1 0\nendalign*","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"All these results are consistent with [1], reassuring that the model and closures are implemented as intended. Finally, we can proceed to solve the resulting ODEs and compare the resulting means and standard deviations to the SSA. Following Soltani et al. [1], we define all model parameters as:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"mean_p = 200\nmean_b = 70\nγ_p_val = 1\nk_off_val = 0.001\nk_on_val = 0.05\n\nk_p_val = mean_p * γ_p_val * (k_off_val * mean_p^2 + k_on_val) / (k_on_val * mean_b)\n\nsymmap = [:k_on => k_on_val,\n :k_off => k_off_val,\n :k_p => k_p_val,\n :γ_p => γ_p_val,\n :b => mean_b]\npmap = symmap_to_varmap(rn, symmap)\n\n# initial gene state and protein number, order [g, p]\nu₀ = [1, 1]\n\n# time interval to solve on\ntspan = (0., 6.0)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"The reaction network with geometric bursts can be simulated using the SSA as usual:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"# convert the reaction network into a system of jump processes\njsys = convert(JumpSystem, rn; combinatoric_ratelaws=false)\n\n# create a discrete problem setting the simulation parameters\ndprob = DiscreteProblem(u₀, tspan, pmap)\n\n# create a JumpProblem compatible with ReactionSystemMod\njprob = JumpProblem(rn, dprob, Direct(), save_positions=(false, false))\n\n# simulate 2×10⁴ SSA trajectories\nensembleprob = EnsembleProblem(jprob)\n@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.1, trajectories=20000)\n# compute the means and variances\nmeans_ssa, vars_ssa = timeseries_steps_meanvar(sol_SSA)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"4.858357 seconds (14.30 M allocations: 901.032 MiB, 6.25% gc time, 63.45% compilation time)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"We continue to solve the moment equations for each closure:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"plt_m = plot() # plot mean protein number\nplt_std = plot() # plot ssd of protein number\n\n# construct the initial molecule number mapping\nu₀map = deterministic_IC(u₀, dm_eqs)\n\n# solve moment ODEs for each closure and plot the results\nfor closure in [\"normal\", \"derivative matching\",\n \"conditional gaussian\", \"conditional derivative matching\"]\n\n # it is very quick so we just apply all closures again\n closed_eqs = moment_closure(eqs, closure, binary_vars)\n\n # solve the system of moment ODEs\n oprob = ODEProblem(closed_eqs, u₀map, tspan, pmap)\n sol = solve(oprob, AutoTsit5(Rosenbrock23()), saveat=0.01)\n\n # μ₀₁ is 2nd and μ₀₂ is 4th element in sol\n # can check the order with `closed_eqs.odes.states`\n plt_m = plot!(plt_m, sol, idxs=[2], label=closure)\n plt_std = plot!(plt_std, sol.t, sqrt.(sol[4, :] .- sol[2, :].^2), label=closure)\n\nend\n\nplt_m = plot!(plt_m, xlabel=\"Time [hr]\", ylabel=\"Protein mean level\")\nplt_m = plot!(plt_m, means_ssa.t, means_ssa[2,:], label=\"SSA\", linestyle=:dash, color=\"gray\")\nplt_std = plot!(plt_std, xlabel=\"Time [hr]\", ylabel=\"Protein standard deviation\")\nplt_std = plot!(plt_std, vars_ssa.t, sqrt.(vars_ssa[2,:]), label=\"SSA\", linestyle=:dash, color=\"gray\")","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"plot(plt_m, lw=2)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"(Image: Gene 1 means)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"plot(plt_std, lw=2)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"(Image: Gene 2 stds)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"We observe that the two conditional closures give the most accurate results. Therefore, closing moments conditioned on the gene being active is an effective approximation in this case. Note that our results for normal closure are different from [1], most likely due to the incorrect fifth-order moment closure function given in the paper.","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"We now turn to a more complex network involving two genes (two Bernoulli variables), a repressor-activator circuit: an activator protein Y expressed by one gene can turn ON another gene which produces a repressor protein X, that subsequently can bind to the gene promoter region of the activator-producing gene turning it OFF (see [1] for more details). As before, X and Y proteins are expressed in geometrically-distributed bursts. The system can be specified as follows:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"@parameters b_x b_y\n# could redefine in terms of success probabilities p_x and p_y as above\nm = rand(Distributions.Geometric(1/(1+b_x)))\nl = rand(Distributions.Geometric(1/(1+b_y)))\n\n# g_x - gene state of X protein producing gene\n# g_y - gene state of Y protein producing gene\n# x, y - proteins X and Y\nrn = @reaction_network begin\n @parameters kx_on kx_off ky_on ky_off k_x γ_x k_y γ_y\n kx_on*(1-g_x)*y, 0 --> g_x # 0 -> g_x\n kx_off, g_x --> 0 # g_x -> 0\n ky_on*(1-g_y), 0 --> g_y # 0 -> g_y\n ky_off*x, g_y --> 0 # g_y -> 0\n k_x*g_x, 0 --> $m*x # 0 -> mx, m ~ Geometric(mean=b_x)\n γ_x, x --> 0 # x -> 0\n k_y*g_y, 0 --> $l*y # 0 -> ly, l ~ Geometric(mean_b_y)\n γ_y, y --> 0 # y -> 0\nend\n\n# both g_x and g_y are Bernoulli random variables\nbinary_vars = [1, 2]\n\n# Parameter initialisation\n\nmean_x = 100\nmean_y = 100\nmean_b_x = 5\nmean_b_y = 5\nγ_x_val = 1\nγ_y_val = 1\nkx_off_val = 4\nky_on_val = 0.3\nkx_on_val = 0.05\nky_off_val = 0.05\n\nk_x_val = mean_x * γ_x_val * (kx_off_val * mean_y^2 + kx_on_val) / (kx_on_val * mean_b_x)\nk_y_val = mean_y * γ_y_val * (ky_off_val * mean_x^2 + ky_on_val) / (ky_on_val * mean_b_y)\n\n# unclear if Soltani et al. (2015) actually used this parameter set as X numbers\n# jump to millions making SSA extremely slow...\n\n# introduce additional rescaling (otherwise rate coefficients are too high)\nk_x_val *= 0.00003\nk_y_val *= 0.01\n\n# parameter mapping\nsymmap = [:kx_on => kx_on_val,\n :kx_off => kx_off_val,\n :ky_on => ky_on_val,\n :ky_off => ky_off_val,\n :k_x => k_x_val,\n :k_y => k_y_val,\n :γ_x => γ_x_val,\n :γ_y => γ_y_val,\n :b_x => mean_b_x,\n :b_y => mean_b_y]\npmap = symmap_to_varmap(rn, symmap)\n\n# initial gene state and protein number, order [g_x, g_y, x, y]\nu₀ = [1, 1, 1, 1]\n\n# time interval to solve on\ntspan = (0., 12.0)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"Note that here we use a different parameter set from the one considered in [1] as otherwise the number of X proteins goes into millions, making the comparison between closure results difficult due to SSA being extremely slow—it appears that either we have included a mistake setting the parameter values or there is a typo in the paper.","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"We can run SSA as follows:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"jsys = convert(JumpSystem, rn, combinatoric_ratelaws=false)\ndprob = DiscreteProblem(jsys, u₀, tspan, pmap)\njprob = JumpProblem(jsys, dprob, Direct(), save_positions=(false, false))\n\nensembleprob = EnsembleProblem(jprob)\n@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.1, trajectories=10000)\nmeans_ssa, vars_ssa = timeseries_steps_meanvar(sol_SSA)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"13.712331 seconds (43.27 M allocations: 1.697 GiB, 6.56% gc time, 10.01% compilation time)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"We use fourth order moment expansion and apply different closure methods as done for the negative feedback loop, considering the number of activator proteins Y and its standard deviation:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"plt_m = plot() # plot mean activator protein number\nplt_std = plot() # plot ssd of activator protein number\n\nfor closure in [\"derivative matching\", \"conditional derivative matching\"]\n\n closed_eqs = moment_closure(eqs, closure, binary_vars)\n\n u₀map = deterministic_IC(u₀, closed_eqs)\n oprob = ODEProblem(closed_eqs, u₀map, tspan, pmap)\n sol = solve(oprob, Tsit5(), saveat=0.1)\n\n # μ₀₀₀₁ is the 4th and μ₀₀₀₂ is the 12th element in sol (can check with closed_eqs.odes.states)\n plt_m = plot!(plt_m, sol, idxs=[4], label=closure)\n plt_std = plot!(plt_std, sol.t, sqrt.(sol[12, :] .- sol[4, :].^2), label=closure)\nend\n\nplt_m = plot!(plt_m, xlabel=\"Time [hr]\", ylabel=\"Activator mean level\")\nplt_m = plot!(plt_m, means_ssa.t, means_ssa[4,:], label=\"SSA\", linestyle=:dash, color=\"gray\")\nplt_std = plot!(plt_std, xlabel=\"Time [hr]\", ylabel=\"Activator standard deviation\")\nplt_std = plot!(plt_std, vars_ssa.t, sqrt.(vars_ssa[4,:]), label=\"SSA\", linestyle=:dash, color=\"gray\")","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"Note that here we apply only derivative matching and conditional derivative matching, as both normal and conditional gaussian closures failed to be evaluated for the entire time course (irrespective of the solver used). Finally, we can plot the results:","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"plot(plt_m, lw=2)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"(Image: Gene 2 means)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"plot(plt_std, lw=2, xlims=(0., 12.))","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"(Image: Gene 2 stds)","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"The trajectories obtained with conditional derivative matching quite accurately match the true dynamics, showing that it is indeed a powerful closure method for reaction networks involving species with very low (binary) copy numbers.","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/#References","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"References","text":"","category":"section"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"[1]: M. Soltani, C. A. Vargas-Garcia, and A. Singh, \"Conditional Moment Closure Schemes for Studying Stochastic Dynamics of Genetic Circuits\", IEEE Transactions on Biomedical Circuits and Systems 9, 518–526 (2015). https://doi.org/10.1109/tbcas.2015.2453158","category":"page"},{"location":"tutorials/geometric_reactions+conditional_closures/","page":"Geometrically Distributed Reaction Products and Conditional Closures","title":"Geometrically Distributed Reaction Products and Conditional Closures","text":"[2]: D. Schnoerr, G. Sanguinetti, and R. Grima, \"Approximation and inference methods for stochastic biochemical kinetics - a tutorial review\", Journal of Physics A: Mathematical and Theoretical 50, 093001 (2017). https://doi.org/10.1088/1751-8121/aa54d9","category":"page"},{"location":"tutorials/common_issues/#common_issues","page":"Common Issues","title":"Common Issues","text":"","category":"section"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"Moment closure approximations are based on ad hoc assumptions and no rigorous and general predictions can be made on whether the results will be accurate or even physically meaningful [1-2]. Moreover, the truncated moment equations are prone to numerical instabilities and it may not be possible to solve them for the entire time course [3]. In this tutorial, we walk through a number of such issues encountered in the analysis of the Brusselator model introduced in the previous tutorial.","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"We first redefine the system and its parameters for completeness:","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"using MomentClosure, Catalyst, OrdinaryDiffEq, Plots\n\nrn = @reaction_network begin\n @parameters c₁ c₂ c₃ c₄ Ω\n (c₁/Ω^2), 2X + Y → 3X\n (c₂), X → Y\n (c₃*Ω, c₄), 0 ↔ X\nend\n\np = [0.9, 2, 1, 1, 100]\nu₀ = [1, 1]\ntspan = (0., 100.)\n\nraw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=false)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"As we have seen earlier, second-order moment expansion using normal closure approximates the true system dynamics sufficiently accurately but it's interesting to see how other closures compare. Let's try applying zero closure:","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"closed_raw_eqs = moment_closure(raw_eqs, \"zero\")\n\nu₀map = deterministic_IC(u₀, closed_raw_eqs)\noprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)\nsol = solve(oprob, Tsit5(), saveat=0.1)\n\nplot(sol, idxs=[1,2], lw=2)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"(Image: Brusselator issue 1)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"The trajectory of μ₀₁ becomes negative and so zero closure fails to provide physically meaningful results for this parameter set. Note that is important to correctly choose the ODE solver depending on the stiffness of the system and the accuracy required. We tried a number of recommended DifferentialEquations solvers here but none seemed to improve the results.","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"Let's apply log-normal closure next:","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"closed_raw_eqs = moment_closure(raw_eqs, \"log-normal\")\n\nu₀map = deterministic_IC(u₀, closed_raw_eqs)\noprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)\nsol = solve(oprob, Tsit5(), saveat=0.1)\n\nplot(sol, idxs=[1,2], lw=2, legend=:bottomright)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"(Image: Brusselator issue 2)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"We observe sustained oscillatory behaviour instead of the expected damped oscillations. This result is unphysical: single SSA trajectories (that may display sustained oscillations) get dephased over time and hence the ensemble average should always show damped or overdamped oscillations [1].","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"Normal closure is also quite fragile. This can be seen by simply including the combinatorial scaling of the mass-action propensity functions with combinatoric_ratelaw=true which leads to unphysical sustained oscillatory trajectories:","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"raw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=true)\nclosed_raw_eqs = moment_closure(raw_eqs, \"normal\")\n\nu₀map = deterministic_IC(u₀, closed_raw_eqs)\noprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)\nsol = solve(oprob, Tsit5(), saveat=0.1)\n\nplot(sol, idxs=[1,2], lw=2)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"(Image: Brusselator issue 3)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"Nevertheless, this can be improved upon by increasing the order of moment expansion:","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"raw_eqs = generate_raw_moment_eqs(rn, 3, combinatoric_ratelaws=true)\nclosed_raw_eqs = moment_closure(raw_eqs, \"normal\")\n\nu₀map = deterministic_IC(u₀, closed_raw_eqs)\noprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)\nsol = solve(oprob, Tsit5(), saveat=0.1)\n\nplot(sol, idxs=[1,2], lw=2, legend=:bottomright)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"(Image: Brusselator issue 4)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"Some dampening in the system is now visible. Increasing the expansion order to 4 finally leads to physically sensible results:","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"raw_eqs = generate_raw_moment_eqs(rn, 4, combinatoric_ratelaws=true)\nclosed_raw_eqs = moment_closure(raw_eqs, \"normal\")\n\nu₀map = deterministic_IC(u₀, closed_raw_eqs)\noprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)\nsol = solve(oprob, Tsit5(), saveat=0.1)\n\nplot(sol, idxs=[1,2], lw=2)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"(Image: Brusselator issue 5)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"For dessert, we consider unphysical divergent trajectories—a frequent problem with moment equations [3]. A good example is the second-order moment expansion including the combinatorial scaling of propensities with log-normal closure applied:","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"raw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=true)\nclosed_raw_eqs = moment_closure(raw_eqs, \"log-normal\")\n\nu₀map = deterministic_IC(u₀, closed_raw_eqs)\noprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)\nsol = solve(oprob, Rodas4P(), saveat=0.1)\n\nplot(sol, idxs=[1,2], lw=2)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"(Image: Brusselator issue 6)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"In contrast to normal closure, increasing the expansion order makes the problem worse:","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"raw_eqs = generate_raw_moment_eqs(rn, 3, combinatoric_ratelaws=true)\nclosed_raw_eqs = moment_closure(raw_eqs, \"log-normal\")\n\nu₀map = deterministic_IC(u₀, closed_raw_eqs)\noprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)\nsol = solve(oprob, Rodas4P(), saveat=0.1)\n\nplot(sol, idxs=[1,2], lw=2)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"┌ Warning: Interrupted. Larger maxiters is needed.\n└ @ SciMLBase C:\\Users\\asukys\\.julia\\packages\\SciMLBase\\Afx1r\\src\\integrator_interface.jl:331","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"(Image: Brusselator issue 7)","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"Note that the solver throws a warning being unable to evaluate the trajectories for the entire time course (other solvers perform similarly in this case). This usually implies that the moment ODE system is too stiff and cannot be solved: the time derivatives grow unboundedly and the solver timestep is being constantly reduced, requiring an ever-increasing number of the solver iterations (hence the maxiters warning).","category":"page"},{"location":"tutorials/common_issues/#References","page":"Common Issues","title":"References","text":"","category":"section"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"[1]: D. Schnoerr, G. Sanguinetti, and R. Grima, \"Comparison of different moment-closure approximations for stochastic chemical kinetics\", The Journal of Chemical Physics 143, 185101 (2015). https://doi.org/10.1063/1.4934990","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"[2]: D. Schnoerr, G. Sanguinetti, and R. Grima, \"Validity conditions for moment closure approximations in stochastic chemical kinetics\", The Journal of Chemical Physics 141, 084103 (2014). https://doi.org/10.1063/1.4892838","category":"page"},{"location":"tutorials/common_issues/","page":"Common Issues","title":"Common Issues","text":"[3]: E. Lakatos, A. Ale, P. D. W. Kirk, and M. P. H. Stumpf, \"Multivariate moment closure techniques for stochastic kinetic models\", The Journal of Chemical Physics 143, 094107 (2015). https://doi.org/10.1063/1.4929837","category":"page"},{"location":"tutorials/parameter_estimation_SDE/#parameter_estimation_SDE","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"","category":"section"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"In this tutorial, we look at the problem of model parameter identification of a diffusion process given timeseries data of its moments. Namely, we use moment closure approximations (MAs) to make the optimisation process more efficient by reducing the model evaluation time. All credit for this tutorial goes to Flemming Holtorf!","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"We consider a noisy variation of the Lotka-Volterra model, describing the interaction between a predator and prey species:","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"beginalign*\n beginbmatrix dx dy endbmatrix = \n beginbmatrix gamma_1 x(t) - gamma_2 x(t) y(t) gamma_4 x(t) y(t) - gamma_3 y(t) - frac12 y(t) endbmatrix dt \n + beginbmatrix gamma_5 x(t) 0 endbmatrix dW_t\nendalign*","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"We can define this system of SDEs using ModelingToolkit as follows:","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"using ModelingToolkit\n\n@variables t, x(t), y(t)\n@parameters γ1, γ2, γ3, γ4, γ5\nγ = [γ1, γ2, γ3, γ4, γ5] \ndrift_eqs = [Differential(t)(x) ~ γ[1] * x - γ[2] * x * y ;\n Differential(t)(y) ~ γ[4] * x * y - γ[3] * y - y*0.5]\ndiff_eqs = [γ[5]*x; 0]\nLV = SDESystem(drift_eqs, diff_eqs, t, [x,y], γ, name = :LV)","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"Next, we generate some data used for the parameter estimation. Namely, we collect timeseries data of means and variances of both species:","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"using DifferentialEquations, DifferentialEquations.EnsembleAnalysis\n\nN_samples = 1000\nTf = 10\nt_data = 0:0.2:Tf\np_true = [γ[1] => 1, γ[2] => 2, γ[3] => 1, γ[4] => 2, γ[5] => 0.1]\nu0 = [1.0, 0.25]\nLV_data = solve(EnsembleProblem(SDEProblem(LV, u0, (0.0, Tf), p_true)), saveat = t_data, trajectories = N_samples)\nmeans, vars = timeseries_steps_meanvar(LV_data)","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"Now we are ready to test if we can estimate the model parameters gamma_1 dotsc gamma_5 solely from the data collected above. We first approach this parameter identification problem using the asymptotically exact approach of estimating the means and variances of the process with ensemble averages. Accordingly, we construct the following loss function:","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"using LinearAlgebra\n\nLV_sde = SDEProblem(LV, u0, (0.0, Tf), zeros(5))\nfunction obj(p)\n prob = remake(LV_sde, p = p)\n sol = solve(EnsembleProblem(prob), saveat = t_data, trajectories = 1000)\n sol_mean, sol_vars = timeseries_steps_meanvar(sol)\n obj = sum(norm(sol_mean[i] - means[i])^2 for i in 1:length(t_data))\n obj += 1e4*sum(norm(sol_vars[i] - vars[i])^2 for i in 1:length(t_data))\n return obj\nend","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"We can use this loss function with any suitable optimisation routine to identify a reasonable choice of the model parameters. For example, we can use a very simple derivative-free optimizer (Nelder-Mead method) implemented in the Optim.jl package. Since a single evaluation of the objective function requires sampling and hence is relatively expensive, we impose the constraint that the optimiser cannot run more than 2 minutes:","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"using Optim\n\npmap = Dict(i => findfirst(isequal(γ[i]), parameters(LV)) for i in 1:5)\np_init = Dict(γ[1] => 1.3, γ[2] => 1.5, γ[3] => 1.4, γ[4] => 2.2, γ[5] => 0.1)\np = [p_init[γ[pmap[i]]] for i in 1:5]\nopt_sampling = Optim.optimize(obj, p, Optim.Options(time_limit = 120))","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"* Status: failure (exceeded time limit of 120.0)\n\n * Candidate solution\n Final objective value: 3.550929e+00\n\n * Found with\n Algorithm: Nelder-Mead\n\n * Convergence measures\n √(Σ(yᵢ-ȳ)²)/n ≰ 1.0e-08\n\n * Work counters\n Seconds run: 121 (vs limit 120)\n Iterations: 139\n f(x) calls: 337","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"We can visualise the moment statistics obtained using the estimated parameters and compare to the true data:","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"using Plots\n\nt_detail = collect(0:0.01:Tf) \nopt_sol = solve(EnsembleProblem(SDEProblem(LV, u0, (0.0, Tf), opt_sampling.minimizer)), saveat = t_detail, trajectories = 1000)\nopt_means, opt_vars = timeseries_steps_meanvar(opt_sol)\n\nmean_comp = scatter(t_data, [m[1] for m in means], color = :blue,\n xlabel = \"time\", ylabel = \"population size\", \n grid = false, title = \"means\", label = \"⟨x⟩ data\")\nscatter!(mean_comp, t_data, [m[2] for m in means], color = :red, label = \"⟨y⟩ data\")\nplot!(mean_comp, t_detail, [m[1] for m in opt_means], linewidth = 2, color = :blue, label = \"⟨x⟩ SDE model\")\nplot!(mean_comp, t_detail, [m[2] for m in opt_means], linewidth = 2, color = :red, label = \"⟨y⟩ SDE model\")\n\nvar_comp = scatter(t_data, [v[1] for v in vars], color = :blue, grid = false,\n xlabel = \"time\", title = \"variances\", label = \"σ²(x) data\", legend = :topleft)\nscatter!(var_comp, t_data, [v[2] for v in vars], color = :red, label = \"σ²(y) data\")\nplot!(var_comp, t_detail, [v[1] for v in opt_vars], color = :blue, label = \"σ²(x) SDE model\")\nplot!(var_comp, t_detail, [v[2] for v in opt_vars], color = :red, label = \"σ²(y) SDE model\")\n\nplot(mean_comp, var_comp, size = (1200.0, 400.0))","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"(Image: LV SDE fig1)","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"We observe that the identified parameters match the data reasonably well. However, one may suspect that the optimiser is converging to a local minimum as the fit is not perfect.","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"Now we approach the same model identification problem via MAs in the hope of cutting down model evaluation cost, allowing us to identify better parameters in the same (or less) time. To that end, we construct an approximation of the moment dynamics of the process assuming that the distribution of the system state is approximately log-normal over the simulation horizon (using log-normal MA). Then we can implement a simple loss function by comparing the moments predicted by the approximate model with those obtained from data:","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"using MomentClosure\n\nLV_moments = moment_closure(generate_raw_moment_eqs(LV, 2), \"log-normal\")\nu0map = deterministic_IC(u0, LV_moments)\nclosed_moment_prob = ODEProblem(LV_moments, u0map, (0.0, Tf), zeros(5))\nfunction obj_MCA(p)\n prob = remake(closed_moment_prob; p=p)\n sol = solve(prob, Tsit5(), saveat = t_data)\n if sol.retcode == ReturnCode.Success\n obj = sum(norm(sol.u[i][1:2] - means[i])^2 for i in 1:length(t_data))\n obj += 1e4*sum((sol.u[i][3] - sol.u[i][1]^2 - vars[i][1])^2 for i in 1:length(t_data))\n obj += 1e4*sum((sol.u[i][5] - sol.u[i][2]^2 - vars[i][2])^2 for i in 1:length(t_data))\n else\n obj = 1e6\n end\n return obj\nend","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"As before, any suitable optimisation routine can now be used to identify parameter values that result in a match between data and model prediction:","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"pmap = Dict(i => parameters(LV_moments.odes)[i] for i in 1:5)\np_init = Dict(γ[1] => 1.3, γ[2] => 1.5, γ[3] => 1.4, γ[4] => 2.2, γ[5] => 0.1)\np = [p_init[pmap[i]] for i in 1:5]\nopt_MCA = Optim.optimize(obj_MCA, p, Optim.Options(time_limit = min(120, opt_sampling.time_run)))","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"* Status: success\n\n * Candidate solution\n Final objective value: 1.160452e+00\n\n * Found with\n Algorithm: Nelder-Mead\n\n * Convergence measures\n √(Σ(yᵢ-ȳ)²)/n ≤ 1.0e-08\n\n * Work counters\n Seconds run: 0 (vs limit 120)\n Iterations: 362\n f(x) calls: 751","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"By visualising the results we see that indeed the identified parameters now provide a better match between data and the model, even if the original SDE model is being evaluated (note that the moment equations using log-normal MA provide a reasonably accurate approximation to the ensemble averages):","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"p_opt = [pmap[i] => opt_MCA.minimizer[i] for i in 1:5]\nt_detail = collect(0:0.01:Tf) \nopt_sol = solve(EnsembleProblem(SDEProblem(LV, u0, (0.0, Tf), p_opt)), saveat = t_detail, trajectories = 1000)\nopt_means = [timestep_mean(opt_sol, i) for i in 1:length(t_detail)]\nopt_vars = [timestep_meanvar(opt_sol, i)[2] for i in 1:length(t_detail)]\n\nopt_sol_approx = solve(ODEProblem(LV_moments, u0map, (0.0, Tf), p_opt), saveat = t_detail)\n\nmean_comp = scatter(t_data, [m[1] for m in means], color = :blue,\n xlabel = \"time\", ylabel = \"population size\", \n grid = false, title = \"means\", label = \"⟨x⟩ data\")\nscatter!(mean_comp, t_data, [m[2] for m in means], color = :red, label = \"⟨y⟩ data\")\nplot!(mean_comp, t_detail, [m[1] for m in opt_means], linewidth = 2, color = :blue, label = \"⟨x⟩ SDE model\")\nplot!(mean_comp, t_detail, [m[2] for m in opt_means], linewidth = 2, color = :red, label = \"⟨y⟩ SDE model\")\nplot!(mean_comp, t_detail, [m[1] for m in opt_sol_approx.u], linewidth = 2, color = :black, linestyle = :dash, label = \"log-normal MA\")\nplot!(mean_comp, t_detail, [m[2] for m in opt_sol_approx.u], linewidth = 2, color = :black, linestyle = :dash, label = nothing)\n\nvar_comp = scatter(t_data, [v[1] for v in vars], color = :blue,\n xlabel = \"time\", title = \"variances\", grid = false, label = \"σ²(x) data\", legend = :topleft)\nscatter!(var_comp, t_data, [v[2] for v in vars], color = :red, label = \"σ²(y) data\")\nplot!(var_comp, t_detail, [v[1] for v in opt_vars], color = :blue, label = \"σ²(x) SDE model\")\nplot!(var_comp, t_detail, [v[2] for v in opt_vars], color = :red, label = \"σ²(y) SDE model\")\nplot!(var_comp, t_detail, [m[3] - m[1]^2 for m in opt_sol_approx.u], linewidth = 2, color = :black, linestyle = :dash, label = \"log-normal MA\")\nplot!(var_comp, t_detail, [m[5] - m[2]^2 for m in opt_sol_approx.u], linewidth = 2, color = :black, linestyle = :dash, label = nothing)\n\nplot(mean_comp, var_comp, size = (1200.0, 400.0))","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"(Image: LV SDE fig2)","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"Finally, note that the parameter estimation is much faster using moment equations (compare to 120 s using the basic approach)","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"opt_MCA.time_run","category":"page"},{"location":"tutorials/parameter_estimation_SDE/","page":"Parameter Estimation of Diffusion Processes","title":"Parameter Estimation of Diffusion Processes","text":"0.10686397552490234","category":"page"},{"location":"tutorials/using_momentclosure_SDE/#tutorial_SDE","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"","category":"section"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"In the previous tutorial, we have shown how to generate and close moment equations for chemical reaction networks. Similarly, MomentClosure can be applied to systems of stochastic differential equations (SDEs) and here we demonstrate this functionality by working through a couple of practical examples. Namely, we consider two specific models from a relevant paper by Ghusinga et al. (2017) [1], 1) the Van der Pol oscillator and 2) a swinging pendulum, and apply moment closure approximations (MA) to reproduce some of the published results. For the theory behind the SDE moment expansion see here.","category":"page"},{"location":"tutorials/using_momentclosure_SDE/#Model-1","page":"Moment Equations from SDEs","title":"Model 1","text":"","category":"section"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"The deterministic Van der Pol oscillator is described by [1]:","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"beginalign*\n fracd^2 xdt^2 - epsilon(1-x^2)fracdxdt + omega_n^2 x = Acos(omega_g t)\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"where epsilon is the bifurcation parameter, omega_n the natural frequency, omega_g the force frequency and A the force amplitude. We formulate a stochastic equivalent of this system by assuming that the force is noisy and taking x_1 = x and x_2 = fracdxdt, so that","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"beginalign*\n dx_1 = x_2 dt \n dx_2 = left( epsilon(1-x_1^2) x_2 - omega_n^2 x_1 right)dt + Acos(omega_g t)dt + A dw_t\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"In Julia, systems of SDEs can be conveniently described using ModelingToolkit.jl that provides an SDESystem type. Defining such models is straightforward (as in this example) and in our case is done as follows:","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"using ModelingToolkit\n\n@variables t, x₁(t), x₂(t)\n@parameters ϵ, ω_n, ω_g, A\n\ndrift_eqs = [Differential(t)(x₁) ~ x₂;\n Differential(t)(x₂) ~ ϵ*(1-x₁^2)*x₂ - ω_n^2*x₁ + A*cos(ω_g*t)]\ndiff_eqs = [0; A]\n\nvdp_model = SDESystem(drift_eqs, diff_eqs, t, [x₁, x₂], [ϵ, ω_n, ω_g, A], name = :VdP)\n\nps = [ϵ => 0.1, ω_n => 120*pi, ω_g => 120*pi, A => 2.5] # parameter values\nu0 = [0.1, 0.1] # initial conditions\ntspan = (0., 0.1) # simulation time limit","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"We can now easily extract the raw moment equations up to second order using MomentClosure","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"using MomentClosure, Latexify\n\nmoment_eqs = generate_raw_moment_eqs(vdp_model, 2) \nlatexify(moment_eqs)","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"beginalign*\nfracdmu_10dt = mu_01 \nfracdmu_01dt = A cosleft( t omega_g right) + epsilon mu_01 - epsilon mu_21 - omega_n^2 mu_10 \nfracdmu_20dt = 2 mu_11 \nfracdmu_11dt = epsilon mu_11 + A mu_10 cosleft( t omega_g right) + mu_02 - epsilon mu_31 - omega_n^2 mu_20 \nfracdmu_02dt = A^2 + 2 epsilon mu_02 + 2 A mu_01 cosleft( t omega_g right) - 2 omega_n^2 mu_11 - 2 epsilon mu_22\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"The obtained moment equations are equivalent to the published ones (except for a single term in mu_11 equation as there is a typo in the paper), giving some confidence that everything works as intended!","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"Note that the moment equations are not closed as there are two fourth order moments involved, mu_31 and mu_22, and hence we need to resort to MAs. We proceed to apply the derivative matching approximation and solve the system of ODEs as follows:","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"using DifferentialEquations\n\nclosed_eqs = moment_closure(moment_eqs, \"derivative matching\")\n\nu0map = deterministic_IC(u0, closed_eqs)\noprob = ODEProblem(closed_eqs, u0map, tspan, ps)\n\nsol_MA = solve(oprob, Tsit5(), saveat=0.0001)","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"Finally, we can also use DifferentialEquations to solve the SDEs for many trajectories and compare the ensemble statistics to the derivative matching approximation (getting a great match):","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"using DifferentialEquations.EnsembleAnalysis, Plots\n\nprob_SDE = SDEProblem(vdp_model, u0, tspan, ps)\n@time sol_SDE = solve(EnsembleProblem(prob_SDE), SRIW1(), saveat=0.0001, trajectories=100)\nmeans_SDE = timeseries_steps_mean(sol_SDE)\n\nplot(sol_MA.t, sol_MA[1, :], lw=2, label=\"MA\", ylabel=\"⟨x₁⟩\", xlabel=\"time\")\nplot!(sol_MA.t, means_SDE[1, :], lw=2, label=\"SDE\", linecolor=:red,\n linestyle=:dash, background_color_legend=nothing, legend=:topright, grid=false)","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"(Image: Model 1 SDE)","category":"page"},{"location":"tutorials/using_momentclosure_SDE/#Model-2","page":"Moment Equations from SDEs","title":"Model 2","text":"","category":"section"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"We next consider a simple pendulum, deterministically described as [1]","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"beginalign*\n fracd^2thetadt^2 + frackmfracdthetadt + fracgl sintheta = 0\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"where theta is the angular displacement, m the mass of the pendulum, g the gravitational acceleration constant, l the pendulum length and k the friction constant. The stochasticity is modelled as a white noise term arising due to pendulum randomly interacting with air molecules (assumed to be inversely proportional to m). Letting x_1 = theta and x_2 = fracdthetadt we write down the SDE as:","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"beginalign*\n dx_1 = x_2 dt \n dx_2 = left( -frackmx_2 - fracglsinx_1 right)dt + frac1mdw_t\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"Using ModelingToolkit again we can define the model as","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"@variables t, x₁(t), x₂(t)\n@parameters k, l, m, g\n\ndrift_eqs = [Differential(t)(x₁) ~ x₂;\n Differential(t)(x₂) ~ -k/m*x₂ - g/l*sin(x₁)]\ndiff_eqs = [0; 1/m]\n\npendulum_model = SDESystem(drift_eqs, diff_eqs, t, [x₁, x₂], [k, l, m, g], name = :pendulum)\nps = [k => 10, m => 10, l => 10, g => 10]\nu0 = [3, 3]\ntspan = (0., 15.)","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"As the drift term is non-polynomial, we can no longer write down the raw moment equations in a straightforward manner. Nevertheless, we can expand the expressions up to a certain Taylor expansion order q and generate the corresponding time-evolution equations for the means and higher order central moments—this situation is identical to moment expansion for chemical reaction networks with non-polynomial propensities. Hence we can obtain the equations for the means and variances with q=3:","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"moment_eqs = generate_central_moment_eqs(pendulum_model, 2, 3) \nlatexify(moment_eqs) # the output here is maybe not the most visually pleasing","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"beginalign*\nfracdmu_10dt = mu_01 \nfracdmu_01dt = fracleft( - k right) mu_01m + fracleft( - g right) sinleft( mu_10 right)l + fracfrac16 g M_30 cosleft( mu_10 right)l + fracfrac12 g M_20 sinleft( mu_10 right)l \nfracdM_20dt = 2 M_11 \nfracdM_11dt = fracleft( - k right) M_11m + fracleft( - g right) M_20 cosleft( mu_10 right)l + fracfrac12 g M_30 sinleft( mu_10 right)l + M_02 \nfracdM_02dt = fracfrac11m^2 + frac-2 k M_02m + fracg M_21 sinleft( mu_10 right)l + frac-2 g M_11 cosleft( mu_10 right)l\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"We can now approximate the moment equations using gamma closure, solve the ODEs numerically and compare the predictions to true SDE solution, finding good agreement:","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"closed_eqs = moment_closure(moment_eqs, \"gamma\")\n\nu0map = deterministic_IC(u0, closed_eqs)\noprob = ODEProblem(closed_eqs, u0map, tspan, ps)\nsol_MA = solve(oprob, Tsit5(), saveat=0.01)\n\nprob_SDE = SDEProblem(pendulum_model, u0, tspan, ps)\nsol_SDE = solve(EnsembleProblem(prob_SDE), SRIW1(), saveat=0.01, trajectories=100)\nmeans_SDE = timeseries_steps_mean(sol_SDE)\n\nplot(sol_MA.t, sin.(sol_MA[1, :]), lw=2, label=\"MA\", ylabel=\"sin(⟨x₁⟩)\", xlabel=\"time\")\nplot!(sol_MA.t, sin.(means_SDE[1, :]), lw=2, label=\"SDE\", linecolor=:red,\n linestyle=:dash, background_color_legend=nothing, legend=:topright, grid=false)","category":"page"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"(Image: Model 2 SDE)","category":"page"},{"location":"tutorials/using_momentclosure_SDE/#References","page":"Moment Equations from SDEs","title":"References","text":"","category":"section"},{"location":"tutorials/using_momentclosure_SDE/","page":"Moment Equations from SDEs","title":"Moment Equations from SDEs","text":"[1]: K. R. Ghusinga, M. Soltani, A. Lamperski, S. V. Dhople, and A. Singh, \"Approximate moment dynamics for polynomial and trigonometric stochastic systems\", IEEE 56th Annual Conference on Decision and Control (2017). https://doi.org/10.1109/CDC.2017.8263922","category":"page"},{"location":"tutorials/using_momentclosure/#main_tutorial","page":"Using MomentClosure","title":"Using MomentClosure","text":"","category":"section"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"This tutorial is an introduction to using MomentClosure to define chemical reaction network models, generate the corresponding moment equations, apply moment closure approximations and finally solve the resulting system of ODEs. To demonstrate this functionality, we will consider a specific case of an oscillatory chemical system known as the Brusselator, characterised by the reactions","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"beginalign*\n2X + Y stackrelc_1rightarrow 3X \nX stackrelc_2rightarrow Y \n undersetc_4stackrelc_3rightleftharpoons X\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"We have chosen this particular model to start with as it has been studied with different moment closures before by Schnoerr et al. (2015) and so it is useful as a reference point. The plots of moment trajectories we obtain in this tutorial fully reproduce some of the figures published in the paper, hence (partially) proving the validity of our implementation.","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The terminology and the notation used throughout is consistent with the Theory section of the docs and we advise giving it a skim-through.","category":"page"},{"location":"tutorials/using_momentclosure/#Model-Initialisation","page":"Using MomentClosure","title":"Model Initialisation","text":"","category":"section"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Catalyst.jl provides a comprehensive interface to modelling chemical reaction networks in Julia and can be used to construct models fully-compatible with MomentClosure. For more details on how to do so we recommend reading Catalyst's tutorial. This way, the Brusselator can be defined as:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"using Catalyst\nrn = @reaction_network begin\n # including system-size parameter Ω\n @parameters c₁ c₂ c₃ c₄ Ω\n (c₁/Ω^2), 2X + Y → 3X\n (c₂), X → Y\n (c₃*Ω, c₄), 0 ↔ X\nend","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The returned rn is an instance of ModelingToolkit.ReactionSystem. The net stoichiometry matrix and an array of the corresponding propensities, if needed, can be extracted directly from the model using Catalyst.netstoichmat and MomentClosure function propensities respectively.","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Note that MomentClosure also supports systems containing geometrically distributed reaction products that can be defined using Catalyst—see this tutorial for more details.","category":"page"},{"location":"tutorials/using_momentclosure/#Generating-Moment-Equations","page":"Using MomentClosure","title":"Generating Moment Equations","text":"","category":"section"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"We can now obtain the moment equations. The system follows the law of mass action, i.e., all propensity functions are polynomials in molecule numbers X(t) and Y(t), and so we can generate either raw or central moment equations, as described in the Theory section on moment expansion.","category":"page"},{"location":"tutorials/using_momentclosure/#Raw-Moment-Equations","page":"Using MomentClosure","title":"Raw Moment Equations","text":"","category":"section"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Let's start with the raw moment equations which we choose to generate up to second order (m=2):","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"using MomentClosure\nraw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=false)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Note that we have set combinatoric_ratelaw=false in order to ignore the factorial scaling factors which Catalyst adds to mass-action reactions. The function generate_raw_moment_eqs returns an instance of RawMomentEquations that contains a ModelingToolkit.ODESystem composed of all the moment equations (accessed by raw_eqs.odes).","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"We can use Latexify to look at the generated moment equations:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"using Latexify\nlatexify(raw_eqs)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"beginalign*\nfracdmu_1 0dt = c_3 Omega + c_1 Omega^-2 mu_2 1 - c_2 mu_1 0 - c_4 mu_1 0 - c_1 Omega^-2 mu_1 1 \nfracdmu_0 1dt = c_2 mu_1 0 + c_1 Omega^-2 mu_1 1 - c_1 Omega^-2 mu_2 1 \nfracdmu_2 0dt = c_2 mu_1 0 + c_3 Omega + c_4 mu_1 0 + 2 c_3 Omega mu_1 0 + 2 c_1 Omega^-2 mu_3 1 - 2 c_2 mu_2 0 - 2 c_4 mu_2 0 - c_1 Omega^-2 mu_1 1 - c_1 Omega^-2 mu_2 1 \nfracdmu_1 1dt = c_2 mu_2 0 + c_3 Omega mu_0 1 + c_1 Omega^-2 mu_1 1 + c_1 Omega^-2 mu_2 2 - c_2 mu_1 0 - c_2 mu_1 1 - c_4 mu_1 1 - c_1 Omega^-2 mu_1 2 - c_1 Omega^-2 mu_3 1 \nfracdmu_0 2dt = c_2 mu_1 0 + 2 c_2 mu_1 1 + c_1 Omega^-2 mu_2 1 + 2 c_1 Omega^-2 mu_1 2 - c_1 Omega^-2 mu_1 1 - 2 c_1 Omega^-2 mu_2 2\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The raw moments are defined as","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"mu_ij(t) = langle X(t)^i Y(t)^j rangle","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"where langle rangle denote the expectation value and we have explicitly included the time-dependence for completeness (made implicit in the formatted moment equations). Note that the ordering of species (X first and Y second) is consistent with the order these variables appear within the Catalyst.@reaction_network macro. The ordering can also be checked using Catalyst.speciesmap function:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"speciesmap(rn)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Dict{Term{Real},Int64} with 2 entries:\n X(t) => 1\n Y(t) => 2","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Coming back to the generated moment equations, we observe that they depend on higher-order moments. For example, the ODE for mu_02 depends on third order moments μ_12 and μ_21 and the fourth order moment mu_22. Consider the general case of raw moment equations: if a network involves reactions that are polynomials (in molecule numbers) of at most order k, then its m^textth order moment equations will depend on moments up to order m+k-1. Hence the relationship seen above is expected as the Brusselator involves a trimolecular reaction whose corresponding propensity function is a third order polynomial in X(t) and Y(t). The number denoting the highest order of moments encountered in the generated RawMomentEquations can also be accessed as raw_eqs.q_order (returning 4 in this case).","category":"page"},{"location":"tutorials/using_momentclosure/#Central-Moment-Equations","page":"Using MomentClosure","title":"Central Moment Equations","text":"","category":"section"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The corresponding central moment equations can also be easily generated:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"central_eqs = generate_central_moment_eqs(rn, 2, combinatoric_ratelaws=false)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Note that in case of non-polynomial propensity functions the Taylor expansion order q must also be specified, see the P53 system example for more details. Luckily, the Brusselator contains only mass-action reactions and hence q is automatically determined by the highest order (polynomial) propensity. The function generate_central_moment_eqs returns an instance of CentralMomentEquations. As before, we can visualise the central moment equations:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"latexify(central_eqs)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"beginalign*\nfracdmu_1 0dt = c_3 Omega + c_1 Omega^-2 M_2 1 + c_1 Omega^-2 mu_1 0^2 mu_0 1 + c_1 Omega^-2 M_2 0 mu_0 1 + 2 c_1 Omega^-2 M_1 1 mu_1 0 - c_2 mu_1 0 - c_4 mu_1 0 - c_1 Omega^-2 M_1 1 - c_1 Omega^-2 mu_0 1 mu_1 0 \nfracdmu_0 1dt = c_2 mu_1 0 + c_1 Omega^-2 M_1 1 + c_1 Omega^-2 mu_0 1 mu_1 0 - c_1 Omega^-2 M_2 1 - c_1 Omega^-2 mu_1 0^2 mu_0 1 - c_1 Omega^-2 M_2 0 mu_0 1 - frac21 c_1 Omega^-2 M_1 1 mu_1 0 \nfracdM_2 0dt = c_3 Omega + c_2 mu_1 0 + c_4 mu_1 0 + 2 c_1 Omega^-2 M_3 1 + c_1 Omega^-2 mu_1 0^2 mu_0 1 + 2 c_1 Omega^-2 mu_1 0^2 M_1 1 + 2 c_1 Omega^-2 M_3 0 mu_0 1 + 4 c_1 Omega^-2 M_2 1 mu_1 0 + 4 c_1 Omega^-2 M_2 0 mu_0 1 mu_1 0 - 2 c_2 M_2 0 - 2 c_4 M_2 0 - c_1 Omega^-2 M_1 1 - c_1 Omega^-2 M_2 1 - c_1 Omega^-2 M_2 0 mu_0 1 - c_1 Omega^-2 mu_0 1 mu_1 0 \nfracdM_1 1dt = c_2 M_2 0 + c_1 Omega^-2 M_1 1 + c_1 Omega^-2 M_2 2 + c_1 Omega^-2 mu_1 0^2 M_0 2 + c_1 Omega^-2 M_2 1 mu_0 1 + c_1 Omega^-2 mu_0 1 mu_1 0 + 2 c_1 Omega^-2 M_1 2 mu_1 0 + 2 c_1 Omega^-2 M_1 1 mu_0 1 mu_1 0 - c_2 M_1 1 - c_4 M_1 1 - c_2 mu_1 0 - c_1 Omega^-2 M_1 2 - c_1 Omega^-2 M_3 1 - c_1 Omega^-2 mu_1 0^2 M_1 1 - c_1 Omega^-2 mu_1 0^2 mu_0 1 - c_1 Omega^-2 M_0 2 mu_1 0 - c_1 Omega^-2 M_1 1 mu_0 1 - c_1 Omega^-2 M_3 0 mu_0 1 - c_1 Omega^-2 M_1 1 mu_1 0 - 2 c_1 Omega^-2 M_2 1 mu_1 0 - 2 c_1 Omega^-2 M_2 0 mu_0 1 mu_1 0 \nfracdM_0 2dt = c_2 mu_1 0 + 2 c_2 M_1 1 + c_1 Omega^-2 M_2 1 + 2 c_1 Omega^-2 M_1 2 + c_1 Omega^-2 mu_1 0^2 mu_0 1 + c_1 Omega^-2 M_2 0 mu_0 1 + 2 c_1 Omega^-2 M_0 2 mu_1 0 + 2 c_1 Omega^-2 M_1 1 mu_0 1 + 2 c_1 Omega^-2 M_1 1 mu_1 0 - c_1 Omega^-2 M_1 1 - 2 c_1 Omega^-2 M_2 2 - 2 c_1 Omega^-2 mu_1 0^2 M_0 2 - c_1 Omega^-2 mu_0 1 mu_1 0 - 2 c_1 Omega^-2 M_2 1 mu_0 1 - 4 c_1 Omega^-2 M_1 2 mu_1 0 - 4 c_1 Omega^-2 M_1 1 mu_0 1 mu_1 0\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Unfortunately, central moment equations often take a visually painful form. Note that the first two ODEs, as before, indicate the means, and the central moments are denoted as","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"M_ij(t) = langle (X(t)-mu_10(t))^i (Y(t)-mu_01(t))^j rangle","category":"page"},{"location":"tutorials/using_momentclosure/#Applying-Moment-Closure","page":"Using MomentClosure","title":"Applying Moment Closure","text":"","category":"section"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"As observed above, the moment equations of the Brusselator are coupled and depend on higher order moments—we have an infinite hierarchy of ODEs in our hands which cannot be solved directly and requires approximate treatment. One way of approaching the problem is to apply moment closure approximations (MAs), in which higher order moments are expressed as functions of lower order moments, thus effectively truncating the hierarchy and enabling a numerical solution. A variety of MAs have been proposed in literature and are implemented in MomentClosure.jl, see the Theory section on MAs for more details.","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Let's apply normal closure to the raw moment equations raw_eqs we have generated earlier using moment_closure function:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"closed_raw_eqs = moment_closure(raw_eqs, \"normal\")","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The function returns ClosedMomentEquations that consists of both the ModelingToolkit.ODESystem containing all closed moment equations as well as the specific closure functions for each higher order raw moments. We can use Latexify again to look at the closed ODEs:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"latexify(closed_raw_eqs)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"beginalign*\nfracdmu_10dt = c_3 Omega + c_1 mu_01 mu_20 Omega^-2 + 2 c_1 mu_10 mu_11 Omega^-2 - c_2 mu_10 - c_4 mu_10 - c_1 mu_11 Omega^-2 - 2 c_1 mu_01 Omega^-2 mu_10^2 \nfracdmu_01dt = c_2 mu_10 + c_1 mu_11 Omega^-2 + 2 c_1 mu_01 Omega^-2 mu_10^2 - c_1 mu_01 mu_20 Omega^-2 - 2 c_1 mu_10 mu_11 Omega^-2 \nfracdmu_20dt = c_2 mu_10 + c_3 Omega + c_4 mu_10 + 2 c_3 Omega mu_10 + 2 c_1 mu_01 Omega^-2 mu_10^2 + 6 c_1 mu_11 mu_20 Omega^-2 - 2 c_2 mu_20 - 2 c_4 mu_20 - c_1 mu_11 Omega^-2 - c_1 mu_01 mu_20 Omega^-2 - 4 c_1 mu_01 Omega^-2 mu_10^3 - 2 c_1 mu_10 mu_11 Omega^-2 \nfracdmu_11dt = c_2 mu_20 + c_1 mu_11 Omega^-2 + c_3 Omega mu_01 + c_1 mu_02 mu_20 Omega^-2 + 2 c_1 Omega^-2 mu_11^2 + 2 c_1 mu_01 Omega^-2 mu_10^3 + 2 c_1 mu_10 Omega^-2 mu_01^2 - c_2 mu_10 - c_2 mu_11 - c_4 mu_11 - 2 c_1 mu_01 mu_11 Omega^-2 - c_1 mu_02 mu_10 Omega^-2 - 3 c_1 mu_11 mu_20 Omega^-2 - 2 c_1 Omega^-2 mu_01^2 mu_10^2 \nfracdmu_02dt = c_2 mu_10 + 2 c_2 mu_11 + c_1 mu_01 mu_20 Omega^-2 + 4 c_1 mu_01 mu_11 Omega^-2 + 2 c_1 mu_02 mu_10 Omega^-2 + 2 c_1 mu_10 mu_11 Omega^-2 + 4 c_1 Omega^-2 mu_01^2 mu_10^2 - c_1 mu_11 Omega^-2 - 4 c_1 Omega^-2 mu_11^2 - 2 c_1 mu_01 Omega^-2 mu_10^2 - 2 c_1 mu_02 mu_20 Omega^-2 - 4 c_1 mu_10 Omega^-2 mu_01^2\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The closure functions can also be displayed by adding :closure argument:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"latexify(closed_raw_eqs, :closure)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"beginalign*\nmu_21 = mu_01 mu_20 + 2 mu_10 mu_11 - 2 mu_01 mu_10^2 \nmu_12 = mu_02 mu_10 + 2 mu_01 mu_11 - 2 mu_10 mu_01^2 \nmu_31 = mu_01 mu_30 + 6 mu_01 mu_10^3 + 3 mu_10 mu_21 + 3 mu_11 mu_20 - 6 mu_11 mu_10^2 - 6 mu_01 mu_10 mu_20 \nmu_22 = mu_02 mu_20 + 2 mu_11^2 + 2 mu_01 mu_21 + 2 mu_10 mu_12 + 6 mu_01^2 mu_10^2 - 2 mu_02 mu_10^2 - 2 mu_20 mu_01^2 - 8 mu_01 mu_10 mu_11\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Similarly, we can close central moment equations using","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"closed_central_eqs = moment_closure(central_eqs, \"normal\")","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"and print out the corresponding closure functions:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"latexify(closed_central_eqs, :closure)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"beginalign*\nM_30 = 0 \nM_21 = 0 \nM_12 = 0 \nM_31 = 3 M_11 M_20 \nM_22 = M_02 M_20 + 2 M_11^2\nendalign*","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Higher order central moments under normal closure take a rather simple form compared to their raw moment equivalents. That can be expected due to the relationship between central moments and cumulants, on which the closure is based.","category":"page"},{"location":"tutorials/using_momentclosure/#Solving-Moment-Equations","page":"Using MomentClosure","title":"Solving Moment Equations","text":"","category":"section"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The closed moment equations can be solved numerically using DifferentialEquations.jl that provides a variety of highly-efficient solvers and analysis tools. In order to do so, first we need to specify the values of all system parameters, the initial condition and the timespan to solve over. Then the ModelingToolkit.ODESystem corresponding to the moment equations can be directly converted into an ODEProblem which can finally be solved. Let's go through the procedure step-by-step for the closed raw moment equations (closed_raw_eqs). Most of what is covered below is closely based on this Catalyst tutorial.","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"We start with the parameters. Note that they are ordered as they appear after the end statement in the @reaction_network macro and this ordering can also be checked using the paramsmap function:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"paramsmap(rn)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Dict{Sym{ModelingToolkit.Parameter{Real}},Int64} with 5 entries:\n c₃ => 3\n Ω => 5\n c₄ => 4\n c₂ => 2\n c₁ => 1","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"We can now create a vector of parameter values as:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"# parameters [c₁, c₂, c₃, c₄, Ω]\np = [0.9, 2, 1, 1, 100]","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Next, we can specify the initial condition. Usually when working with moment equations we consider deterministic initial conditions so that the molecule numbers at initial time take the specified integer values with probability one. We can define the initial molecule numbers as X(t=0) = X_0 and Y(t=0) = Y_0. Probability one implies that initially the means will be equal to the molecule numbers, i.e., μ_10(t=0) = X_0 and μ_01(t=0) = Y_0, whereas all higher order raw moments will be products of the corresponding powers of the means, e.g., μ_21 = X_0^2 Y_0. Note that all central moments would be set to zero in this case. To make life easier we use deterministic_IC function which, given the initial molecule numbers, automatically constructs the variable mapping under deterministic initial conditions:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"# initial molecule numbers [X, Y] (order as in speciesmap(rn))\nu₀ = [1, 1]\nu₀map = deterministic_IC(u₀, closed_raw_eqs)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The next ingredient, the time interval to solve on, can be specified simply as:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"tspan = (0., 100.)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Now we are able to create the corresponding ODEProblem:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Finally, we have everything we need to solve the raw moment equations which can be done using any ODE solver implemented within DifferentialEquations.jl. We use the default Tsit5() solver and then plot the obtained mean molecule numbers:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"# using only ODE solvers from DifferentialEquations (faster to load)\nusing OrdinaryDiffEq\nsol = solve(oprob, Tsit5(), saveat=0.1)\n\nusing Plots\nplot(sol, idxs=[1,2], lw=2)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"(Image: Brusselator means 1)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The obtained moment dynamics show damped oscillations which is the expected averaged behaviour of the Brusselator in a vast swathe of parameter space [1]. However, to establish more clearly how well a second order moment expansion with normal moment closure performs for this system and this specific set of parameters, we can compare the resulting moment trajectories to the true moment estimates obtained using Gillespie's Stochastic Simulation Algorithm (SSA).","category":"page"},{"location":"tutorials/using_momentclosure/#Stochastic-Simulation","page":"Using MomentClosure","title":"Stochastic Simulation","text":"","category":"section"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"To run the SSA for a given reaction network, we build a JumpProcesses (formerly known as DiffEqJump) JumpProblem using Gillespie's Direct method. Note that other SSA variants are also available, see the documentation. Moreover, in order to run many realisations of the jump process, we define a corresponding EnsembleProblem. All of this can be done as follows:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"using JumpProcesses\n\n# convert ReactionSystem into JumpSystem\njsys = convert(JumpSystem, rn, combinatoric_ratelaws=false)\n\n# create a DiscreteProblem encoding that the molecule numbers are integer-valued\ndprob = DiscreteProblem(jsys, u₀, tspan, p) # same parameters as defined earlier\n\n# create a JumpProblem: specify Gillespie's Direct Method as the solver\n# and SET save_positions to (false, false) as otherwise time of each\n# reaction occurence would be saved (complicating moment estimates)\njprob = JumpProblem(jsys, dprob, Direct(), save_positions=(false, false))\n\n# define an EnsembleProblem to simulate multiple trajectories\nensembleprob = EnsembleProblem(jprob)\n\n# simulate 10000 SSA trajectories\n@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.1, trajectories=10000)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"Now we use the DifferentialEquations ensemble statistics tools to calculate the SSA mean values and plot them:","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"using DiffEqBase.EnsembleAnalysis\n\nmeans_SSA = timeseries_steps_mean(sol_SSA)\nplot!(means_SSA, lw=2, labels=[\"SSA μ₁₀(t)\" \"SSA μ₀₁(t)\"], linestyle=:dash,\n linecolor=[1 2], background_color_legend=nothing, legend=:bottomright)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"(Image: Brusselator SSA 1)","category":"page"},{"location":"tutorials/using_momentclosure/","page":"Using MomentClosure","title":"Using MomentClosure","text":"The comparison to the SSA reveals that the second-order moment expansion using normal closure captures the correct qualitative behaviour of the Brusselator and provides reasonably accurate moment estimates given this particular parameter set. Note, however, that moment closure approximations can lead to unphysical results and suffer from numerical instabilities, please see the Common Issues tutorial for more details.","category":"page"},{"location":"#MomentClosure","page":"Home","title":"MomentClosure","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"MomentClosure.jl is a tool to automatically obtain time-evolution equations of moments up to an arbitrary order for virtually any chemical reaction network or system of stochastic differential equations (SDEs), implementing a wide array of moment closure approximations commonly used in stochastic biochemical kinetics [1]. MomentClosure is (attempted to be) fairly well-integrated within the broader Julia ecosystem utilising a number of familiar packages:","category":"page"},{"location":"","page":"Home","title":"Home","text":"MomentClosure can be immediately applied to reaction network models defined using Catalyst and SDE systems built with ModelingToolkit.\nMoment equations are generated as a ModelingToolkit ODESystem (with some extra help from Symbolics and SymbolicUtils).\nThe resulting ODESystem can be solved using any DifferentialEquations ODE solvers, enabling further study of the system using parameter estimation, sensitivity analysis and bifurcation analysis tools.","category":"page"},{"location":"#Features","page":"Home","title":"Features","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Chemical reaction networks containing any number of molecular species and reactions with any type of smooth propensity functions are supported. Models can be defined using Catalyst as ModelingToolkit.ReactionSystem.\nAdded support for reaction networks involving reaction products that are geometrically distributed random variables. An example of such network is an autoregulatory gene network with bursty protein production where the burst size follows a geometric distribution, see this example for more details.\nEquations describing the time evolution of means and central moments of the number of molecules of each species in the system can be generated up to arbitrary order [2, 3]. Note that non-polynomial propensity functions are Taylor expanded to a specified order. Raw moment equations can also be generated for mass-action systems (where all propensity functions are polynomials). \nSDE systems defined as ModelingToolkit.SDESystem are supported (big thanks to @FHoltorf). Similarly to reaction networks with non-polynomial propensities, non-polynomial drift and diffusion coefficients are Taylor expanded.\nCurrently implemented moment closure approximations include:\nzero (central-moment neglect) closure [4, 5]\nnormal closure [4]\npoisson closure [4]\nlog-normal closure [5]\ngamma closure [5]\nderivative matching [6]\nconditional gaussian closure [7]\nconditional derivative matching [7]\nlinear mapping approximation [8]\nMoment equations are constructed as a ModelingToolkit.ODESystem that can be solved using any DifferentialEquations ODE solver. Moreover, parameter estimation, sensitivity analysis and bifurcation analysis tools can be applied to further study the resulting system of equations.\nLatexify can be used to generate LaTeX expressions of the corresponding moment equations.","category":"page"},{"location":"#Installation","page":"Home","title":"Installation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"MomentClosure can be installed through the Julia package manager:","category":"page"},{"location":"","page":"Home","title":"Home","text":"]add MomentClosure\nusing MomentClosure","category":"page"},{"location":"#Citation","page":"Home","title":"Citation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"If you use MomentClosure in your work, please cite our paper:","category":"page"},{"location":"","page":"Home","title":"Home","text":"@article{MomentClosure2021,\n author = {Sukys, Augustinas and Grima, Ramon},\n title = \"{MomentClosure.jl: automated moment closure approximations in Julia}\",\n journal = {Bioinformatics},\n volume = {38},\n number = {1},\n pages = {289-290},\n year = {2021},\n month = {06},\n issn = {1367-4803},\n doi = {10.1093/bioinformatics/btab469},\n url = {https://doi.org/10.1093/bioinformatics/btab469},\n eprint = {https://academic.oup.com/bioinformatics/article-pdf/38/1/289/41891091/btab469.pdf},\n}","category":"page"},{"location":"#References","page":"Home","title":"References","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"[1]: D. Schnoerr, G. Sanguinetti, and R. Grima, \"Approximation and inference methods for stochastic biochemical kinetics - a tutorial review\", Journal of Physics A: Mathematical and Theoretical 50, 093001 (2017). https://doi.org/10.1088/1751-8121/aa54d9","category":"page"},{"location":"","page":"Home","title":"Home","text":"[2]: A. Ale, P. Kirk, and M. P. H. Stumpf, \"A general moment expansion method for stochastic kinetic models\", The Journal of Chemical Physics 138, 174101 (2013). https://doi.org/10.1063/1.4802475","category":"page"},{"location":"","page":"Home","title":"Home","text":"[3]: C. H. Lee, \"A Moment Closure Method for Stochastic Chemical Reaction Networks with General Kinetics\", MATCH Communications in Mathematical and in Computer Chemistry 70, 785-800 (2013). https://match.pmf.kg.ac.rs/electronicversions/Match70/n3/match70n3785-800.pdf","category":"page"},{"location":"","page":"Home","title":"Home","text":"[4]: D. Schnoerr, G. Sanguinetti, and R. Grima, \"Comparison of different moment-closure approximations for stochastic chemical kinetics\", The Journal of Chemical Physics 143, 185101 (2015). https://doi.org/10.1063/1.4934990","category":"page"},{"location":"","page":"Home","title":"Home","text":"[5]: E. Lakatos, A. Ale, P. D. W. Kirk, and M. P. H. Stumpf, \"Multivariate moment closure techniques for stochastic kinetic models\", The Journal of Chemical Physics 143, 094107 (2015). https://doi.org/10.1063/1.4929837","category":"page"},{"location":"","page":"Home","title":"Home","text":"[6]: A. Singh and J. P. Hespanha, \"Lognormal Moment Closures for Biochemical Reactions\", in Proceedings of the 45th IEEE Conference on Decision and Control, ISSN: 0191-2216 (Dec. 2006), pp. 2063-2068. https://doi.org/10.1109/CDC.2006.376994","category":"page"},{"location":"","page":"Home","title":"Home","text":"[7]: M. Soltani, C. A. Vargas-Garcia, and A. Singh, \"Conditional Moment Closure Schemes for Studying Stochastic Dynamics of Genetic Circuits\", IEEE Transactions on Biomedical Circuits and Systems 9, 518-526 (2015). https://doi.org/10.1109/TBCAS.2015.2453158","category":"page"},{"location":"","page":"Home","title":"Home","text":"[8]: Z. Cao and R. Grima, \"Linear mapping approximation of gene regulatory networks with stochastic dynamics\", Nature Communications 9, 3305 (2018). https://doi.org/10.1038/s41467-018-05822-0","category":"page"},{"location":"api/momentclosure_api/#api","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"","category":"section"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"CurrentModule = MomentClosure","category":"page"},{"location":"api/momentclosure_api/#Model-definition","page":"MomentClosure.jl API","title":"Model definition","text":"","category":"section"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"MomentClosure is fully compatible with reaction network models defined using Catalyst and stored as a ModelingToolkit.ReactionSystem. Note that previously we had implemented our own ReactionSystemMod, that allowed us to consider systems containing reactions which products are independent geometrically distributed random variables. However, this is now deprecated as Catalyst has added support for such parameteric stoichiometries offering a much more complete and efficient feature set.","category":"page"},{"location":"api/momentclosure_api/#api-basic-network-properties","page":"MomentClosure.jl API","title":"Basic model properties","text":"","category":"section"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"Moreover, we include a couple of tiny extensions to the Catalyst API:","category":"page"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"propensities\nget_stoichiometry","category":"page"},{"location":"api/momentclosure_api/#MomentClosure.propensities","page":"MomentClosure.jl API","title":"MomentClosure.propensities","text":"propensities(rn::Union{ReactionSystem, ReactionSystemMod}; combinatoric_ratelaws=true)\n\nReturn a vector of propensity functions of all reactions in the given ReactionSystem.\n\nNotes:\n\ncombinatoric_ratelaws=true uses binomials in calculating the propensity functions of a ReactionSystem, see the notes for ModelingToolkit.jumpratelaw.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#MomentClosure.get_stoichiometry","page":"MomentClosure.jl API","title":"MomentClosure.get_stoichiometry","text":"get_stoichiometry(rn::ReactionSystem, smap::AbstractDict)\n\nReturn the net stoichiometry matrix using the specified mapping of species to their indices.\n\nNotes:\n\nThis is a modification of Catalyst.netstoichmat that is used internally to deal with reactions involving symbolic stoichiometry coefficients.\nThe function also allows custom smap, so it is not limited to the default Catalyst.speciesmap ordering.\nTODO: remove once this Catalyst issue is resolved.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#Moment-Equations","page":"MomentClosure.jl API","title":"Moment Equations","text":"","category":"section"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"generate_raw_moment_eqs\nRawMomentEquations\ngenerate_central_moment_eqs\nCentralMomentEquations\nbernoulli_moment_eqs","category":"page"},{"location":"api/momentclosure_api/#MomentClosure.generate_raw_moment_eqs","page":"MomentClosure.jl API","title":"MomentClosure.generate_raw_moment_eqs","text":"generate_raw_moment_eqs(rn::ReactionSystem, m_order::Int;\n langevin::Bool=false, combinatoric_ratelaws::Bool=true, smap=speciesmap(rn))\n\nGiven a ReactionSystem return the RawMomentEquations of the system generated up to m_order.\n\nNotes:\n\nThe expansion order q, denoted by q_order throughout the docs, is automatically determined from the given polynomial form of the propensity functions, see the tutorial and the theory section for more details on how q_order is obtained.\nif langevin=true, instead of the Chemical Master Equation the Chemical Langevin Equation (diffusion approximation) is considered, and the moment equations are constructed from the corresponding SDE formulation.\ncombinatoric_ratelaws=true uses binomials in calculating the propensity functions of a ReactionSystem, see the notes for ModelingToolkit.jumpratelaw. Note that this field is irrelevant using ReactionSystemMod as then the propensities are defined directly by the user.\nsmap sets the variable ordering in the moment equations (which index corresponds to which species in the reaction network). By default, this is consistent with the internal system ordering accessible with Catalyst.speciesmap.\n\n\n\n\n\ngenerate_raw_moment_eqs(sys::SDESystem, m_order::Int)\n\nGiven an SDESystem, return the RawMomentEquations of the system generated up to m_order.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#MomentClosure.RawMomentEquations","page":"MomentClosure.jl API","title":"MomentClosure.RawMomentEquations","text":"struct RawMomentEquations <: MomentClosure.MomentEquations\n\nRaw moment equations generated for the given system plus a number of helper parameters (used internally).\n\nFields\n\nodes: ModelingToolkit.ODESystem consisting of the time-evolution equations of raw moments.\nμ: Symbolic variables defining the raw moments.\nN: Number of species within the system.\nm_order: Order of moment equations.\nq_order: Expansion order.\niter_all: Vector of all index combinations up to q_order.\niter_m: Vector of all index combinations up to m_order.\niter_q: Vector of all index combinations of order greater than m_order up to q_order.\niter_1: Vector of index combinations of order 1.\n\n\n\n\n\n","category":"type"},{"location":"api/momentclosure_api/#MomentClosure.generate_central_moment_eqs","page":"MomentClosure.jl API","title":"MomentClosure.generate_central_moment_eqs","text":"generate_central_moment_eqs(rn::ReactionSystem, m_order::Int, q_order::Int=0;\n langevin::Bool=false, combinatoric_ratelaws::Bool=true, smap=speciesmap(rn))\n\nGiven a ReactionSystem return the CentralMomentEquations of the system generated up to m_order.\n\nNotes:\n\nif q_order is not specified by the user, it is assumed that the reaction network contains only polynomial propensity functions and hence q_order is determined automatically as in generate_raw_moment_eqs. However, q_order must be specified if non-polynomial propensities are included. Note that the expansion order q denotes the highest order of central moments which will be included in the ODEs (due to the Taylor expansion of propensity functions).\nif langevin=true, instead of the Chemical Master Equation the Chemical Langevin Equation (diffusion approximation) is considered, and the moment equations are constructed from the corresponding SDE formulation.\ncombinatoric_ratelaws=true uses binomials in calculating the propensity functions of a ReactionSystem, see the notes for ModelingToolkit.jumpratelaw. Note that this field is irrelevant using ReactionSystemMod as then the propensities are defined directly by the user.\nsmap sets the variable ordering in the moment equations (which index corresponds to which species in the reaction network). By default, this is consistent with the internal system ordering accessible with Catalyst.speciesmap.\n\n\n\n\n\ngenerate_central_moment_eqs(sys::SDESystem, m_order::Int, q_order::Int=0)\n\nGiven an SDESystem, return the CentralMomentEquations of the system generated up to m_order.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#MomentClosure.CentralMomentEquations","page":"MomentClosure.jl API","title":"MomentClosure.CentralMomentEquations","text":"struct CentralMomentEquations <: MomentClosure.MomentEquations\n\nCentral moment equations generated for the given system plus a number of helper parameters (used internally).\n\nFields\n\nodes: ModelingToolkit.ODESystem consisting of the time-evolution equations of central moments.\nμ: Symbolic variables defining the means.\nM: Symbolic variables defining the central moments.\nN: Number of species within the system.\nm_order: Order of moment equations.\nq_order: Expansion order.\niter_all: Vector of all index combinations up to q_order.\niter_m: Vector of all index combinations up to m_order.\niter_q: Vector of all index combinations of order greater than m_order up to q_order.\niter_1: Vector of index combinations of order 1.\n\n\n\n\n\n","category":"type"},{"location":"api/momentclosure_api/#MomentClosure.bernoulli_moment_eqs","page":"MomentClosure.jl API","title":"MomentClosure.bernoulli_moment_eqs","text":"bernoulli_moment_eqs(sys::MomentEquations, binary_vars::Array{Int,1})\n\nGiven MomentEquations and an array of indices specifying the species which molecule numbers are binary variables (either 0 or 1), apply identities of Bernoulli variables to remove the redundant ODEs and return the cleaned up MomentEquations. See here for example usage.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#Moment-Closure","page":"MomentClosure.jl API","title":"Moment Closure","text":"","category":"section"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"moment_closure\nClosedMomentEquations\ndeterministic_IC","category":"page"},{"location":"api/momentclosure_api/#MomentClosure.moment_closure","page":"MomentClosure.jl API","title":"MomentClosure.moment_closure","text":"moment_closure(sys::MomentEquations, closure::String, binary_vars::Array{Int,1}=Int[])\n\nGiven MomentEquations, apply the specified moment closure approximation and return the ClosedMomentEquations.\n\nThe supported closure options are:\n\n\"zero\"\n\"normal\"\n\"log-normal\"\n\"poisson\"\n\"gamma\"\n\"derivative matching\"\n\"conditional gaussian\"\n\"conditional derivative matching\"\n\nNotes\n\nbinary_vars must be specified for conditional closures as an array of indices of all species (as in Catalyst.speciesmap) which molecule number is a Bernoulli variable. Although not necessary for other closures, specifying binary_vars is recommended as the properties of Bernoulli variables will be used to remove the redundant moment equations and simplify the expressions, which can significantly improve numerical stability.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#MomentClosure.ClosedMomentEquations","page":"MomentClosure.jl API","title":"MomentClosure.ClosedMomentEquations","text":"struct ClosedMomentEquations <: MomentClosure.MomentEquations\n\nClosed moment equations and the corresponding closure functions.\n\nFields\n\nodes: ModelingToolkit.ODESystem consisting of the time-evolution equations of closed moments.\nclosure: Dictionary of moment closure functions for each higher order moment.\nopen_eqs: Original raw or central moment equations (before closure was applied).\n\n\n\n\n\n","category":"type"},{"location":"api/momentclosure_api/#MomentClosure.deterministic_IC","page":"MomentClosure.jl API","title":"MomentClosure.deterministic_IC","text":"deterministic_IC(u₀::Array{T, 1}, eqs::MomentEquations) where T<:Real\n\nGiven an array of initial molecule numbers and the corresponding moment equations, return a mapping of each moment to its initial value under deterministic initial conditions.\n\nNotes\n\nThe means are set to initial molecule numbers (as they take the values specified in u₀ with probability one). The higher order raw moments are products of the corresponding powers of the means whereas the higher order central moments are simply zero.\nThe ordering of u₀ elements must be consistent with the ordering of species in the corresponding reaction system (can be checked with the Catalyst.speciesmap function).\nAs higher-order moment functions under log-normal, gamma, derivative matching and the conditional closures involve moments raised to negative powers, setting initial molecule numbers of certain species to zeros will result in NaN errors when solving the ODEs (the specifics depend on the system at hand).\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#visualisation_api","page":"MomentClosure.jl API","title":"Displaying Equations and Closures","text":"","category":"section"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"The generated moment equations can be converted into LaTeX expressions using Latexify as:","category":"page"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"using Latexify\nlatexify(moment_eqs)","category":"page"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"A ModelingToolkit.ODESystem (saved as moment_eqs.odes) can also be passed to latexify function directly but the output will be different as we apply additional formatting to the symbolic expressions.","category":"page"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"Given ClosedMomentEquations, the closure functions can be visualised in the same way by adding a :closure argument:","category":"page"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"latexify(moment_eqs, :closure)","category":"page"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"Note that this will print out only those higher order moments which are found in the given moment equations. It is possible to print the closure functions of all higher order moments using print_all=true argument:","category":"page"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"latexify(moment_eqs, :closure, print_all=true)","category":"page"},{"location":"api/momentclosure_api/#Linear-Mapping-Approximation","page":"MomentClosure.jl API","title":"Linear Mapping Approximation","text":"","category":"section"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"linear_mapping_approximation","category":"page"},{"location":"api/momentclosure_api/#MomentClosure.linear_mapping_approximation","page":"MomentClosure.jl API","title":"MomentClosure.linear_mapping_approximation","text":" linear_mapping_approximation(rn_nonlinear::T, rn_linear::T, binary_vars::Array{Int,1}=Int[], m_order::Int=0;\n combinatoric_ratelaws = true) where T <: ReactionSystem\n\nGiven a nonlinear ReactionSystem and an equivalent linear ReactionSystem, perform the Linear Mapping Approximation (LMA) and return the corresponding linear RawMomentEquations of the system as well as a Dictionary of reaction parameter substitutions obtained using LMA that are used to generate the moment equations. See the LMA theory section for more details.\n\nNotes:\n\nrn_nonlinear and rn_linear must be identical in layout in order to be interpreted correctly, and the nonlinear reactions contained in rn_nonlinear must all be linearised in rn_linear with rate coefficients updated accordingly. Although this requires a lot of manual input, automating the linearisation further is difficult due to arbitrary choices that may be mane in constructing the reaction networks.\nbinary_vars must be specified for conditional closures as an array of indices of all species (as in Catalyst.speciesmap) which molecule number is a Bernoulli variable. Note that rn_nonlinear and rn_linear may internally order the species differently: binary_vars must be consistent with the ordering in the nonlinear network.\nBy default the moment equations will be generated up to the order determined by the degree of nonlinearity of the nonlinear system's reactions. However, if higher order moment information is required, the optional m_order argument may be provided to increase the expansion order manually.\ncombinatoric_ratelaws=true uses binomials in calculating the propensity functions of a ReactionSystem, see the notes for ModelingToolkit.jumpratelaw.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#stochastic_simulation_utilities","page":"MomentClosure.jl API","title":"Stochastic Simulation Utilities","text":"","category":"section"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"We provide provides functions for higher-order moment extraction from SSA and FSP data:","category":"page"},{"location":"api/momentclosure_api/","page":"MomentClosure.jl API","title":"MomentClosure.jl API","text":"get_raw_moments\nget_central_moments\nget_cumulants\nget_moments_FSP","category":"page"},{"location":"api/momentclosure_api/#MomentClosure.get_raw_moments","page":"MomentClosure.jl API","title":"MomentClosure.get_raw_moments","text":"get_raw_moments(sol::EnsembleSolution, order::Int; naive::Bool=true, b::Int=2)\n\nGiven an EnsembleSolution of DifferentialEquations ensemble simulation, return a Dictionary of raw moments computed up to the specified order at each time step.\n\nNotes\n\nFor example, the dictionary key (2,0,1) maps to an array containing the values of the raw moment μ_201 at each time step.\nIt is assumed that the time steps are all at the same time point for all trajectories (i.e., fixed dt used by the integrator or values were saved using saveat, as discussed here).\nMoments are computed using Cumulants.jl internally. The naive algorithm of moment tensor calculations (naive=true) is usually faster for small systems but the proposed novel algorithm (naive=false) should be more efficient in case of many marginal variables. The block size b can also be specified for the novel algorithm and may have a significant effect on its performance.\nOnly useful if higher order moments are needed: DifferentialEquations has a number of far more efficient and flexible ensemble statistics functions for means, variances and correlations, see this tutorial for more details.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#MomentClosure.get_central_moments","page":"MomentClosure.jl API","title":"MomentClosure.get_central_moments","text":"get_central_moments(sol::EnsembleSolution, order::Int; naive::Bool=true, b::Int=2)\n\nGiven an EnsembleSolution of DifferentialEquations ensemble simulation, return a Dictionary of central moment estimates computed up to the specified order at each time step. See the notes of get_raw_moments function for more information.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#MomentClosure.get_cumulants","page":"MomentClosure.jl API","title":"MomentClosure.get_cumulants","text":"get_cumulants(sol::EnsembleSolution, order::Int; naive::Bool=true, b::Int=2)\n\nGiven an EnsembleSolution of DifferentialEquations ensemble simulation, return a Dictionary of cumulant estimates computed up to the specified order at each time step. See the notes of get_raw_moments function for more information.\n\n\n\n\n\n","category":"function"},{"location":"api/momentclosure_api/#MomentClosure.get_moments_FSP","page":"MomentClosure.jl API","title":"MomentClosure.get_moments_FSP","text":"get_moments_FSP(sol::ODESolution, order::Int, moment_type::String)\n\nGiven an ODESolution obtained using FiniteStateProjection.jl, return a Dictionary of moments computed up to the specified order at each time step. Here, moment_type specifies the type of moments to be computed: available options are raw, central or cumulant.\n\nNotes\n\nThe ODESolution represents the time-evolution of the probability density function that is the solution of the Chemical Master Equation approximated using Finite State Projection algorithms. See the documentation of FiniteStateProjection.jl for more information.\n\n\n\n\n\n","category":"function"}] } diff --git a/dev/theory/linear_mapping_approximation/index.html b/dev/theory/linear_mapping_approximation/index.html index 79423e7..2b9244e 100644 --- a/dev/theory/linear_mapping_approximation/index.html +++ b/dev/theory/linear_mapping_approximation/index.html @@ -1,6 +1,6 @@ -Linear Mapping Approximation · MomentClosure.jl

    Linear Mapping Approximation

    The Linear Mapping Approximation (LMA) provides a novel way of approximating the solution of the CME and has been shown to be accurate for a variety of models of gene regulatory networks (GRNs) [1]. It is based on mapping a nonlinear GRN onto an equivalent linear GRN so that the exact solution of the linear system gives an approximate solution of the nonlinear system. The LMA is restricted in its applicability to chemical reaction networks where one of the substrates in each nonlinear reaction is a molecular species which copy number can be either zero or one (a Bernoulli/binary random variable). Note that a network can contain an arbitrary number of such species but more than one of them cannot be involved in any nonlinear reaction. Below we provide a short overview of the LMA and urge the reader to see the original paper for a more comprehensive description [1].

    To explain the LMA procedure, we start by considering a simple example of a two-state GRN as done in a previous section on conditional closures, denoting the binary gene state by $g$ and the protein number by $p$. We assume that there is a single nonlinear reversible reaction in the network given by

    \[\begin{align*} -G+P &\underset{σ_u}{\stackrel{σ_b}{\rightleftharpoons}} G^*, -\end{align*}\]

    where $P$ denotes the protein and the gene can be in either state $G$ ($g=1$) or $G^*$ ($g=0$). Our aim is to find an approximate time-dependent probability distribution of protein numbers $p$ at time $t$.

    The steps of performing the LMA can then be described as follows:

    1. Find the linear network by replacing any reversible nonlinear reaction (it must involve one binary species) in the nonlinear network by a reversible pseudo first-order reaction between the binary species' states.

    • In our example, we replace the reaction above with $G \underset{σ_u}{\stackrel{\bar{σ}_b}{\rightleftharpoons}} G^*$, noting that the rate parameter is changed from $σ_b$ to $\bar{σ}_b$. Moreover, this approach is just as applicable in case of cooperativity, e.g., $G+nP \rightleftharpoons G^*$ (where $n$ is an integer indicating the cooperative order) would be similarly replaced with $G \rightleftharpoons G^*$.

    2. Approximate the changed rate parameters of the linearised reactions by their expectation values.

    • As noted in [1], the first-order reaction $G \stackrel{\bar{σ}_b}\rightarrow G^*$ maps onto the second-order reaction $G+P \stackrel{σ_b}\rightarrow G^*$ if we choose $\bar{σ}_b = σ_b \left(p \,|\, g=1 \right)$, where $p \,|\, g=1$ indicates the instantaneous protein number given the gene is in the state $G$. In LMA, we use the mean-field approximation taking the expectation value of the rate so that

      \[\begin{align*} -\bar{σ}_b = σ_b \left \langle p \,|\, g=1 \right \rangle = σ_b \frac{\left\langle pg \right\rangle}{\left\langle g \right\rangle}. -\end{align*}\]

      The same procedure can be extended to the general nonlinear reaction where $n$ proteins bind cooperatively. The effective parameter is then given by

      \[\bar{σ}_b = σ_b \frac{\left\langle \prod_{i=0}^{n-1} \left( p-i\right)g \right\rangle}{\left\langle g \right\rangle}.\]

    3. Write down the moment equations for the linear network using the approximated stochastic rates.

    • Note that the moment equations must be generated up the order given by the highest order nonlinear reaction in the network. If the only nonlinear reaction is the second-order reaction $G+P \stackrel{σ_b}\rightarrow G^*$, we need to consider only moments up to the second order (as hinted by the functional form of $\bar{σ}_b$ above). However, the moment hierarchy is otherwise closed, no additional moment closure approximations need to be performed, and therefore we can solve the moment equations in a straightforward manner.

    4. Solve the moment equations numerically up to time $t$ and plug the resulting moment values into the equations for the effective parameters. Proceed to calculate the time-average of these parameters over the time-interval $[0, t]$.

    • In our example, plugging the solved-for moment values into the equation for $\bar{σ}_b$ allows us to interpret the effective parameter as a time-dependent function $\bar{σ}_b(t)$. However, as the time-dependent probability distribution solution of the CME for the nonlinear network with a general time-dependent $\bar{σ}_b$ is most likely intractable, we transform $\bar{σ}_b(t)$ into a time-independent constant by taking its time-average $\bar{σ}_b^* = \int_0^t \bar{σ}_b(t') dt' / t$. This approach is justified in [1] by considering the Magnus expansion.

    5. Obtain the time-dependent probability distribution solution of the CME of the linear network assuming that the rate parameters of the linearised reactions are time-independent constants.

    • Note that this step is the major limitation of the LMA as closed-form solutions are available only for a handful of systems (consult [1] for more details).

    6. Finally, construct the approximate probability distribution of the nonlinear network at time $t$ by replacing the respective rate parameters with their time-averaged equivalents obtained in the previous step.

    MomentClosure.jl provides automated generation of the closed moment equations using LMA given a nonlinear chemical reaction network and its linear equivalent. This encapsulates the first three steps of the LMA procedure outlined above which are general and can be seen as an original moment closure approximation. We apply the LMA on simple models of nonlinear GRNs and also discuss how the subsequent LMA steps can be performed in Julia on a case-by-case basis in this tutorial example.

    References

    [1]: Z. Cao and R. Grima, "Linear mapping approximation of gene regulatory networks with stochastic dynamics", Nature Communications 9, 3305 (2018). https://doi.org/10.1038/s41467-018-05822-0

    +Linear Mapping Approximation · MomentClosure.jl

    Linear Mapping Approximation

    The Linear Mapping Approximation (LMA) provides a novel way of approximating the solution of the CME and has been shown to be accurate for a variety of models of gene regulatory networks (GRNs) [1]. It is based on mapping a nonlinear GRN onto an equivalent linear GRN so that the exact solution of the linear system gives an approximate solution of the nonlinear system. The LMA is restricted in its applicability to chemical reaction networks where one of the substrates in each nonlinear reaction is a molecular species which copy number can be either zero or one (a Bernoulli/binary random variable). Note that a network can contain an arbitrary number of such species but more than one of them cannot be involved in any nonlinear reaction. Below we provide a short overview of the LMA and urge the reader to see the original paper for a more comprehensive description [1].

    To explain the LMA procedure, we start by considering a simple example of a two-state GRN as done in a previous section on conditional closures, denoting the binary gene state by $g$ and the protein number by $p$. We assume that there is a single nonlinear reversible reaction in the network given by

    \[\begin{align*} +G+P &\underset{σ_u}{\stackrel{σ_b}{\rightleftharpoons}} G^*, +\end{align*}\]

    where $P$ denotes the protein and the gene can be in either state $G$ ($g=1$) or $G^*$ ($g=0$). Our aim is to find an approximate time-dependent probability distribution of protein numbers $p$ at time $t$.

    The steps of performing the LMA can then be described as follows:

    1. Find the linear network by replacing any reversible nonlinear reaction (it must involve one binary species) in the nonlinear network by a reversible pseudo first-order reaction between the binary species' states.

    • In our example, we replace the reaction above with $G \underset{σ_u}{\stackrel{\bar{σ}_b}{\rightleftharpoons}} G^*$, noting that the rate parameter is changed from $σ_b$ to $\bar{σ}_b$. Moreover, this approach is just as applicable in case of cooperativity, e.g., $G+nP \rightleftharpoons G^*$ (where $n$ is an integer indicating the cooperative order) would be similarly replaced with $G \rightleftharpoons G^*$.

    2. Approximate the changed rate parameters of the linearised reactions by their expectation values.

    • As noted in [1], the first-order reaction $G \stackrel{\bar{σ}_b}\rightarrow G^*$ maps onto the second-order reaction $G+P \stackrel{σ_b}\rightarrow G^*$ if we choose $\bar{σ}_b = σ_b \left(p \,|\, g=1 \right)$, where $p \,|\, g=1$ indicates the instantaneous protein number given the gene is in the state $G$. In LMA, we use the mean-field approximation taking the expectation value of the rate so that

      \[\begin{align*} +\bar{σ}_b = σ_b \left \langle p \,|\, g=1 \right \rangle = σ_b \frac{\left\langle pg \right\rangle}{\left\langle g \right\rangle}. +\end{align*}\]

      The same procedure can be extended to the general nonlinear reaction where $n$ proteins bind cooperatively. The effective parameter is then given by

      \[\bar{σ}_b = σ_b \frac{\left\langle \prod_{i=0}^{n-1} \left( p-i\right)g \right\rangle}{\left\langle g \right\rangle}.\]

    3. Write down the moment equations for the linear network using the approximated stochastic rates.

    • Note that the moment equations must be generated up the order given by the highest order nonlinear reaction in the network. If the only nonlinear reaction is the second-order reaction $G+P \stackrel{σ_b}\rightarrow G^*$, we need to consider only moments up to the second order (as hinted by the functional form of $\bar{σ}_b$ above). However, the moment hierarchy is otherwise closed, no additional moment closure approximations need to be performed, and therefore we can solve the moment equations in a straightforward manner.

    4. Solve the moment equations numerically up to time $t$ and plug the resulting moment values into the equations for the effective parameters. Proceed to calculate the time-average of these parameters over the time-interval $[0, t]$.

    • In our example, plugging the solved-for moment values into the equation for $\bar{σ}_b$ allows us to interpret the effective parameter as a time-dependent function $\bar{σ}_b(t)$. However, as the time-dependent probability distribution solution of the CME for the nonlinear network with a general time-dependent $\bar{σ}_b$ is most likely intractable, we transform $\bar{σ}_b(t)$ into a time-independent constant by taking its time-average $\bar{σ}_b^* = \int_0^t \bar{σ}_b(t') dt' / t$. This approach is justified in [1] by considering the Magnus expansion.

    5. Obtain the time-dependent probability distribution solution of the CME of the linear network assuming that the rate parameters of the linearised reactions are time-independent constants.

    • Note that this step is the major limitation of the LMA as closed-form solutions are available only for a handful of systems (consult [1] for more details).

    6. Finally, construct the approximate probability distribution of the nonlinear network at time $t$ by replacing the respective rate parameters with their time-averaged equivalents obtained in the previous step.

    MomentClosure.jl provides automated generation of the closed moment equations using LMA given a nonlinear chemical reaction network and its linear equivalent. This encapsulates the first three steps of the LMA procedure outlined above which are general and can be seen as an original moment closure approximation. We apply the LMA on simple models of nonlinear GRNs and also discuss how the subsequent LMA steps can be performed in Julia on a case-by-case basis in this tutorial example.

    References

    [1]: Z. Cao and R. Grima, "Linear mapping approximation of gene regulatory networks with stochastic dynamics", Nature Communications 9, 3305 (2018). https://doi.org/10.1038/s41467-018-05822-0

    diff --git a/dev/theory/moment_closure_approximations/index.html b/dev/theory/moment_closure_approximations/index.html index 48b3307..310720c 100644 --- a/dev/theory/moment_closure_approximations/index.html +++ b/dev/theory/moment_closure_approximations/index.html @@ -1,94 +1,94 @@ -Moment Closure Approximations · MomentClosure.jl

    Moment Closure Approximations

    In the previous section, we have shown that for a non-linear system an infinite hierarchy of coupled moment equations is obtained that cannot be solved directly and, therefore, needs to be truncated in an approximate way. This can be achieved using moment closure approximations (MAs), in which all moments above a certain order $m$ are expressed in terms of $m^{\text{th}}$ and lower order moments using various (usually distributional) assumptions [1]. Doing so enables us to effectively close the moment hierarchy, leading to a finite set of ODEs which can then be solved numerically. In this section, we present some the commonly used MA methods that are implemented in MomentClosure. Please see the Tutorials section for examples showing different MAs applied to a variety of systems.

    Zero Closure

    The simplest MA is the "central-moment-neglect" MA (CMN-MA) [2], also referred to as "zero-closure" [3] or "low dispersion moment closure" [4], where CMN-MA at $m^{\text{th}}$ order means that the moment equations are truncated by setting all central moments above order $m$ to zero. For example, in the simple case of $2$nd order truncation, the moment equations for the means $\mu_i$ and covariances $C_{ij}$ become:

    \[\begin{align*} - \frac{d \mu_i}{dt} &= \sum_{r} S_{ir} \Big( a_r(\mathbf{μ}) + \frac{1}{2}\sum_{i_1, i_2} \frac{\partial^2 a_r({\mathbf{μ}})}{\partial n_{i_1} \partial n_{i_2}} M_{i_1, i_2} \Big), \\ - \frac{dC_{ij}}{dt} &= \frac{dM_{\mathbf{0}_{i+, j+}}}{dt} \\ - &= \frac{d\langle (n_{i}-\mu_i) (n_{j}-\mu_{j}) \rangle}{dt} = \\ - &= \sum_r \Big[ S_{ir} \sum_k \frac{\partial a_r(\mathbf{μ})}{\partial n_k} C_{jk} + S_{jr} \sum_k \frac{\partial a_r(\mathbf{μ})}{\partial n_k} C_{ik} \\ - &+ S_{ir}S_{jr} \Big( a_r(\mathbf{μ}) + \frac{1}{2} \sum_{k, l} \frac{\partial^2 a_r(\mathbf{μ})}{\partial n_{k} \partial n_{l}} C_{kl} \Big) \Big] \;. -\end{align*}\]

    Normal Closure

    Another popular MA is the "normal moment-closure", pioneered by Goodman [5] and Whittle [6], where all cumulants $\kappa_{\mathbf{i}}$ above order $m$ are set to zero, approximating the probability distribution of the system with the normal distribution [2]:

    \[\begin{align*} - \kappa_{\mathbf{i}} = 0, \quad \text{for} \; |\mathbf{i}| > m. -\end{align*}\]

    In order to truncate the higher order central or raw moments $M_{\mathbf{i}}$ using normal closure we express them in terms of cumulants $\kappa_{\mathbf{i}}$ using the multivariate moment and cumulant relationships formalised by Balakrishnan et al. [7].

    Note that a different implementation of normal closure can be found in literature [3], where the higher order central moments are expressed in terms of a sum of product of covariances using Isserlis' theorem. However, one could argue that such formulation is not advisable as it assumes stronger "Gaussianity" of the underlying distribution than setting the higher order cumulants to zero which is less of an approximation on the form of the distribution and hence is preferable in the development of MAs. For example, in case we are truncating the moment equations at $4$th order, the truncation-order central moments would be expressed only in terms of covariances whereas our formulation using cumulants would explicitly include information about the computed values of third central moments, which is expected to improve numerical stability and lead to more accurate moment estimates.

    Poisson Closure

    Although the Poisson distribution lacks a general formulation for multiple variables [3], "Poisson MA" has been formulated [2, 8] assuming that the joint multivariate distribution is a product of univariate Poisson distributions, i.e., $n_i \sim \text{Poisson}(\mu_i)$. The cumulants of a univariate Poisson distribution are equal to the mean, hence in Poisson closure we set all higher order diagonal cumulants to the corresponding mean values and mixed cumulants to zero [2], which in our notation can be expressed as:

    \[\begin{align*} - \kappa_{\mathbf{i}} &= \mu_j, \quad \text{if} \; i_{j} > m \; \text{and} \; i_{j\neq k} = 0 \quad \text{for some} \; j, k \in \{1,\dotsc,N\}, \\ - \kappa_{\mathbf{i}} &= 0, \quad \text{if} \; |\mathbf{i}| > m \; \text{and} \; i_{j} \neq i_{k} \; (\text{where} \; i_{j} \neq 0, i_{k} \neq 0) \quad \text{for some} \; j, k \in \{1,\dotsc,N\} -\end{align*}\]

    Similarly to normal closure, the higher order central/raw moments can be expressed in terms of cumulants as described in [7].

    Log-normal Closure

    "Log-normal" MA, first applied by Keeling [9], allows one to truncate the moment equations under the assumption that the distribution of the underlying stochastic process is log-normal. A positive multi-dimensional random variable $\mathbf{n}$ follows a log-normal distribution if its logarithm is normally distributed, so that $\mathbf{y} = \ln \mathbf{n}$, and $\mathbf{y} \sim \mathcal{N}(\mathbf{\nu}, \Sigma)$, where $\mathbf{\nu}$ and $\Sigma$ denote the vector of means and the covariance matrix respectively. By considering the moment generating function of the normal distribution, $\mathcal{N}(\mathbf{\nu}, \Sigma)$, one can show that the raw moments are given by [3, 10]:

    \[\begin{align*} - \mu_{\mathbf{i}} = \exp\left(\mathbf{i}^{\top}\mathbf{\nu} + \frac{1}{2}\mathbf{i}^{\top}\Sigma\mathbf{i}\right). -\end{align*}\]

    It follows that

    \[\begin{align*} - \nu_i &= \ln \mu_i - \frac{1}{2} \Sigma_{ii}, \\ - \Sigma_{ij} &= \ln \left( 1 + \frac{\langle (n_i - \mu_i)(n_j - \mu_j) \rangle}{\exp \left( \nu_i + \nu_j + \frac{1}{2} \left( \Sigma_{ii} + \Sigma_{jj} \right) \right)} \right) \\ - &= \ln \left( 1 + \frac{C_{ij}}{\exp \left( \nu_i + \nu_j + \frac{1}{2} \left( \Sigma_{ii} + \Sigma_{jj} \right) \right)} \right), \\ - \Sigma_{ii} &= \ln \left( 1 + \frac{C_{ii}}{\mu_i^2} \right) . -\end{align*}\]

    Note that central moments can be obtained from raw moments by utilising their general multivariate relationship [11].

    Gamma Closure

    The method of "gamma closure" was originally implemented by Lakatos et al. [3], where the authors acknowledged the ambiguity arising in defining multivariate gamma distributions, and, building upon previous definitions in the literature (e.g. [12] and [13]), proposed a new formulation of a multivariate gamma distribution. Here we reproduce the definition by closely following the description in [3] and elucidating some of the derivation steps.

    We denote a random variable drawn from gamma distribution with shape $\alpha$ and scale $\beta$ as $n \sim \text{Gamma}(\alpha, \beta)$. The probability density function of the univariate gamma distribution with the corresponding shape-scale parameterisation is

    \[\begin{align*} - f(n; \alpha, \beta) = \frac{1}{\Gamma(\alpha)\beta^{\alpha}} n^{\alpha-1}e^{-\frac{n}{\beta}}, -\end{align*}\]

    where $\Gamma$ is the gamma function. The $i^{\text{th}}$ raw moment of $n$ is given by

    \[\begin{align*} - μ_i &= \frac{\Gamma(\alpha+i)\beta^i}{\Gamma(\alpha)} = (\alpha)_i \beta^i, \tag{a} -\end{align*}\]

    where $(\alpha)_i = \alpha (\alpha+1) \dotsm (\alpha+i-1)$. Note that the moment generating function of X is

    \[\begin{align*} - G_{n}(k) = \langle e^{kn} \rangle = \left( 1 - \beta k \right)^{-\alpha}. -\end{align*}\]

    In order to construct a multivariate gamma distribution, we start by considering independent gamma variables $Y_{kl}$, $k, l = 1, \dotsc, N$, with shape and scale parameters $\alpha_{kl}$ and $\beta_{kl}$ respectively. Here we define $Y_{kl}$ to be symmetric in indices, i.e., $Y_{kl} = Y_{lk}$. Now consider an $N$-dimensional random vector $\mathbf{n} = \left( n_1, n_2, \dotsc, n_N \right)$, where $n_i$ is a linear combination of independent gamma variables:

    \[\begin{align*} - n_i = \sum_{j=1}^N \frac{\beta_{ii}}{\beta_{ij}} Y_{ij}. -\end{align*}\]

    The $i^{\text{th}}$ marginal moment generating function of the joint distribution of $\mathbf{n}$ is given by:

    \[\begin{align*} - G_{n_i}(k_i) &= \left\langle e^{k_i \sum_{j=1}^N \frac{\beta_{ii}}{\beta_{ij}}} \right\rangle \\ - &= G_{Y_{i1}}\left(k_i \frac{\beta_{ii}}{\beta_{i1}} \right) G_{Y_{i2}}\left(k_i \frac{\beta_{ii}}{\beta_{i2}} \right) \dotsm G_{Y_{iN}}\left(k_i \frac{\beta_{ii}}{\beta_{iN}} \right) \\ - &= \left(1-\beta_{ii} k_i \right)^{\sum_{j=1}^N \alpha_{ij}}, -\end{align*}\]

    so that $n_i \sim \text{Gamma}(\alpha_i, \beta_i)$, where $\alpha_i = \sum_{j=1}^N \alpha_{ij}$ and $\beta_i = \beta_{ii}$. Therefore, we have obtained an $N$-variate gamma distribution, which can be denoted as $\mathbf{n} \sim MG(\mathbf{\alpha}, \mathbf{\beta})$, where the vectors of shape and scale parameters are given by $\mathbf{\alpha} = \left( \alpha_1, \dotsc, \alpha_N \right)$ and $\mathbf{\beta} = \left( \beta_1, \beta_2, \dotsc, \beta_N \right)$ respectively.

    We can now readily obtain the raw $m^{\text{th}}$ order moment of $n_i$:

    \[\begin{align*} - \langle n_i^{m} \rangle &= \left\langle \left( \sum_{j=1}^N \frac{\beta_{ii}}{\beta_{ij}} Y_{ij} \right)^m \right\rangle \\ - &= \left\langle \sum_{k_1+k_2+\dotsb+k_N = m} \frac{m!}{k_1!k_2! \dotsm k_N!} \prod_{j=1}^N \left( \frac{\beta_{ii}}{\beta_{ij}} Y_{ij} \right)^{k_j} \right\rangle \\ - &= \sum_{|\mathbf{k}|=m} \frac{m!}{\mathbf{k!}} \prod_{j=1}^N \left\langle \left( \frac{\beta_{ii}}{\beta_{ij}} Y_{ij} \right)^{k_j} \right\rangle \\ - &= \beta_i^m \sum_{|\mathbf{k}|=m} \frac{m!}{\mathbf{k!}} \left( - \prod_{j=1}^N \left( \alpha_{ij} \right)_{k_j} \right). -\end{align*}\]

    Note that we have used Eq. (a) to get to the last line. The mixed raw moments are computed in a similar fashion:

    \[\begin{align*} - \mu_{\mathbf{i}} &= \left\langle \left( \sum_{j=1}^N \frac{\beta_{11}}{\beta_{1j}}Y_{1j} \right)^{i_1} \dotsm \left( \sum_{j=1}^N \frac{\beta_{NN}}{\beta_{Nj}}Y_{Nj} \right)^{i_N} \right\rangle \\ - &= \mathbf{\beta}^{\mathbf{i}} \left\langle \sum_{|\mathbf{k_1}|=i_1} \dotsm \sum_{|\mathbf{k_N}|=i_N} \frac{\mathbf{i!}}{\mathbf{k_1!}\dotsm\mathbf{k_N!}} \prod_{j=1}^N \left( \frac{Y_{1j}}{\beta_{1j}} \right)^{{k_1}_{j}} \dotsm \prod_{j=1}^N \left( \frac{Y_{Nj}}{\beta_{Nj}} \right)^{{k_N}_{j}} \right\rangle \\ - &= \mathbf{\beta}^{\mathbf{i}} \left\langle \sum_{|\mathbf{k_1}|=i_1} \dotsm \sum_{|\mathbf{k_N}|=i_N} \frac{\mathbf{i!}}{\mathbf{k_1!}\dotsm\mathbf{k_N!}} \prod_{q=1}^{N} \left( \frac{Y_{qq}}{\beta_{qq}} \right)^{{k_q}_{q}} \prod_{r=q+1}^N \left( \frac{Y_{qr}}{\beta_{qr}} \right)^{{k_{q}}_{r} + {k_r}_q} \right\rangle \\ - &= \mathbf{\beta}^{\mathbf{i}} \sum_{|\mathbf{k_1}|=i_1} \dotsm \sum_{|\mathbf{k_N}|=i_N} \frac{\mathbf{i!}}{\mathbf{k_1!}\dotsm\mathbf{k_N!}} \prod_{q=1}^{N} \left( \alpha_{qq} \right)_{{k_q}_{q}} \prod_{r=q+1}^N \left( \alpha_{qr} \right)_{{k_{q}}_{r} + {k_{r}}_{q}}, -\end{align*}\]

    where we have taken into account the symmetry in indices and defined each $\mathbf{k_i}$ as an $N$-dimensional vector $\mathbf{k_i} = \left( k_{i_{1}}, \dotsc, k_{i_{N}} \right)$ and $\mathbf{\beta}^{\mathbf{i}} = \beta_1^{i_1} \dotsm \beta_N^{i_N}$. Note that the mean and variance of $n_i$ can be obtained from:

    \[\begin{align*} - \mu_i &= \sum_{j=1}^N \alpha_{ij} \beta_i, \tag{b} \\ - C_{ii} &= (\alpha_i)_2 \beta_i^2 - \alpha_i^2\beta_i^2 \\ - &= \sum_{j=1}^N \alpha_{ij} \beta_i^2. -\end{align*}\]

    Similarly, from Eq. (a) it follows that

    \[\begin{align*} - \langle n_i n_j \rangle = \beta_i \beta_j \left( \sum_{\substack{k, l \\ (k, l) \neq (j, i)}}^N \alpha_{ik} \alpha_{jl} + (\alpha_{ij})_2 \right), -\end{align*}\]

    which together with Eq. (b) allows us to express the covariance as:

    \[\begin{align*} - C_{ij} &= \langle n_i n_j \rangle - \beta_i \beta_j \left( \sum_{k,l} \alpha_{ik} \alpha_{jl} \right) \\ - &= \alpha_{ij} \beta_i \beta_j. -\end{align*}\]

    Finally, from the equations above we can obtain all shape and scale parameters:

    \[\begin{align*} - \beta_i &= \frac{C_{ii}}{\mu_i}, \\ - \alpha_{ij} &= \frac{C_{ij}}{\beta_i \beta_j}, \\ - \alpha_{ii} &= \frac{\mu_i}{\beta_i} - \sum_{\substack{k \\ k \neq i}} \alpha_{ik}. -\end{align*}\]

    Derivative Matching

    The derivative matching MA [14, 15] is based on expressing moments above order $m$ in terms of lower order moments in such a way that their time derivatives match those of the exact moments at some initial time and initial conditions. We outline the approach below, closely following the complete exposition found in the original papers of Singh and Hespanha [14, 15].

    The raw moment equations up to order $m$ for any mass-action reaction network containing at most bimolecular (second order) reactions can be written down concisely in the matrix form:

    \[\begin{align*} - \frac{d\mathbf{μ}}{dt} = \hat{\mathbf{a}} + A\mathbf{μ} + B \bar{\mathbf{μ}} \;, -\end{align*}\]

    where $\mathbf{μ}$ is a vector containing all raw moments of the system up to order $m$ and $\bar{\mathbf{μ}}$ consists of all $(m+1)^{\text{th}}$ order raw moments which the equations depend on. The constant vector $\hat{\mathbf{a}}$ and constant matrices $A$ and $B$ are chosen appropriately for the system at hand. In this case, an MA can be defined as a procedure where each moment in $\bar{\mathbf{μ}}$, $\bar{μ}_{\mathbf{i}}$, is approximated by a moment closure function $\varphi_{\mathbf{i}} (\mathbf{μ})$ of moments up to order $m$. Then the moment equations can be rewritten as

    \[ \frac{d\mathbf{ν}}{dt} = \hat{\mathbf{a}} + A\mathbf{ν} + B\bar{\mathbf{φ}}(\mathbf{ν}) \;,\]

    where the state of the system is now denoted by $\mathbf{ν}$ instead of $\mathbf{μ}$, stressing the fact that we are considering the approximation of the true moment dynamics, and $\bar{\mathbf{φ}}(\mathbf{ν})$ is the corresponding vector of moment closure functions.

    The idea behind derivative matching is to determine a map $\bar{\mathbf{φ}}$ so that the time derivatives between the exact moments, $\mathbf{μ}(t)$, and the approximate moments, $\mathbf{ν}(t)$, would match at some initial time $t_0$ under the initial condition $\mathbf{μ}(t_0) = \mathbf{ν}(t_0)$:

    \[\begin{align*} - \left. \frac{d^i \mathbf{μ}}{dt} \right\rvert_{t=t_0} = \left. \frac{d^i \mathbf{ν}}{dt} \right\rvert_{t=t_0} -\end{align*}\]

    If these conditions hold, one can expect from a Taylor series approximation argument that $\mathbf{μ}(t)$ and $\mathbf{ν}(t)$ will stay close at least locally in time and hence the MA will be sufficiently accurate.

    In order to move forward, Singh and Hespanha present what can be understood as essentially an ansatz. Firstly, moment closure functions for each $\mathbf{i}$, where $|\mathbf{i}| > m$, are chosen to have a separable form given by

    \[\begin{align*} - φ_{\mathbf{i}}(\mathbf{μ}) = \prod_{\substack{1 \leq j_1+\dotsb+j_N \leq m}} \left( μ_{\mathbf{j}} \right)^{γ_{\mathbf{j}}} = \prod_{|\mathbf{j}|=1}^{m} \left( μ_{\mathbf{j}} \right)^{γ_{\mathbf{j}}} \;, -\end{align*}\]

    where $γ_{\mathbf{j}}$ are constants (unique for each vector $\mathbf{i}$) that can be determined by solving the following linear equation system:

    \[\begin{align*} - C^{\mathbf{i}}_{\mathbf{j}} = \sum_{|\mathbf{k}|=1}^m \gamma_{\mathbf{k}} C^{\mathbf{k}}_{\mathbf{j}} \;, \quad \text{for each } \mathbf{j} \; \text{where } |\mathbf{j}|\leq m \,, -\end{align*}\]

    were we have introduced multi-index scalars

    \[\begin{align*} - C^{\mathbf{u}}_{\mathbf{v}} &= C^{u_1}_{v_1}C^{u_2}_{v_2} \dotsm C^{u_N}_{v_N}, -\end{align*}\]

    with each element defined as

    \[\begin{align*} -C^{a}_{b} &= -\begin{cases} - \frac{a!}{(a-b)!b!}, & a \geq b \\ - 0, & a \lt b -\end{cases}\;. -\end{align*}\]

    Using the specific construction of $\bar{\mathbf{φ}}$ described above, it can be shown [15] that for every deterministic initial condition, i.e., $\mathbf{n}(t_0) = \mathbf{n}_0$ with probability one, we will have

    \[\begin{align*} - \mathbf{μ}(t_0) = \mathbf{ν}(t_0) &\implies \left. \frac{d \mathbf{μ}}{dt} \right\rvert_{t=t_0} = \left. \frac{d \mathbf{ν}}{dt} \right\rvert_{t=t_0} \\ - &\implies \left. \frac{d^2\mathbf{μ}}{dt^2} \right\rvert_{t=t_0} = \left. \frac{d^2 \mathbf{ν}}{dt^2} \right\rvert_{t=t_0} + \mathbf{ϵ}(\mathbf{n}_0) \;, -\end{align*}\]

    where all elements of $\mathbf{ϵ}(\mathbf{n}_0)$ are zero except the ones corresponding to $m^{\text{th}}$ order raw moments—these elements are second order polynomials in $\mathbf{n}_0$. Note, however, that these results hold only for mass-action systems containing no higher than second order chemical reactions. While the derivative matching MA can be applied in the same way to systems containing higher order polynomial and non-polynomial propensity functions, it has not been rigorously analysed in such scenarios, where, naturally, we expect significantly larger approximation errors.

    Conditional Closures

    As standard MAs often fail to provide sufficiently accurate approximations of chemical reaction networks involving both high- and low-abundance species, some novel approaches suggest using moments conditioned on the low-copy number species, which can lead to a more effective description of the system dynamics [1, 16]. Here we discuss the conditional moment closure proposed by Soltani et al. (2015) [16], applicable to networks containing molecular species which copy number can be either zero or one, i.e., a binary/Bernoulli random variable. Such conditional MA can be very useful in the study of gene networks where two-state gene systems are often considered—the gene state itself can be treated as a distinct species which molecule number is a Bernoulli variable.

    The conditional MA is based on conditioning the higher order moments of high-abundance species on the binary species being in state 1 (instead of 0) and then applying standard MAs on the conditional moments. Closely following Soltani et al. [16], we use a two-state gene circuit to illustrate the conditional MAs, denoting the binary gene state by $g$ and the protein number (high-abundance species) by $p$. Firstly, note that as $g$ is a Bernoulli variable the following identities hold

    \[\begin{align*} -\langle g^j p \rangle &= \langle g \rangle, \quad j \in {2, 3, \dotsc}, \\ -\langle g^j p^k \rangle &= \langle g p^k \rangle, \quad j,k \in {1, 2, 3, \dotsc} -\end{align*}\]

    Therefore, we only need to concern ourselves with moments of the form $\langle p^k \rangle$ and $\langle gp^k \rangle$. The former can be approximated using the standard MAs (no conditioning needed), whereas the latter can be written down as:

    \[\begin{align*} -\langle gp^j \rangle = \langle p^j \,|\, g=1 \rangle \langle g \rangle, \quad j\in \{1,2, \dotsc\}. -\end{align*}\]

    Now the conditional moment $\langle p^j \,|\, g= 1 \rangle$ can be expressed in terms of lower order conditional moments using one of the standard MAs, e.g., normal closure or derivative matching—the two methods (including the conditioning step) are respectively known as the conditional gaussian and conditional derivative matching MAs. For completeness, we show how the two methods are applied to approximate a specific higher order moment:

    \[\begin{align*} - \langle gp^3 \rangle = \langle p^3 \,|\, g=1 \rangle \langle g \rangle. -\end{align*}\]

    Conditional Gaussian Closure

    Under the conditional Gaussian MA, we assume that the number of protein molecules conditioned on the gene being active, $p \,|\, g = 1$, follows a Gaussian distribution. In other words, we apply normal MA on the conditional moment $\langle p^j \,|\, g=1 \rangle$. Hence we obtain (following the example above):

    \[\begin{align*} -\langle p^3 \,|\, g= 1 \rangle = 3 \langle p^2 \,|\, g = 1 \rangle \langle p \,|\, g=1 \rangle - 2 \langle p \,|\, g=1 \rangle^3. -\end{align*}\]

    Using $\langle gp^j \rangle = \langle p^j \,|\, g=1 \rangle \langle g \rangle$, we can rewrite the equation as:

    \[\begin{align*} -\langle p^3 \,|\, g= 1 \rangle = 3 \frac{\langle gp^2 \rangle \langle gp \rangle}{\langle g \rangle^2} - 2 \frac{\langle gp \rangle^3}{\langle g \rangle^3}. -\end{align*}\]

    Plugging this into the previous expression of the higher-order moment $\langle gp^3 \rangle$ we finally obtain:

    \[\begin{align*} - \langle gp^3 \rangle = 3 \frac{\langle gp^2 \rangle \langle gp \rangle}{\langle g \rangle} - 2 \frac{\langle gp \rangle^3}{\langle g \rangle^2}. -\end{align*}\]

    Conditional Derivative Matching

    The conditional derivative matching boils down to approximating the higher order conditional moments in terms of lower order conditional moments using the standard derivative matching:

    \[\begin{align*} -\langle p^3 \,|\, g = 1 \rangle = \frac{\langle p^2 \,|\, g = 1 \rangle^3}{\langle p \,|\, g= 1 \rangle^3}. -\end{align*}\]

    Using $\langle gp^j \rangle = \langle p^j \,|\, g=1 \rangle \langle g \rangle$ again, we find:

    \[\begin{align*} -\langle gp^3 \rangle = \frac{\langle gp^2 \rangle^3 \langle g \rangle}{\langle gp \rangle^3}. -\end{align*}\]

    Note that conditional moment closure is fully applicable to systems containing multiple binary species. For example, given two two-state genes, $g_1$ and $g_2$, the same Bernoulli variable properties hold and the higher-order moments can be expressed as:

    \[\begin{align*} -\langle g_1 g_2 p^j \rangle = \langle p^j \,|\, g_1 = g_2 = 1 \rangle \langle g_1 g_2 \rangle, \quad j \in \{1,2,\dotsc\}. -\end{align*}\]

    Such higher order conditional moments can again be closed using normal closure or derivative matching.

    Note that the description here is taken from [16] and we urge the reader to see the paper for more details. In addition, we have used MomentClosure to apply conditional closures on genetic feedback loops and reproduce some of the published results in this example.

    References

    [1]: D. Schnoerr, G. Sanguinetti, and R. Grima, "Approximation and inference methods for stochastic biochemical kinetics - a tutorial review", Journal of Physics A: Mathematical and Theoretical 50, 093001 (2017). https://doi.org/10.1088/1751-8121/aa54d9

    [2]: D. Schnoerr, G. Sanguinetti, and R. Grima, "Comparison of different moment-closure approximations for stochastic chemical kinetics", The Journal of Chemical Physics 143, 185101 (2015). https://doi.org/10.1063/1.4934990

    [3]: E. Lakatos, A. Ale, P. D. W. Kirk, and M. P. H. Stumpf, "Multivariate moment closure techniques for stochastic kinetic models", The Journal of Chemical Physics 143, 094107 (2015). https://doi.org/10.1063/1.4929837

    [4]: J. Hespanha, "Moment closure for biochemical networks", in 2008 3rd International Symposium on Communications, Control and Signal Processing (Mar. 2008), pp. 142–147. https://doi.org/10.1109/ISCCSP.2008.4537208

    [5]: L. A. Goodman, "Population Growth of the Sexes", Biometrics 9, Publisher: [Wiley, International Biometric Society], 212–225 (1953). https://doi.org/10.2307/3001852

    [6]: P. Whittle, "On the use of the normal approximation in the treatment of stochastic processes", Journal of the Royal Statistical Society: Series B (Methodological) 19, 268–281 (1957). https://doi.org/10.1111/j.2517-6161.1957.tb00263.x

    [7]: N. Balakrishnan, N. L. Johnson, and S. Kotz, “A note on relationships between moments, central moments and cumulants from multivariate distributions”, Statistics & Probability Letters 39, 49–54 (1998). https://doi.org/10.1016/S0167-7152(98)00027-3

    [8]: I. Nasell, "An extension of the moment closure method", Theoretical Population Biology 64, 233–239 (2003). https://doi.org/10.1016/S0040-5809(03)00074-1

    [9]: M. J. Keeling, "Multiplicative Moments and Measures of Persistence in Ecology", Journal of Theoretical Biology 205, 269–281 (2000). https://doi.org/10.1006/jtbi.2000.2066

    [10]: E. L. Crow and K. Shimizu, eds., Lognormal Distributions: Theory and Applications (Marcel Dekker, 1988).

    [11]: N. L. Johnson, S. Kotz, and N. Balakrishnan, Discrete Multivariate Distributions (Wiley, Feb. 1997).

    [12]: A. M. Mathal and P. G. Moschopoulos, "A form of multivariate gamma distribution", Annals of the Institute of Statistical Mathematics 44, 97–106 (1992). https://doi.org/10.1007/BF00048672

    [13]: E. Furman, "On a multivariate gamma distribution", Statistics & Probability Letters 78, 2353–2360 (2008). https://doi.org/10.1016/j.spl.2008.02.012

    [14]: A. Singh and J. P. Hespanha, "Lognormal Moment Closures for Biochemical Reactions", in Proceedings of the 45th IEEE Conference on Decision and Control, ISSN:0191-2216 (Dec. 2006), pp. 2063–2068. https://doi.org/10.1109/CDC.2006.376994

    [15]: A. Singh and J. P. Hespanha, "Approximate Moment Dynamics for Chemically Reacting Systems", IEEE Transactions on Automatic Control 56, 414–418 (2011). https://doi.org/10.1109/TAC.2010.2088631

    [16]: M. Soltani, C. A. Vargas-Garcia, and A. Singh, "Conditional Moment Closure Schemes for Studying Stochastic Dynamics of Genetic Circuits", IEEE Transactions on Biomedical Circuits and Systems 9, 518–526 (2015). https://doi.org/10.1109/tbcas.2015.2453158

    +Moment Closure Approximations · MomentClosure.jl

    Moment Closure Approximations

    In the previous section, we have shown that for a non-linear system an infinite hierarchy of coupled moment equations is obtained that cannot be solved directly and, therefore, needs to be truncated in an approximate way. This can be achieved using moment closure approximations (MAs), in which all moments above a certain order $m$ are expressed in terms of $m^{\text{th}}$ and lower order moments using various (usually distributional) assumptions [1]. Doing so enables us to effectively close the moment hierarchy, leading to a finite set of ODEs which can then be solved numerically. In this section, we present some the commonly used MA methods that are implemented in MomentClosure. Please see the Tutorials section for examples showing different MAs applied to a variety of systems.

    Zero Closure

    The simplest MA is the "central-moment-neglect" MA (CMN-MA) [2], also referred to as "zero-closure" [3] or "low dispersion moment closure" [4], where CMN-MA at $m^{\text{th}}$ order means that the moment equations are truncated by setting all central moments above order $m$ to zero. For example, in the simple case of $2$nd order truncation, the moment equations for the means $\mu_i$ and covariances $C_{ij}$ become:

    \[\begin{align*} + \frac{d \mu_i}{dt} &= \sum_{r} S_{ir} \Big( a_r(\mathbf{μ}) + \frac{1}{2}\sum_{i_1, i_2} \frac{\partial^2 a_r({\mathbf{μ}})}{\partial n_{i_1} \partial n_{i_2}} M_{i_1, i_2} \Big), \\ + \frac{dC_{ij}}{dt} &= \frac{dM_{\mathbf{0}_{i+, j+}}}{dt} \\ + &= \frac{d\langle (n_{i}-\mu_i) (n_{j}-\mu_{j}) \rangle}{dt} = \\ + &= \sum_r \Big[ S_{ir} \sum_k \frac{\partial a_r(\mathbf{μ})}{\partial n_k} C_{jk} + S_{jr} \sum_k \frac{\partial a_r(\mathbf{μ})}{\partial n_k} C_{ik} \\ + &+ S_{ir}S_{jr} \Big( a_r(\mathbf{μ}) + \frac{1}{2} \sum_{k, l} \frac{\partial^2 a_r(\mathbf{μ})}{\partial n_{k} \partial n_{l}} C_{kl} \Big) \Big] \;. +\end{align*}\]

    Normal Closure

    Another popular MA is the "normal moment-closure", pioneered by Goodman [5] and Whittle [6], where all cumulants $\kappa_{\mathbf{i}}$ above order $m$ are set to zero, approximating the probability distribution of the system with the normal distribution [2]:

    \[\begin{align*} + \kappa_{\mathbf{i}} = 0, \quad \text{for} \; |\mathbf{i}| > m. +\end{align*}\]

    In order to truncate the higher order central or raw moments $M_{\mathbf{i}}$ using normal closure we express them in terms of cumulants $\kappa_{\mathbf{i}}$ using the multivariate moment and cumulant relationships formalised by Balakrishnan et al. [7].

    Note that a different implementation of normal closure can be found in literature [3], where the higher order central moments are expressed in terms of a sum of product of covariances using Isserlis' theorem. However, one could argue that such formulation is not advisable as it assumes stronger "Gaussianity" of the underlying distribution than setting the higher order cumulants to zero which is less of an approximation on the form of the distribution and hence is preferable in the development of MAs. For example, in case we are truncating the moment equations at $4$th order, the truncation-order central moments would be expressed only in terms of covariances whereas our formulation using cumulants would explicitly include information about the computed values of third central moments, which is expected to improve numerical stability and lead to more accurate moment estimates.

    Poisson Closure

    Although the Poisson distribution lacks a general formulation for multiple variables [3], "Poisson MA" has been formulated [2, 8] assuming that the joint multivariate distribution is a product of univariate Poisson distributions, i.e., $n_i \sim \text{Poisson}(\mu_i)$. The cumulants of a univariate Poisson distribution are equal to the mean, hence in Poisson closure we set all higher order diagonal cumulants to the corresponding mean values and mixed cumulants to zero [2], which in our notation can be expressed as:

    \[\begin{align*} + \kappa_{\mathbf{i}} &= \mu_j, \quad \text{if} \; i_{j} > m \; \text{and} \; i_{j\neq k} = 0 \quad \text{for some} \; j, k \in \{1,\dotsc,N\}, \\ + \kappa_{\mathbf{i}} &= 0, \quad \text{if} \; |\mathbf{i}| > m \; \text{and} \; i_{j} \neq i_{k} \; (\text{where} \; i_{j} \neq 0, i_{k} \neq 0) \quad \text{for some} \; j, k \in \{1,\dotsc,N\} +\end{align*}\]

    Similarly to normal closure, the higher order central/raw moments can be expressed in terms of cumulants as described in [7].

    Log-normal Closure

    "Log-normal" MA, first applied by Keeling [9], allows one to truncate the moment equations under the assumption that the distribution of the underlying stochastic process is log-normal. A positive multi-dimensional random variable $\mathbf{n}$ follows a log-normal distribution if its logarithm is normally distributed, so that $\mathbf{y} = \ln \mathbf{n}$, and $\mathbf{y} \sim \mathcal{N}(\mathbf{\nu}, \Sigma)$, where $\mathbf{\nu}$ and $\Sigma$ denote the vector of means and the covariance matrix respectively. By considering the moment generating function of the normal distribution, $\mathcal{N}(\mathbf{\nu}, \Sigma)$, one can show that the raw moments are given by [3, 10]:

    \[\begin{align*} + \mu_{\mathbf{i}} = \exp\left(\mathbf{i}^{\top}\mathbf{\nu} + \frac{1}{2}\mathbf{i}^{\top}\Sigma\mathbf{i}\right). +\end{align*}\]

    It follows that

    \[\begin{align*} + \nu_i &= \ln \mu_i - \frac{1}{2} \Sigma_{ii}, \\ + \Sigma_{ij} &= \ln \left( 1 + \frac{\langle (n_i - \mu_i)(n_j - \mu_j) \rangle}{\exp \left( \nu_i + \nu_j + \frac{1}{2} \left( \Sigma_{ii} + \Sigma_{jj} \right) \right)} \right) \\ + &= \ln \left( 1 + \frac{C_{ij}}{\exp \left( \nu_i + \nu_j + \frac{1}{2} \left( \Sigma_{ii} + \Sigma_{jj} \right) \right)} \right), \\ + \Sigma_{ii} &= \ln \left( 1 + \frac{C_{ii}}{\mu_i^2} \right) . +\end{align*}\]

    Note that central moments can be obtained from raw moments by utilising their general multivariate relationship [11].

    Gamma Closure

    The method of "gamma closure" was originally implemented by Lakatos et al. [3], where the authors acknowledged the ambiguity arising in defining multivariate gamma distributions, and, building upon previous definitions in the literature (e.g. [12] and [13]), proposed a new formulation of a multivariate gamma distribution. Here we reproduce the definition by closely following the description in [3] and elucidating some of the derivation steps.

    We denote a random variable drawn from gamma distribution with shape $\alpha$ and scale $\beta$ as $n \sim \text{Gamma}(\alpha, \beta)$. The probability density function of the univariate gamma distribution with the corresponding shape-scale parameterisation is

    \[\begin{align*} + f(n; \alpha, \beta) = \frac{1}{\Gamma(\alpha)\beta^{\alpha}} n^{\alpha-1}e^{-\frac{n}{\beta}}, +\end{align*}\]

    where $\Gamma$ is the gamma function. The $i^{\text{th}}$ raw moment of $n$ is given by

    \[\begin{align*} + μ_i &= \frac{\Gamma(\alpha+i)\beta^i}{\Gamma(\alpha)} = (\alpha)_i \beta^i, \tag{a} +\end{align*}\]

    where $(\alpha)_i = \alpha (\alpha+1) \dotsm (\alpha+i-1)$. Note that the moment generating function of X is

    \[\begin{align*} + G_{n}(k) = \langle e^{kn} \rangle = \left( 1 - \beta k \right)^{-\alpha}. +\end{align*}\]

    In order to construct a multivariate gamma distribution, we start by considering independent gamma variables $Y_{kl}$, $k, l = 1, \dotsc, N$, with shape and scale parameters $\alpha_{kl}$ and $\beta_{kl}$ respectively. Here we define $Y_{kl}$ to be symmetric in indices, i.e., $Y_{kl} = Y_{lk}$. Now consider an $N$-dimensional random vector $\mathbf{n} = \left( n_1, n_2, \dotsc, n_N \right)$, where $n_i$ is a linear combination of independent gamma variables:

    \[\begin{align*} + n_i = \sum_{j=1}^N \frac{\beta_{ii}}{\beta_{ij}} Y_{ij}. +\end{align*}\]

    The $i^{\text{th}}$ marginal moment generating function of the joint distribution of $\mathbf{n}$ is given by:

    \[\begin{align*} + G_{n_i}(k_i) &= \left\langle e^{k_i \sum_{j=1}^N \frac{\beta_{ii}}{\beta_{ij}}} \right\rangle \\ + &= G_{Y_{i1}}\left(k_i \frac{\beta_{ii}}{\beta_{i1}} \right) G_{Y_{i2}}\left(k_i \frac{\beta_{ii}}{\beta_{i2}} \right) \dotsm G_{Y_{iN}}\left(k_i \frac{\beta_{ii}}{\beta_{iN}} \right) \\ + &= \left(1-\beta_{ii} k_i \right)^{\sum_{j=1}^N \alpha_{ij}}, +\end{align*}\]

    so that $n_i \sim \text{Gamma}(\alpha_i, \beta_i)$, where $\alpha_i = \sum_{j=1}^N \alpha_{ij}$ and $\beta_i = \beta_{ii}$. Therefore, we have obtained an $N$-variate gamma distribution, which can be denoted as $\mathbf{n} \sim MG(\mathbf{\alpha}, \mathbf{\beta})$, where the vectors of shape and scale parameters are given by $\mathbf{\alpha} = \left( \alpha_1, \dotsc, \alpha_N \right)$ and $\mathbf{\beta} = \left( \beta_1, \beta_2, \dotsc, \beta_N \right)$ respectively.

    We can now readily obtain the raw $m^{\text{th}}$ order moment of $n_i$:

    \[\begin{align*} + \langle n_i^{m} \rangle &= \left\langle \left( \sum_{j=1}^N \frac{\beta_{ii}}{\beta_{ij}} Y_{ij} \right)^m \right\rangle \\ + &= \left\langle \sum_{k_1+k_2+\dotsb+k_N = m} \frac{m!}{k_1!k_2! \dotsm k_N!} \prod_{j=1}^N \left( \frac{\beta_{ii}}{\beta_{ij}} Y_{ij} \right)^{k_j} \right\rangle \\ + &= \sum_{|\mathbf{k}|=m} \frac{m!}{\mathbf{k!}} \prod_{j=1}^N \left\langle \left( \frac{\beta_{ii}}{\beta_{ij}} Y_{ij} \right)^{k_j} \right\rangle \\ + &= \beta_i^m \sum_{|\mathbf{k}|=m} \frac{m!}{\mathbf{k!}} \left( + \prod_{j=1}^N \left( \alpha_{ij} \right)_{k_j} \right). +\end{align*}\]

    Note that we have used Eq. (a) to get to the last line. The mixed raw moments are computed in a similar fashion:

    \[\begin{align*} + \mu_{\mathbf{i}} &= \left\langle \left( \sum_{j=1}^N \frac{\beta_{11}}{\beta_{1j}}Y_{1j} \right)^{i_1} \dotsm \left( \sum_{j=1}^N \frac{\beta_{NN}}{\beta_{Nj}}Y_{Nj} \right)^{i_N} \right\rangle \\ + &= \mathbf{\beta}^{\mathbf{i}} \left\langle \sum_{|\mathbf{k_1}|=i_1} \dotsm \sum_{|\mathbf{k_N}|=i_N} \frac{\mathbf{i!}}{\mathbf{k_1!}\dotsm\mathbf{k_N!}} \prod_{j=1}^N \left( \frac{Y_{1j}}{\beta_{1j}} \right)^{{k_1}_{j}} \dotsm \prod_{j=1}^N \left( \frac{Y_{Nj}}{\beta_{Nj}} \right)^{{k_N}_{j}} \right\rangle \\ + &= \mathbf{\beta}^{\mathbf{i}} \left\langle \sum_{|\mathbf{k_1}|=i_1} \dotsm \sum_{|\mathbf{k_N}|=i_N} \frac{\mathbf{i!}}{\mathbf{k_1!}\dotsm\mathbf{k_N!}} \prod_{q=1}^{N} \left( \frac{Y_{qq}}{\beta_{qq}} \right)^{{k_q}_{q}} \prod_{r=q+1}^N \left( \frac{Y_{qr}}{\beta_{qr}} \right)^{{k_{q}}_{r} + {k_r}_q} \right\rangle \\ + &= \mathbf{\beta}^{\mathbf{i}} \sum_{|\mathbf{k_1}|=i_1} \dotsm \sum_{|\mathbf{k_N}|=i_N} \frac{\mathbf{i!}}{\mathbf{k_1!}\dotsm\mathbf{k_N!}} \prod_{q=1}^{N} \left( \alpha_{qq} \right)_{{k_q}_{q}} \prod_{r=q+1}^N \left( \alpha_{qr} \right)_{{k_{q}}_{r} + {k_{r}}_{q}}, +\end{align*}\]

    where we have taken into account the symmetry in indices and defined each $\mathbf{k_i}$ as an $N$-dimensional vector $\mathbf{k_i} = \left( k_{i_{1}}, \dotsc, k_{i_{N}} \right)$ and $\mathbf{\beta}^{\mathbf{i}} = \beta_1^{i_1} \dotsm \beta_N^{i_N}$. Note that the mean and variance of $n_i$ can be obtained from:

    \[\begin{align*} + \mu_i &= \sum_{j=1}^N \alpha_{ij} \beta_i, \tag{b} \\ + C_{ii} &= (\alpha_i)_2 \beta_i^2 - \alpha_i^2\beta_i^2 \\ + &= \sum_{j=1}^N \alpha_{ij} \beta_i^2. +\end{align*}\]

    Similarly, from Eq. (a) it follows that

    \[\begin{align*} + \langle n_i n_j \rangle = \beta_i \beta_j \left( \sum_{\substack{k, l \\ (k, l) \neq (j, i)}}^N \alpha_{ik} \alpha_{jl} + (\alpha_{ij})_2 \right), +\end{align*}\]

    which together with Eq. (b) allows us to express the covariance as:

    \[\begin{align*} + C_{ij} &= \langle n_i n_j \rangle - \beta_i \beta_j \left( \sum_{k,l} \alpha_{ik} \alpha_{jl} \right) \\ + &= \alpha_{ij} \beta_i \beta_j. +\end{align*}\]

    Finally, from the equations above we can obtain all shape and scale parameters:

    \[\begin{align*} + \beta_i &= \frac{C_{ii}}{\mu_i}, \\ + \alpha_{ij} &= \frac{C_{ij}}{\beta_i \beta_j}, \\ + \alpha_{ii} &= \frac{\mu_i}{\beta_i} - \sum_{\substack{k \\ k \neq i}} \alpha_{ik}. +\end{align*}\]

    Derivative Matching

    The derivative matching MA [14, 15] is based on expressing moments above order $m$ in terms of lower order moments in such a way that their time derivatives match those of the exact moments at some initial time and initial conditions. We outline the approach below, closely following the complete exposition found in the original papers of Singh and Hespanha [14, 15].

    The raw moment equations up to order $m$ for any mass-action reaction network containing at most bimolecular (second order) reactions can be written down concisely in the matrix form:

    \[\begin{align*} + \frac{d\mathbf{μ}}{dt} = \hat{\mathbf{a}} + A\mathbf{μ} + B \bar{\mathbf{μ}} \;, +\end{align*}\]

    where $\mathbf{μ}$ is a vector containing all raw moments of the system up to order $m$ and $\bar{\mathbf{μ}}$ consists of all $(m+1)^{\text{th}}$ order raw moments which the equations depend on. The constant vector $\hat{\mathbf{a}}$ and constant matrices $A$ and $B$ are chosen appropriately for the system at hand. In this case, an MA can be defined as a procedure where each moment in $\bar{\mathbf{μ}}$, $\bar{μ}_{\mathbf{i}}$, is approximated by a moment closure function $\varphi_{\mathbf{i}} (\mathbf{μ})$ of moments up to order $m$. Then the moment equations can be rewritten as

    \[ \frac{d\mathbf{ν}}{dt} = \hat{\mathbf{a}} + A\mathbf{ν} + B\bar{\mathbf{φ}}(\mathbf{ν}) \;,\]

    where the state of the system is now denoted by $\mathbf{ν}$ instead of $\mathbf{μ}$, stressing the fact that we are considering the approximation of the true moment dynamics, and $\bar{\mathbf{φ}}(\mathbf{ν})$ is the corresponding vector of moment closure functions.

    The idea behind derivative matching is to determine a map $\bar{\mathbf{φ}}$ so that the time derivatives between the exact moments, $\mathbf{μ}(t)$, and the approximate moments, $\mathbf{ν}(t)$, would match at some initial time $t_0$ under the initial condition $\mathbf{μ}(t_0) = \mathbf{ν}(t_0)$:

    \[\begin{align*} + \left. \frac{d^i \mathbf{μ}}{dt} \right\rvert_{t=t_0} = \left. \frac{d^i \mathbf{ν}}{dt} \right\rvert_{t=t_0} +\end{align*}\]

    If these conditions hold, one can expect from a Taylor series approximation argument that $\mathbf{μ}(t)$ and $\mathbf{ν}(t)$ will stay close at least locally in time and hence the MA will be sufficiently accurate.

    In order to move forward, Singh and Hespanha present what can be understood as essentially an ansatz. Firstly, moment closure functions for each $\mathbf{i}$, where $|\mathbf{i}| > m$, are chosen to have a separable form given by

    \[\begin{align*} + φ_{\mathbf{i}}(\mathbf{μ}) = \prod_{\substack{1 \leq j_1+\dotsb+j_N \leq m}} \left( μ_{\mathbf{j}} \right)^{γ_{\mathbf{j}}} = \prod_{|\mathbf{j}|=1}^{m} \left( μ_{\mathbf{j}} \right)^{γ_{\mathbf{j}}} \;, +\end{align*}\]

    where $γ_{\mathbf{j}}$ are constants (unique for each vector $\mathbf{i}$) that can be determined by solving the following linear equation system:

    \[\begin{align*} + C^{\mathbf{i}}_{\mathbf{j}} = \sum_{|\mathbf{k}|=1}^m \gamma_{\mathbf{k}} C^{\mathbf{k}}_{\mathbf{j}} \;, \quad \text{for each } \mathbf{j} \; \text{where } |\mathbf{j}|\leq m \,, +\end{align*}\]

    were we have introduced multi-index scalars

    \[\begin{align*} + C^{\mathbf{u}}_{\mathbf{v}} &= C^{u_1}_{v_1}C^{u_2}_{v_2} \dotsm C^{u_N}_{v_N}, +\end{align*}\]

    with each element defined as

    \[\begin{align*} +C^{a}_{b} &= +\begin{cases} + \frac{a!}{(a-b)!b!}, & a \geq b \\ + 0, & a \lt b +\end{cases}\;. +\end{align*}\]

    Using the specific construction of $\bar{\mathbf{φ}}$ described above, it can be shown [15] that for every deterministic initial condition, i.e., $\mathbf{n}(t_0) = \mathbf{n}_0$ with probability one, we will have

    \[\begin{align*} + \mathbf{μ}(t_0) = \mathbf{ν}(t_0) &\implies \left. \frac{d \mathbf{μ}}{dt} \right\rvert_{t=t_0} = \left. \frac{d \mathbf{ν}}{dt} \right\rvert_{t=t_0} \\ + &\implies \left. \frac{d^2\mathbf{μ}}{dt^2} \right\rvert_{t=t_0} = \left. \frac{d^2 \mathbf{ν}}{dt^2} \right\rvert_{t=t_0} + \mathbf{ϵ}(\mathbf{n}_0) \;, +\end{align*}\]

    where all elements of $\mathbf{ϵ}(\mathbf{n}_0)$ are zero except the ones corresponding to $m^{\text{th}}$ order raw moments—these elements are second order polynomials in $\mathbf{n}_0$. Note, however, that these results hold only for mass-action systems containing no higher than second order chemical reactions. While the derivative matching MA can be applied in the same way to systems containing higher order polynomial and non-polynomial propensity functions, it has not been rigorously analysed in such scenarios, where, naturally, we expect significantly larger approximation errors.

    Conditional Closures

    As standard MAs often fail to provide sufficiently accurate approximations of chemical reaction networks involving both high- and low-abundance species, some novel approaches suggest using moments conditioned on the low-copy number species, which can lead to a more effective description of the system dynamics [1, 16]. Here we discuss the conditional moment closure proposed by Soltani et al. (2015) [16], applicable to networks containing molecular species which copy number can be either zero or one, i.e., a binary/Bernoulli random variable. Such conditional MA can be very useful in the study of gene networks where two-state gene systems are often considered—the gene state itself can be treated as a distinct species which molecule number is a Bernoulli variable.

    The conditional MA is based on conditioning the higher order moments of high-abundance species on the binary species being in state 1 (instead of 0) and then applying standard MAs on the conditional moments. Closely following Soltani et al. [16], we use a two-state gene circuit to illustrate the conditional MAs, denoting the binary gene state by $g$ and the protein number (high-abundance species) by $p$. Firstly, note that as $g$ is a Bernoulli variable the following identities hold

    \[\begin{align*} +\langle g^j p \rangle &= \langle g \rangle, \quad j \in {2, 3, \dotsc}, \\ +\langle g^j p^k \rangle &= \langle g p^k \rangle, \quad j,k \in {1, 2, 3, \dotsc} +\end{align*}\]

    Therefore, we only need to concern ourselves with moments of the form $\langle p^k \rangle$ and $\langle gp^k \rangle$. The former can be approximated using the standard MAs (no conditioning needed), whereas the latter can be written down as:

    \[\begin{align*} +\langle gp^j \rangle = \langle p^j \,|\, g=1 \rangle \langle g \rangle, \quad j\in \{1,2, \dotsc\}. +\end{align*}\]

    Now the conditional moment $\langle p^j \,|\, g= 1 \rangle$ can be expressed in terms of lower order conditional moments using one of the standard MAs, e.g., normal closure or derivative matching—the two methods (including the conditioning step) are respectively known as the conditional gaussian and conditional derivative matching MAs. For completeness, we show how the two methods are applied to approximate a specific higher order moment:

    \[\begin{align*} + \langle gp^3 \rangle = \langle p^3 \,|\, g=1 \rangle \langle g \rangle. +\end{align*}\]

    Conditional Gaussian Closure

    Under the conditional Gaussian MA, we assume that the number of protein molecules conditioned on the gene being active, $p \,|\, g = 1$, follows a Gaussian distribution. In other words, we apply normal MA on the conditional moment $\langle p^j \,|\, g=1 \rangle$. Hence we obtain (following the example above):

    \[\begin{align*} +\langle p^3 \,|\, g= 1 \rangle = 3 \langle p^2 \,|\, g = 1 \rangle \langle p \,|\, g=1 \rangle - 2 \langle p \,|\, g=1 \rangle^3. +\end{align*}\]

    Using $\langle gp^j \rangle = \langle p^j \,|\, g=1 \rangle \langle g \rangle$, we can rewrite the equation as:

    \[\begin{align*} +\langle p^3 \,|\, g= 1 \rangle = 3 \frac{\langle gp^2 \rangle \langle gp \rangle}{\langle g \rangle^2} - 2 \frac{\langle gp \rangle^3}{\langle g \rangle^3}. +\end{align*}\]

    Plugging this into the previous expression of the higher-order moment $\langle gp^3 \rangle$ we finally obtain:

    \[\begin{align*} + \langle gp^3 \rangle = 3 \frac{\langle gp^2 \rangle \langle gp \rangle}{\langle g \rangle} - 2 \frac{\langle gp \rangle^3}{\langle g \rangle^2}. +\end{align*}\]

    Conditional Derivative Matching

    The conditional derivative matching boils down to approximating the higher order conditional moments in terms of lower order conditional moments using the standard derivative matching:

    \[\begin{align*} +\langle p^3 \,|\, g = 1 \rangle = \frac{\langle p^2 \,|\, g = 1 \rangle^3}{\langle p \,|\, g= 1 \rangle^3}. +\end{align*}\]

    Using $\langle gp^j \rangle = \langle p^j \,|\, g=1 \rangle \langle g \rangle$ again, we find:

    \[\begin{align*} +\langle gp^3 \rangle = \frac{\langle gp^2 \rangle^3 \langle g \rangle}{\langle gp \rangle^3}. +\end{align*}\]

    Note that conditional moment closure is fully applicable to systems containing multiple binary species. For example, given two two-state genes, $g_1$ and $g_2$, the same Bernoulli variable properties hold and the higher-order moments can be expressed as:

    \[\begin{align*} +\langle g_1 g_2 p^j \rangle = \langle p^j \,|\, g_1 = g_2 = 1 \rangle \langle g_1 g_2 \rangle, \quad j \in \{1,2,\dotsc\}. +\end{align*}\]

    Such higher order conditional moments can again be closed using normal closure or derivative matching.

    Note that the description here is taken from [16] and we urge the reader to see the paper for more details. In addition, we have used MomentClosure to apply conditional closures on genetic feedback loops and reproduce some of the published results in this example.

    References

    [1]: D. Schnoerr, G. Sanguinetti, and R. Grima, "Approximation and inference methods for stochastic biochemical kinetics - a tutorial review", Journal of Physics A: Mathematical and Theoretical 50, 093001 (2017). https://doi.org/10.1088/1751-8121/aa54d9

    [2]: D. Schnoerr, G. Sanguinetti, and R. Grima, "Comparison of different moment-closure approximations for stochastic chemical kinetics", The Journal of Chemical Physics 143, 185101 (2015). https://doi.org/10.1063/1.4934990

    [3]: E. Lakatos, A. Ale, P. D. W. Kirk, and M. P. H. Stumpf, "Multivariate moment closure techniques for stochastic kinetic models", The Journal of Chemical Physics 143, 094107 (2015). https://doi.org/10.1063/1.4929837

    [4]: J. Hespanha, "Moment closure for biochemical networks", in 2008 3rd International Symposium on Communications, Control and Signal Processing (Mar. 2008), pp. 142–147. https://doi.org/10.1109/ISCCSP.2008.4537208

    [5]: L. A. Goodman, "Population Growth of the Sexes", Biometrics 9, Publisher: [Wiley, International Biometric Society], 212–225 (1953). https://doi.org/10.2307/3001852

    [6]: P. Whittle, "On the use of the normal approximation in the treatment of stochastic processes", Journal of the Royal Statistical Society: Series B (Methodological) 19, 268–281 (1957). https://doi.org/10.1111/j.2517-6161.1957.tb00263.x

    [7]: N. Balakrishnan, N. L. Johnson, and S. Kotz, “A note on relationships between moments, central moments and cumulants from multivariate distributions”, Statistics & Probability Letters 39, 49–54 (1998). https://doi.org/10.1016/S0167-7152(98)00027-3

    [8]: I. Nasell, "An extension of the moment closure method", Theoretical Population Biology 64, 233–239 (2003). https://doi.org/10.1016/S0040-5809(03)00074-1

    [9]: M. J. Keeling, "Multiplicative Moments and Measures of Persistence in Ecology", Journal of Theoretical Biology 205, 269–281 (2000). https://doi.org/10.1006/jtbi.2000.2066

    [10]: E. L. Crow and K. Shimizu, eds., Lognormal Distributions: Theory and Applications (Marcel Dekker, 1988).

    [11]: N. L. Johnson, S. Kotz, and N. Balakrishnan, Discrete Multivariate Distributions (Wiley, Feb. 1997).

    [12]: A. M. Mathal and P. G. Moschopoulos, "A form of multivariate gamma distribution", Annals of the Institute of Statistical Mathematics 44, 97–106 (1992). https://doi.org/10.1007/BF00048672

    [13]: E. Furman, "On a multivariate gamma distribution", Statistics & Probability Letters 78, 2353–2360 (2008). https://doi.org/10.1016/j.spl.2008.02.012

    [14]: A. Singh and J. P. Hespanha, "Lognormal Moment Closures for Biochemical Reactions", in Proceedings of the 45th IEEE Conference on Decision and Control, ISSN:0191-2216 (Dec. 2006), pp. 2063–2068. https://doi.org/10.1109/CDC.2006.376994

    [15]: A. Singh and J. P. Hespanha, "Approximate Moment Dynamics for Chemically Reacting Systems", IEEE Transactions on Automatic Control 56, 414–418 (2011). https://doi.org/10.1109/TAC.2010.2088631

    [16]: M. Soltani, C. A. Vargas-Garcia, and A. Singh, "Conditional Moment Closure Schemes for Studying Stochastic Dynamics of Genetic Circuits", IEEE Transactions on Biomedical Circuits and Systems 9, 518–526 (2015). https://doi.org/10.1109/tbcas.2015.2453158

    diff --git a/dev/theory/moment_expansion_CME/index.html b/dev/theory/moment_expansion_CME/index.html index 4e88d94..10706fb 100644 --- a/dev/theory/moment_expansion_CME/index.html +++ b/dev/theory/moment_expansion_CME/index.html @@ -1,49 +1,49 @@ -Moment Expansion (CME) · MomentClosure.jl

    Moment Expansion (CME)

    The Chemical Master Equation

    Consider a chemical reaction network with $N$ different molecular species $X_i$ ($i=1, \dotsc, N$) and $R$ chemical reactions, so that the system can be described by [1]:

    \[\begin{align*} - \sum_{i=1}^{N} s_{ij} X_{i} \xrightarrow{k_j} \sum_{i=1}^N r_{ij} X_i, \quad j=1,\dotsc,R, -\end{align*}\]

    where $s_{ij}$ and $r_{ij}$ respectively denote the numbers of reactant and product molecules of species $i$ in the chemical reaction $j$. The stoichiometric matrix is defined as $S_{ij} = r_{ij} - s_{ij}$ (the net change in the number of molecules of species $X_{i}$ when the $r^{\text{th}}$ reaction occurs). The state of the system is determined by the state vector $\mathbf{n}=(n_1, \dotsc, n_N)$, where $n_i$ is the number of $X_i$ molecules. The time evolution of the probability distribution of $\mathbf{n}$ is described by the Chemical Master Equation (CME)

    \[\begin{equation} - \frac{d P(\mathbf{n}, t)}{dt} = \sum^{R}_{r=1} \Big[ a_r(\mathbf{n}-S_r)P(\mathbf{n}-S_r, t) - a_r(\mathbf{n}) P(\mathbf{n}, t) \Big]\;, \tag{1} -\end{equation}\]

    where $a_{r}(\mathbf{n})$ is the propensity function of the $r^{\text{th}}$ reaction and $S_r$ is the $r^{\text{th}}$ column of the stoichiometric matrix $S$.

    Modelling using the CME framework is common in the study of biochemical and gene networks within cells. Although such master equations are rather simple in structure, for most systems there are no known analytical solutions and their stochastic simulations can be very computationally expensive. One possible approach to investigate the system at hand is to approximate the whole probability distribution solution of the CME in terms of its first few moments (e.g. mean and variance).

    Raw Moment Equations

    From Eq. (1) we can obtain a system of ordinary differential equations (ODEs) governing the time-evolution of the raw moments of the system up to specified moment expansion order $m$, given by $\mu_{\mathbf{i}} = \mu_{i_1, \dotsc, i_N} = \langle n_1^{i_1} \dotsm n_N^{i_N} \rangle$, where the indices $\mathbf{i}=(i_1, \dotsc, i_N)$ are restricted such that $|\mathbf{i}| = \sum_{j=1}^N i_j \leq m$. Note that first order raw moments are simply the means. For example, when N = 3, the mean molecule number of second species in the system is given by $\mu_2 = \mu_{0, 1, 0} = \langle n_2 \rangle$ (when $N=3$). We chose to relax the notation throughout so that the means can be indicated by a single index of the molecular species (used in this section) or by the corresponding one-hot vector (used in the code).

    To find the first moment equations, we multiply the CME by $n_i$ and sum over all possible states:

    \[\begin{align*} - \sum_{\mathbf{n}} n_i \frac{dP(\mathbf{n},t)}{dt} &= \sum_{n_1}^{\infty} \sum_{n_2}^{\infty} \dotsm \sum_{n_N}^{\infty} n_i \frac{dP(\mathbf{n},t)}{dt} \\ - &= \sum_{r} \sum_{\mathbf{n}} n_i a_r(\mathbf{n}-S_r)P(\mathbf{n}-S_r, t) - n_i a_r(\mathbf{n}) P(\mathbf{n}, t) \;. -\end{align*}\]

    Applying a transformation $\mathbf{n}-S_r \rightarrow \mathbf{n}$ on the first term in the sum leads to

    \[\begin{align*} - \frac{d\mu_i}{dt} &= \sum_{r} \sum_{\mathbf{n}} (n_i+S_{ir}) a_r(\mathbf{n})P(\mathbf{n}, t) - n_i a_r(\mathbf{n}) P(\mathbf{n}, t) \\ - &= \sum_{r} \sum_{\mathbf{n}} S_{ir} a_r({\mathbf{n}}) P(\mathbf{n}, t) \\ - &= \sum_{r} S_{ir} \langle a_r(\mathbf{n}) \rangle\;. \tag{2} -\end{align*}\]

    The derivation can be extended to the multivariate case of higher order moments $\mu_{\mathbf{i}}$ with $|\mathbf{i}| \leq m$:

    \[\begin{align*} - \frac{d\mu_{\mathbf{i}}}{dt} &= \sum_{\mathbf{n}} n_1^{i_1}\dotsm n_N^{i_N} \frac{dP(\mathbf{n}, t)}{dt} \\ - &= \sum_{r} \sum_{\mathbf{n}} \left[ (n_1+S_{1r})^{i_1}\dotsm (n_N +S_{2r})^{i_N} - n_1^{i_1}\dotsm n_N^{i_N} \right] a_r(\mathbf{n})P(\mathbf{n}, t) \\ - &= \sum_r \sum_{\mathbf{n}} \left[ \sum^{i_1}_{j_1=0} \binom{i_1}{j_1} n_{1}^{j_1}S_{1r}^{\,i_1-j_1} \dotsm \sum^{i_N}_{j_N=0} \binom{i_N}{j_N} n_{N}^{j_N}S_{Nr}^{\, i_N-j_N} - n_1^{i_1}\dotsm n_N^{i_N} \right] a_r(\mathbf{n})P(\mathbf{n}, t) \\ - &= \sum_r \sum_{\mathbf{n}} \sum^{|\mathbf{i}|-1}_{|\mathbf{j}|=0} \binom{i_1}{j_1} \dotsm \binom{i_N}{j_N} S_{1r}^{\,i_1-j_1} \dotsm S_{Nr}^{\, i_N-j_N} n_{1}^{j_1} \dotsm n_{N}^{j_N} a_r(\mathbf{n})P(\mathbf{n}, t) \\ - &= \sum_r \sum^{|\mathbf{i}|-1}_{|\mathbf{j}|=0} \binom{\, \mathbf{i} \,}{\, \mathbf{j} \,} S_r^{\,\mathbf{i}-\mathbf{j}} \langle \mathbf{n}^{\mathbf{j}} a_r(\mathbf{n}) \rangle \;, -\end{align*}\]

    where we have introduced multi-index notation:

    \[\begin{align} - |\mathbf{i}| &= \sum^{N}_{j=1} i_j , \tag{3} \\ - \sum^{|\mathbf{i}|-1}_{|\mathbf{j}|=0} &= \sum_{\substack{0 \leq j_1 \leq i_1, \, \dotsc, \, 0 \leq j_N \leq i_N\\ 0 \leq j_1+\dotsb+j_N \leq |\mathbf{i}|-1}} \tag{4} \\ - \binom{\, \mathbf{i} \,}{\, \mathbf{j} \,} &= \binom{i_1}{j_1} \dotsm \binom{i_N}{j_N} \tag{5}, \\ - \mathbf{n}^{\mathbf{j}} &= n_1^{j_1}\dotsm n_N^{j_N}, \tag{6} \\ - S_{r}^{\,\mathbf{i}-\mathbf{j}} &= S_{1r}^{\, i_1-j_1} \dotsm S_{Nr}^{\, i_N-j_N} \tag{7}\;. -\end{align}\]

    It is crucial to stress three key points:

    • Throughout all derivations presented in this section we assume that the components of the net stoichiometry matrix $S$ are constant values. However, in certain cases the reaction product may itself be a stochastic variable so that the corresponding expectation values, $\langle S_{r}^{\,\mathbf{i}-\mathbf{j}} \rangle$, must be taken into account. We have implemented a limited support for such systems where components of $S$ can be independent geometrically distributed variables, see the specific gene network example.
    • Generation of raw moment equations is only possible if the kinetics of the system at hand are governed by the law of mass action where all propensity functions are polynomials in $\mathbf{n}$, otherwise the expectation value terms $\langle a_r(\mathbf{n}) \rangle$ and $\langle n_{i_1}^{j_1} \dotsm n_{i_N}^{j_N} a_r(\mathbf{n}) \rangle$ are ill-defined. This key issue can be overcome by the general central moment expansion method presented below.
    • The order of the polynomials $a_r(\mathbf{n})$ determines the order of moments encountered in the generated system of ODEs. If the system is linear (contains only zeroth and first order reactions), the $m^{\text{th}}$ order moments will depend only of moments of order $m$ or lower, hence constituting a finite hierarchy of moment ODEs that can be readily solved numerically or otherwise without approximations. However, if the system is non-linear (involves second or higher order reactions), moment equations will depend on higher order moments. For example, if the reaction network contains bimolecular reactions, the corresponding propensity functions will be second order polynomials and hence $m^{\text{th}}$ order moment equations will now depend on $(m+1)^{th}$ order moments. This leads to an infinite hierarchy of coupled moment equations where each moment will depend on higher order moments—it cannot be solved directly and needs to be truncated. This can be achieved using one of many moment closure approximations that express $(m+1)^{\text{th}}$ order moments in terms of $m^{\text{th}}$ and lower order moments using different distributional assumptions, effectively closing the hierarchy and enabling one to solve the moment equations up to $m^{\text{th}}$ order [1]. Details of all closure methods currently implemented within the package can be found in the next Theory section.

    Central Moment Equations

    As we have seen, the moment equations of $P(\mathbf{n}, t)$ can be obtained in a straightforward manner if the kinetics of the system are governed by the law of mass action where all propensity functions are polynomials in $\mathbf{n}$ [1]. Similarly, given all propensities are rational functions, a polynomial form can also be recovered [2]. However, problems arise when the propensities take more complicated non-polynomial functions. This can nevertheless be overcome by considering a more general method of moment expansion that enables us to obtain mean and central moment equations up to arbitrary order for virtually any chemical reaction network with any type of smooth (infinitely differentiable) propensity functions. Such framework was first independently formulated by Lee [3] and Ale et al. [4]—our derivation below closely follows these works.

    We start by Taylor-expanding the propensity functions around the mean $\mathbf{μ} = \langle \mathbf{n} \rangle = (\mu_1, \dotsc, \mu_N)$. This allows us to consider any general propensity function under the assumption that it is infinitely differentiable (smooth). The expansion leads to

    \[\begin{align*} - a_r({\mathbf{n}}) &= a_{r}(\mathbf{μ}) + \sum_{j_1}^N \frac{\partial a_r(\mathbf{μ})}{\partial n_{j_1}}(n_{j_1}-\mu_{j_1}) \\ - &+ \frac{1}{2!}\sum_{j_1, j_2} \frac{\partial^2 a_r({\mathbf{μ}})}{\partial n_{j_1} \partial n_{j_2}} (n_{j_1}-\mu_{j_1}) (n_{j_2}-\mu_{j_2}) + \dotsb \\ - & + \frac{1}{q!} \sum_{j_1, j_2, \dotsc, j_q} \frac{\partial^q a_r(\mathbf{μ})}{\partial n_{j_1} \partial n_{j_2}\dotsm\partial n_{j_q}} (n_{j_1}-\mu_{j_1}) (n_{j_2}-\mu_{j_2}) \dotsm(n_{j_q} - \mu_{j_q}) + \dotsb \\ - &= \sum_{|\mathbf{j}|=0}^{q} \frac{1}{\mathbf{j}!} D^{\mathbf{j}} a_r(\mathbf{μ}) (\mathbf{n} - \mathbf{μ})^{\mathbf{j}} + \dotsb \;, -\end{align*}\]

    where $q$ controls the expansion order and we have simplified the expression by using Eqs. (3-7) in addition to:

    \[\begin{align*} -\mathbf{j}! &= j_1!\dotsm j_N!, \\ -D^{\,\mathbf{j}} f &= \frac{\partial^{|\mathbf{j}|}}{\partial n_1^{j_1} \dotsm \partial n_N^{j_N}} f \;. -\end{align*}\]

    Now we can obtain equations governing the time-evolution of the means $μ_i$ and the central moments $M_{\mathbf{i}} = M_{i_1, \dotsc, i_N} = \langle (n_1 - \mu_1)^{i_1}\dotsm(n_N - \mu_N)^{i_N} \rangle$, where again $|\mathbf{i}| \leq m$. We first consider the equations for the means immediately starting from Eq. (2):

    \[\begin{align*} - \frac{d\mu_i}{dt} &= \sum_{r} S_{ir} \langle a_r(\mathbf{n}) \rangle \\ - &= \sum_r S_{ir} \Big( \sum_{|\mathbf{j}|=0}^{q} \frac{1}{\mathbf{j}!} D^{\, \mathbf{j}} a_r(\mathbf{μ}) \langle (\mathbf{n} - \mathbf{μ})^{\mathbf{j}} \rangle + \dotsb \Big) \\ - &= \sum_r S_{ir} \Big( \sum_{|\mathbf{j}|=0}^{q} \frac{1}{\mathbf{j}!} D^{\, \mathbf{j}} a_r(\mathbf{μ}) M_{\mathbf{j}} + \dotsb \Big) \;. -\end{align*}\]

    We can now derive the equations for central moments by taking the time derivative of $M_{\mathbf{i}}$ and using Eq. (1):

    \[\begin{align*} - \frac{dM_{\mathbf{i}}}{dt} &= \sum_{\mathbf{n}} (n_1 - \mu_1)^{i_1}\dotsm(n_N - \mu_N)^{i_N} \frac{dP(\mathbf{n}, t)}{dt} \\ - &- \sum_{\mathbf{n}} \sum_{j=1}^{N} i_j \frac{d\mu_j}{dt} (n_1-\mu_1)^{i_1} \dotsm(n_j-\mu_j)^{i_j-1}\dotsm(n_N-\mu_N)^{i_N}P(\mathbf{n}, t) \\ - &= \sum_{r} \sum_{\mathbf{n}} \Big[ (n_1 - \mu_1 + S_{1r})^{i_1} \dotsm (n_N-\mu_N+S_{Nr})^{i_N} \\ - &- (n_1-\mu_1)^{i_1}\dotsm(n_N-\mu_N)^{i_N} \Big]a_r(\mathbf{n})P(\mathbf{n}, t) - \sum_j i_j \frac{d\mu_{j}}{dt}M_{i_1,\dotsc,i_{j}-1,\dotsc, i_N} \\ - &= \sum_r \sum_{\mathbf{n}} \Bigg[ \sum_{|\mathbf{j}|=0}^{|\mathbf{i}|-1} \binom{i_1}{j_1} \dotsm \binom{i_N}{j_N} S_{1r}^{\, i_1-j_1} \dotsm S_{Nr}^{\, i_N-j_N}(n_1-\mu_1)^{j_1}\dotsm(n_N-\mu_N)^{j_N}\Bigg] \\ - &\times \Bigg[ \sum_{|\mathbf{j}|=0}^{q} \frac{1}{\mathbf{j}!} D^{\mathbf{j}} a_r(\mathbf{μ}) (\mathbf{n} - \mathbf{μ})^{\mathbf{j}} + \dotsb \Bigg]-\sum_j i_j \frac{d\mu_{j}}{dt} M_{\mathbf{i}_{j-}} \\ - &= \sum_r \sum_{|\mathbf{j}|=0}^{|\mathbf{i}|-1} \Bigg[ \binom{i_1}{j_1} \dotsm \binom{i_N}{j_N} S_{1r}^{\, i_1-j_1} \dotsm S_{Nr}^{\, i_N-j_N} \sum_{|\mathbf{k}|=0}^{q-|\mathbf{j}|} \frac{1}{\mathbf{k}!}D^{\mathbf{k}} a_r(\mathbf{μ}) M_{\mathbf{j}+\mathbf{k}} + \dotsb \Bigg] \\ &- \sum_j i_j \frac{d\mu_{j}}{dt} M_{\mathbf{i}_{j-}} \\ - &= \sum_r \sum_{|\mathbf{j}|=0}^{|\mathbf{i}|-1} \Bigg[ \binom{\mathbf{i}}{\mathbf{j}} S_r^{\mathbf{i}-\mathbf{j}} \sum_{|\mathbf{k}|=0}^{q-|\mathbf{j}|} \frac{1}{\mathbf{k}!}D^{\mathbf{k}} a_r(\mathbf{μ}) M_{\mathbf{j}+\mathbf{k}} + \dotsb \Bigg] - \sum_j i_j \frac{d\mu_{j}}{dt} M_{\mathbf{i}_{j-}} \;, -\end{align*}\]

    where we have also defined

    \[\begin{align*} - M_{\mathbf{i}_{j-}}&=M_{i_1,\dotsc,i_{j}-1,\dotsc, i_N}, \\ - M_{\mathbf{j}+\mathbf{k}} &= M_{j_1+k_1,\dotsc,j_N+k_N} \;. -\end{align*}\]

    Although raw moment equations for non-linear mass-action systems already require approximate treatment using moment closure, here we have an additional complication: if a system contains non-polynomial propensity functions, the equations for both means and central moments will in principle depend on an infinite number of higher order central moments. Hence the Taylor expansion order $q$ is of utmost importance as it controls the degree of approximation: the propensity functions are expanded up to $q^{\text{th}}$ order so that $m^{\text{th}}$ central moment equations will depend on central moments of order $q>m$ and lower. Finally, moment closure approximations can be applied similarly as in the case of raw moment equations.

    References

    [1]: D. Schnoerr, G. Sanguinetti, and R. Grima, "Approximation and inference methods for stochastic biochemical kinetics - a tutorial review", Journal of Physics A: Mathematical and Theoretical 50, 093001 (2017). https://doi.org/10.1088/1751-8121/aa54d9

    [2]: P. Milner, C. S. Gillespie, and D. J. Wilkinson, "Moment closure approximations for stochastic kinetic models with rational rate laws", Mathematical Biosciences 231, 99-104 (2011). https://doi.org/10.1016/j.mbs.2011.02.006

    [3]: A. Ale, P. Kirk, and M. P. H. Stumpf, "A general moment expansion method for stochastic kinetic models", The Journal of Chemical Physics 138, 174101 (2013). https://doi.org/10.1063/1.4802475

    [4]: C. H. Lee, "A Moment Closure Method for Stochastic Chemical Reaction Networks with General Kinetics", MATCH Communications in Mathematical and in Computer Chemistry 70, 785-800 (2013). https://match.pmf.kg.ac.rs/electronicversions/Match70/n3/match70n3785-800.pdf

    +Moment Expansion (CME) · MomentClosure.jl

    Moment Expansion (CME)

    The Chemical Master Equation

    Consider a chemical reaction network with $N$ different molecular species $X_i$ ($i=1, \dotsc, N$) and $R$ chemical reactions, so that the system can be described by [1]:

    \[\begin{align*} + \sum_{i=1}^{N} s_{ij} X_{i} \xrightarrow{k_j} \sum_{i=1}^N r_{ij} X_i, \quad j=1,\dotsc,R, +\end{align*}\]

    where $s_{ij}$ and $r_{ij}$ respectively denote the numbers of reactant and product molecules of species $i$ in the chemical reaction $j$. The stoichiometric matrix is defined as $S_{ij} = r_{ij} - s_{ij}$ (the net change in the number of molecules of species $X_{i}$ when the $r^{\text{th}}$ reaction occurs). The state of the system is determined by the state vector $\mathbf{n}=(n_1, \dotsc, n_N)$, where $n_i$ is the number of $X_i$ molecules. The time evolution of the probability distribution of $\mathbf{n}$ is described by the Chemical Master Equation (CME)

    \[\begin{equation} + \frac{d P(\mathbf{n}, t)}{dt} = \sum^{R}_{r=1} \Big[ a_r(\mathbf{n}-S_r)P(\mathbf{n}-S_r, t) - a_r(\mathbf{n}) P(\mathbf{n}, t) \Big]\;, \tag{1} +\end{equation}\]

    where $a_{r}(\mathbf{n})$ is the propensity function of the $r^{\text{th}}$ reaction and $S_r$ is the $r^{\text{th}}$ column of the stoichiometric matrix $S$.

    Modelling using the CME framework is common in the study of biochemical and gene networks within cells. Although such master equations are rather simple in structure, for most systems there are no known analytical solutions and their stochastic simulations can be very computationally expensive. One possible approach to investigate the system at hand is to approximate the whole probability distribution solution of the CME in terms of its first few moments (e.g. mean and variance).

    Raw Moment Equations

    From Eq. (1) we can obtain a system of ordinary differential equations (ODEs) governing the time-evolution of the raw moments of the system up to specified moment expansion order $m$, given by $\mu_{\mathbf{i}} = \mu_{i_1, \dotsc, i_N} = \langle n_1^{i_1} \dotsm n_N^{i_N} \rangle$, where the indices $\mathbf{i}=(i_1, \dotsc, i_N)$ are restricted such that $|\mathbf{i}| = \sum_{j=1}^N i_j \leq m$. Note that first order raw moments are simply the means. For example, when N = 3, the mean molecule number of second species in the system is given by $\mu_2 = \mu_{0, 1, 0} = \langle n_2 \rangle$ (when $N=3$). We chose to relax the notation throughout so that the means can be indicated by a single index of the molecular species (used in this section) or by the corresponding one-hot vector (used in the code).

    To find the first moment equations, we multiply the CME by $n_i$ and sum over all possible states:

    \[\begin{align*} + \sum_{\mathbf{n}} n_i \frac{dP(\mathbf{n},t)}{dt} &= \sum_{n_1}^{\infty} \sum_{n_2}^{\infty} \dotsm \sum_{n_N}^{\infty} n_i \frac{dP(\mathbf{n},t)}{dt} \\ + &= \sum_{r} \sum_{\mathbf{n}} n_i a_r(\mathbf{n}-S_r)P(\mathbf{n}-S_r, t) - n_i a_r(\mathbf{n}) P(\mathbf{n}, t) \;. +\end{align*}\]

    Applying a transformation $\mathbf{n}-S_r \rightarrow \mathbf{n}$ on the first term in the sum leads to

    \[\begin{align*} + \frac{d\mu_i}{dt} &= \sum_{r} \sum_{\mathbf{n}} (n_i+S_{ir}) a_r(\mathbf{n})P(\mathbf{n}, t) - n_i a_r(\mathbf{n}) P(\mathbf{n}, t) \\ + &= \sum_{r} \sum_{\mathbf{n}} S_{ir} a_r({\mathbf{n}}) P(\mathbf{n}, t) \\ + &= \sum_{r} S_{ir} \langle a_r(\mathbf{n}) \rangle\;. \tag{2} +\end{align*}\]

    The derivation can be extended to the multivariate case of higher order moments $\mu_{\mathbf{i}}$ with $|\mathbf{i}| \leq m$:

    \[\begin{align*} + \frac{d\mu_{\mathbf{i}}}{dt} &= \sum_{\mathbf{n}} n_1^{i_1}\dotsm n_N^{i_N} \frac{dP(\mathbf{n}, t)}{dt} \\ + &= \sum_{r} \sum_{\mathbf{n}} \left[ (n_1+S_{1r})^{i_1}\dotsm (n_N +S_{2r})^{i_N} - n_1^{i_1}\dotsm n_N^{i_N} \right] a_r(\mathbf{n})P(\mathbf{n}, t) \\ + &= \sum_r \sum_{\mathbf{n}} \left[ \sum^{i_1}_{j_1=0} \binom{i_1}{j_1} n_{1}^{j_1}S_{1r}^{\,i_1-j_1} \dotsm \sum^{i_N}_{j_N=0} \binom{i_N}{j_N} n_{N}^{j_N}S_{Nr}^{\, i_N-j_N} - n_1^{i_1}\dotsm n_N^{i_N} \right] a_r(\mathbf{n})P(\mathbf{n}, t) \\ + &= \sum_r \sum_{\mathbf{n}} \sum^{|\mathbf{i}|-1}_{|\mathbf{j}|=0} \binom{i_1}{j_1} \dotsm \binom{i_N}{j_N} S_{1r}^{\,i_1-j_1} \dotsm S_{Nr}^{\, i_N-j_N} n_{1}^{j_1} \dotsm n_{N}^{j_N} a_r(\mathbf{n})P(\mathbf{n}, t) \\ + &= \sum_r \sum^{|\mathbf{i}|-1}_{|\mathbf{j}|=0} \binom{\, \mathbf{i} \,}{\, \mathbf{j} \,} S_r^{\,\mathbf{i}-\mathbf{j}} \langle \mathbf{n}^{\mathbf{j}} a_r(\mathbf{n}) \rangle \;, +\end{align*}\]

    where we have introduced multi-index notation:

    \[\begin{align} + |\mathbf{i}| &= \sum^{N}_{j=1} i_j , \tag{3} \\ + \sum^{|\mathbf{i}|-1}_{|\mathbf{j}|=0} &= \sum_{\substack{0 \leq j_1 \leq i_1, \, \dotsc, \, 0 \leq j_N \leq i_N\\ 0 \leq j_1+\dotsb+j_N \leq |\mathbf{i}|-1}} \tag{4} \\ + \binom{\, \mathbf{i} \,}{\, \mathbf{j} \,} &= \binom{i_1}{j_1} \dotsm \binom{i_N}{j_N} \tag{5}, \\ + \mathbf{n}^{\mathbf{j}} &= n_1^{j_1}\dotsm n_N^{j_N}, \tag{6} \\ + S_{r}^{\,\mathbf{i}-\mathbf{j}} &= S_{1r}^{\, i_1-j_1} \dotsm S_{Nr}^{\, i_N-j_N} \tag{7}\;. +\end{align}\]

    It is crucial to stress three key points:

    • Throughout all derivations presented in this section we assume that the components of the net stoichiometry matrix $S$ are constant values. However, in certain cases the reaction product may itself be a stochastic variable so that the corresponding expectation values, $\langle S_{r}^{\,\mathbf{i}-\mathbf{j}} \rangle$, must be taken into account. We have implemented a limited support for such systems where components of $S$ can be independent geometrically distributed variables, see the specific gene network example.
    • Generation of raw moment equations is only possible if the kinetics of the system at hand are governed by the law of mass action where all propensity functions are polynomials in $\mathbf{n}$, otherwise the expectation value terms $\langle a_r(\mathbf{n}) \rangle$ and $\langle n_{i_1}^{j_1} \dotsm n_{i_N}^{j_N} a_r(\mathbf{n}) \rangle$ are ill-defined. This key issue can be overcome by the general central moment expansion method presented below.
    • The order of the polynomials $a_r(\mathbf{n})$ determines the order of moments encountered in the generated system of ODEs. If the system is linear (contains only zeroth and first order reactions), the $m^{\text{th}}$ order moments will depend only of moments of order $m$ or lower, hence constituting a finite hierarchy of moment ODEs that can be readily solved numerically or otherwise without approximations. However, if the system is non-linear (involves second or higher order reactions), moment equations will depend on higher order moments. For example, if the reaction network contains bimolecular reactions, the corresponding propensity functions will be second order polynomials and hence $m^{\text{th}}$ order moment equations will now depend on $(m+1)^{th}$ order moments. This leads to an infinite hierarchy of coupled moment equations where each moment will depend on higher order moments—it cannot be solved directly and needs to be truncated. This can be achieved using one of many moment closure approximations that express $(m+1)^{\text{th}}$ order moments in terms of $m^{\text{th}}$ and lower order moments using different distributional assumptions, effectively closing the hierarchy and enabling one to solve the moment equations up to $m^{\text{th}}$ order [1]. Details of all closure methods currently implemented within the package can be found in the next Theory section.

    Central Moment Equations

    As we have seen, the moment equations of $P(\mathbf{n}, t)$ can be obtained in a straightforward manner if the kinetics of the system are governed by the law of mass action where all propensity functions are polynomials in $\mathbf{n}$ [1]. Similarly, given all propensities are rational functions, a polynomial form can also be recovered [2]. However, problems arise when the propensities take more complicated non-polynomial functions. This can nevertheless be overcome by considering a more general method of moment expansion that enables us to obtain mean and central moment equations up to arbitrary order for virtually any chemical reaction network with any type of smooth (infinitely differentiable) propensity functions. Such framework was first independently formulated by Lee [3] and Ale et al. [4]—our derivation below closely follows these works.

    We start by Taylor-expanding the propensity functions around the mean $\mathbf{μ} = \langle \mathbf{n} \rangle = (\mu_1, \dotsc, \mu_N)$. This allows us to consider any general propensity function under the assumption that it is infinitely differentiable (smooth). The expansion leads to

    \[\begin{align*} + a_r({\mathbf{n}}) &= a_{r}(\mathbf{μ}) + \sum_{j_1}^N \frac{\partial a_r(\mathbf{μ})}{\partial n_{j_1}}(n_{j_1}-\mu_{j_1}) \\ + &+ \frac{1}{2!}\sum_{j_1, j_2} \frac{\partial^2 a_r({\mathbf{μ}})}{\partial n_{j_1} \partial n_{j_2}} (n_{j_1}-\mu_{j_1}) (n_{j_2}-\mu_{j_2}) + \dotsb \\ + & + \frac{1}{q!} \sum_{j_1, j_2, \dotsc, j_q} \frac{\partial^q a_r(\mathbf{μ})}{\partial n_{j_1} \partial n_{j_2}\dotsm\partial n_{j_q}} (n_{j_1}-\mu_{j_1}) (n_{j_2}-\mu_{j_2}) \dotsm(n_{j_q} - \mu_{j_q}) + \dotsb \\ + &= \sum_{|\mathbf{j}|=0}^{q} \frac{1}{\mathbf{j}!} D^{\mathbf{j}} a_r(\mathbf{μ}) (\mathbf{n} - \mathbf{μ})^{\mathbf{j}} + \dotsb \;, +\end{align*}\]

    where $q$ controls the expansion order and we have simplified the expression by using Eqs. (3-7) in addition to:

    \[\begin{align*} +\mathbf{j}! &= j_1!\dotsm j_N!, \\ +D^{\,\mathbf{j}} f &= \frac{\partial^{|\mathbf{j}|}}{\partial n_1^{j_1} \dotsm \partial n_N^{j_N}} f \;. +\end{align*}\]

    Now we can obtain equations governing the time-evolution of the means $μ_i$ and the central moments $M_{\mathbf{i}} = M_{i_1, \dotsc, i_N} = \langle (n_1 - \mu_1)^{i_1}\dotsm(n_N - \mu_N)^{i_N} \rangle$, where again $|\mathbf{i}| \leq m$. We first consider the equations for the means immediately starting from Eq. (2):

    \[\begin{align*} + \frac{d\mu_i}{dt} &= \sum_{r} S_{ir} \langle a_r(\mathbf{n}) \rangle \\ + &= \sum_r S_{ir} \Big( \sum_{|\mathbf{j}|=0}^{q} \frac{1}{\mathbf{j}!} D^{\, \mathbf{j}} a_r(\mathbf{μ}) \langle (\mathbf{n} - \mathbf{μ})^{\mathbf{j}} \rangle + \dotsb \Big) \\ + &= \sum_r S_{ir} \Big( \sum_{|\mathbf{j}|=0}^{q} \frac{1}{\mathbf{j}!} D^{\, \mathbf{j}} a_r(\mathbf{μ}) M_{\mathbf{j}} + \dotsb \Big) \;. +\end{align*}\]

    We can now derive the equations for central moments by taking the time derivative of $M_{\mathbf{i}}$ and using Eq. (1):

    \[\begin{align*} + \frac{dM_{\mathbf{i}}}{dt} &= \sum_{\mathbf{n}} (n_1 - \mu_1)^{i_1}\dotsm(n_N - \mu_N)^{i_N} \frac{dP(\mathbf{n}, t)}{dt} \\ + &- \sum_{\mathbf{n}} \sum_{j=1}^{N} i_j \frac{d\mu_j}{dt} (n_1-\mu_1)^{i_1} \dotsm(n_j-\mu_j)^{i_j-1}\dotsm(n_N-\mu_N)^{i_N}P(\mathbf{n}, t) \\ + &= \sum_{r} \sum_{\mathbf{n}} \Big[ (n_1 - \mu_1 + S_{1r})^{i_1} \dotsm (n_N-\mu_N+S_{Nr})^{i_N} \\ + &- (n_1-\mu_1)^{i_1}\dotsm(n_N-\mu_N)^{i_N} \Big]a_r(\mathbf{n})P(\mathbf{n}, t) - \sum_j i_j \frac{d\mu_{j}}{dt}M_{i_1,\dotsc,i_{j}-1,\dotsc, i_N} \\ + &= \sum_r \sum_{\mathbf{n}} \Bigg[ \sum_{|\mathbf{j}|=0}^{|\mathbf{i}|-1} \binom{i_1}{j_1} \dotsm \binom{i_N}{j_N} S_{1r}^{\, i_1-j_1} \dotsm S_{Nr}^{\, i_N-j_N}(n_1-\mu_1)^{j_1}\dotsm(n_N-\mu_N)^{j_N}\Bigg] \\ + &\times \Bigg[ \sum_{|\mathbf{j}|=0}^{q} \frac{1}{\mathbf{j}!} D^{\mathbf{j}} a_r(\mathbf{μ}) (\mathbf{n} - \mathbf{μ})^{\mathbf{j}} + \dotsb \Bigg]-\sum_j i_j \frac{d\mu_{j}}{dt} M_{\mathbf{i}_{j-}} \\ + &= \sum_r \sum_{|\mathbf{j}|=0}^{|\mathbf{i}|-1} \Bigg[ \binom{i_1}{j_1} \dotsm \binom{i_N}{j_N} S_{1r}^{\, i_1-j_1} \dotsm S_{Nr}^{\, i_N-j_N} \sum_{|\mathbf{k}|=0}^{q-|\mathbf{j}|} \frac{1}{\mathbf{k}!}D^{\mathbf{k}} a_r(\mathbf{μ}) M_{\mathbf{j}+\mathbf{k}} + \dotsb \Bigg] \\ &- \sum_j i_j \frac{d\mu_{j}}{dt} M_{\mathbf{i}_{j-}} \\ + &= \sum_r \sum_{|\mathbf{j}|=0}^{|\mathbf{i}|-1} \Bigg[ \binom{\mathbf{i}}{\mathbf{j}} S_r^{\mathbf{i}-\mathbf{j}} \sum_{|\mathbf{k}|=0}^{q-|\mathbf{j}|} \frac{1}{\mathbf{k}!}D^{\mathbf{k}} a_r(\mathbf{μ}) M_{\mathbf{j}+\mathbf{k}} + \dotsb \Bigg] - \sum_j i_j \frac{d\mu_{j}}{dt} M_{\mathbf{i}_{j-}} \;, +\end{align*}\]

    where we have also defined

    \[\begin{align*} + M_{\mathbf{i}_{j-}}&=M_{i_1,\dotsc,i_{j}-1,\dotsc, i_N}, \\ + M_{\mathbf{j}+\mathbf{k}} &= M_{j_1+k_1,\dotsc,j_N+k_N} \;. +\end{align*}\]

    Although raw moment equations for non-linear mass-action systems already require approximate treatment using moment closure, here we have an additional complication: if a system contains non-polynomial propensity functions, the equations for both means and central moments will in principle depend on an infinite number of higher order central moments. Hence the Taylor expansion order $q$ is of utmost importance as it controls the degree of approximation: the propensity functions are expanded up to $q^{\text{th}}$ order so that $m^{\text{th}}$ central moment equations will depend on central moments of order $q>m$ and lower. Finally, moment closure approximations can be applied similarly as in the case of raw moment equations.

    References

    [1]: D. Schnoerr, G. Sanguinetti, and R. Grima, "Approximation and inference methods for stochastic biochemical kinetics - a tutorial review", Journal of Physics A: Mathematical and Theoretical 50, 093001 (2017). https://doi.org/10.1088/1751-8121/aa54d9

    [2]: P. Milner, C. S. Gillespie, and D. J. Wilkinson, "Moment closure approximations for stochastic kinetic models with rational rate laws", Mathematical Biosciences 231, 99-104 (2011). https://doi.org/10.1016/j.mbs.2011.02.006

    [3]: A. Ale, P. Kirk, and M. P. H. Stumpf, "A general moment expansion method for stochastic kinetic models", The Journal of Chemical Physics 138, 174101 (2013). https://doi.org/10.1063/1.4802475

    [4]: C. H. Lee, "A Moment Closure Method for Stochastic Chemical Reaction Networks with General Kinetics", MATCH Communications in Mathematical and in Computer Chemistry 70, 785-800 (2013). https://match.pmf.kg.ac.rs/electronicversions/Match70/n3/match70n3785-800.pdf

    diff --git a/dev/theory/moment_expansion_SDE/index.html b/dev/theory/moment_expansion_SDE/index.html index a119cc5..409eddc 100644 --- a/dev/theory/moment_expansion_SDE/index.html +++ b/dev/theory/moment_expansion_SDE/index.html @@ -1,29 +1,29 @@ -Moment Expansion (SDE) · MomentClosure.jl

    Moment Expansion (SDE)

    Moment equations can be also written down for models described by $N$-dimensional Stochastic Differential Equations (SDEs) of the form

    \[\begin{align*} - d\mathbf{n} = \mathbf{f} \left(\mathbf{n}, t \right) dt + \mathbf{G}\left( \mathbf{n}, t \right) d\mathbf{w}_t, -\end{align*}\]

    where $\mathbf{n}=(n_1, \dotsc, n_N)$ is a $N \times 1$ state vector, $\mathbf{f} \left(\mathbf{n}, t \right) = \left( f_1(\mathbf{n}, t), \dotsc, f_N(\mathbf{n}, t) \right)^\top$ is the deterministic (drift) term, $\mathbf{G}(\mathbf{n}, t)$ is a $N \times m$ (diffusion) matrix and $\mathbf{w}_t$ is a $m \times 1$ vector of Wiener processes so that $\langle d\mathbf{w}_t \rangle = \mathbf{0}$ and $d\mathbf{w}_t d\mathbf{w}_t^\top = \mathbf{I}\,dt$, with $\mathbf{I}$ being an $m \times m$ identity matrix. Note that the notation used throughout is consistent with that of the previous section, and the state vector here is the same as for a chemical reaction network of $N$ species (the only difference being that its elements are now continuous variables). The derivations below are based on Ghusinga et al. (2017) [1] and Bover (1978) [2].

    Raw Moment Equations

    To obtain the raw moment equations, we begin with Itô's lemma stating that for any smooth scalar function $h(\mathbf{n})$ one has

    \[\begin{align*} - dh(\mathbf{n}) = \left\{ \sum_{i=1}^N \frac{\partial h(\mathbf{n}) }{\partial n_i} f_i + \frac{1}{2} \sum_{i=1}^N \sum_{j=1}^N \frac{\partial^2 h(\mathbf{n}) }{\partial n_i \partial n_j} (\mathbf{G}\mathbf{G}^\top)_{ij} \right\}dt + \sum_{i=1}^N \sum_{j=1}^N \frac{\partial h(\mathbf{n}) }{\partial n_i} \mathbf{G}_{ij} dw_j \,. -\end{align*}\]

    Taking the expectation of both sides we obtain

    \[\begin{align*} - \frac{d \langle h(\mathbf{n}) \rangle}{dt} = \sum_{i=1}^N \left\langle \frac{\partial h(\mathbf{n})}{\partial n_i} f_i \right\rangle + \frac{1}{2} \sum_{i=1}^N \sum_{j=1}^N \left\langle \frac{\partial^2 h(\mathbf{n})}{\partial n_i \partial n_j} (\mathbf{G}\mathbf{G}^\top)_{ij}\right\rangle \,, -\end{align*}\]

    where we have used the fact that $\langle d\mathbf{w} \rangle = \mathbf{0}$. Finally, the general form of raw moment equations up to $m^{\text{th}}$ order is obtained by setting $h(\mathbf{n}) = \mathbf{n}^{\mathbf{i}} = n_1^{i_1} \dotsm n_N^{i_N}$, so that $\langle h(\mathbf{n}) \rangle = \mu_{\mathbf{i}}$ and $|\mathbf{i}| = \sum_{j=1}^N i_j \leq m$, leading to

    \[\begin{align*} - \frac{d\mu_{\mathbf{i}}}{dt} = \sum_{j=1}^N \left\langle \frac{\partial \mathbf{n}^{\mathbf{i}} }{\partial n_j} f_j \right\rangle + \frac{1}{2} \sum_{j=1}^N \sum_{k=1}^N \left\langle \frac{\partial^2 \mathbf{n}^{\mathbf{i}} }{\partial n_j \partial n_k} (\mathbf{G}\mathbf{G}^\top)_{jk}\right\rangle \,. -\end{align*}\]

    The equation for the mean vector $\mathbf{μ} = \langle \mathbf{n} \rangle = (\mu_1, \dotsc, \mu_N)$ take a particularly simple form (as the second derivatives are zero):

    \[\begin{align*} - \frac{d\mathbf{μ}}{dt} = \langle \mathbf{f}(\mathbf{n}, t) \rangle. -\end{align*}\]

    Central Moment Equations

    Note that the raw moment expansion formulated above is valid only when the SDE terms $\mathbf{f} \left(\mathbf{n}, t \right)$ and $\mathbf{G}(\mathbf{n}, t)$ are polynomial functions. If these functions are non-polynomial, we have to consider central moment equations and Taylor expand both $\mathbf{f} \left(\mathbf{n}, t \right)$ and $\mathbf{G}(\mathbf{n}, t)$ around the mean $\mathbf{μ}$ up to the expansion order $q$ (as done in case of the CME with non-polynomial propensities).

    The corresponding Taylor expansions can be written down as:

    \[\begin{align*} - f_j(\mathbf{n}) &= \sum_{|\mathbf{k}|=0}^{q} \frac{1}{\mathbf{k}!}D^{\mathbf{k}} f_j(\mathbf{μ}) (\mathbf{n} - \mathbf{μ})^{\mathbf{k}} + \dotsb \,, \\ - \left( \mathbf{G}(\mathbf{n}) \mathbf{G}(\mathbf{n})^\top \right)_{jk} &= \sum_{|\mathbf{l}|=0}^{q} \frac{1}{\mathbf{l}!} D^{\mathbf{l}} \left( \mathbf{G}(\mathbf{μ})\mathbf{G}(\mathbf{μ})^\top \right)_{jk} (\mathbf{n} - \mathbf{μ})^{\mathbf{l}} + \dotsb \,, -\end{align*}\]

    and we remind the reader that we have previously introduced the notation

    \[\begin{align*} -\mathbf{k}! &= k_1!\dotsm k_N!, \\ -D^{\mathbf{k}} f &= \frac{\partial^{|\mathbf{k}|}}{\partial n_1^{k_1} \dotsm \partial n_N^{k_N}} f,\\ -(\mathbf{n} - \mathbf{μ})^{\mathbf{k}} &= (n_1-\mu_1)^{k_1} \dotsm (n_N-\mu_N)^{k_N} \;. -\end{align*}\]

    It follows that the equations for the means can now be written down as:

    \[\begin{align*} - \frac{d\mu_i}{dt} = \langle f_i \rangle = \sum_{|\mathbf{j}|=0}^q \frac{1}{\mathbf{j}!} D^{\,\mathbf{j}} f_i(\mathbf{μ}) M_{\mathbf{j}} + \dotsb \,, -\end{align*}\]

    where $M_{\mathbf{j}} = \langle (\mathbf{n}-\mathbf{μ})^{\mathbf{j}} \rangle$ are central moments.

    To obtain the central moment equations, we first perform a change of variables $\mathbf{y} = \mathbf{n} - \langle \mathbf{n} \rangle$ and note again that $d\langle \mathbf{n} \rangle/dt = \langle \mathbf{f}(\mathbf{n}, t) \rangle$, so that the SDE becomes

    \[\begin{align*} - d\mathbf{y} = \left[ \mathbf{f}\left(\mathbf{y} + \langle\mathbf{n}\rangle, t \right) - \left\langle \mathbf{f} \left(\mathbf{y} + \langle\mathbf{n}\rangle, t \right) \right\rangle \right] dt + \mathbf{G}\left(\mathbf{y} + \langle\mathbf{n}\rangle, t \right) d\mathbf{w}_t \,. -\end{align*}\]

    Then, using Itô's lemma for a smooth function $h(\mathbf{y})$ and taking the expectation of both sides we find

    \[\begin{align*} - \frac{d \langle h(\mathbf{y}) \rangle}{dt} = \sum_{i=1}^N \left[ \left\langle \frac{\partial h(\mathbf{y})}{\partial y_i} f_i \right\rangle - \left\langle \frac{\partial h(\mathbf{y})}{\partial y_i} \right\rangle \left\langle f_i \right\rangle \right] + \frac{1}{2} \sum_{i=1}^N \sum_{j=1}^N \left\langle \frac{\partial^2 h(\mathbf{y})}{\partial y_i \partial y_j} (\mathbf{G}\mathbf{G}^\top)_{ij}\right\rangle \,. -\end{align*}\]

    Letting $h(\mathbf{y}) = (\mathbf{n} - \mathbf{μ})^{\mathbf{i}}$ and substituting in the needed Taylor expansions we obtain the final form of central moment equations:

    \[\begin{align*} - \frac{d M_{\mathbf{i}}}{dt} &= \sum_{j=1}^N \Bigg[ \left\langle \frac{\partial (\mathbf{n} - \mathbf{μ})^{\mathbf{i}} }{\partial (n_j - \mu_j)} \sum_{|\mathbf{k}|=0}^{q-|\mathbf{i}|+1} \frac{1}{\mathbf{k}!} D^{\mathbf{k}} f_j(\mathbf{μ}) (\mathbf{n}-\mathbf{μ})^\mathbf{k} + \dotsb \right\rangle \\ - &- \left\langle \frac{\partial (\mathbf{n}-\mathbf{μ})^{\mathbf{i}} }{\partial(n_j - μ_j)} \right\rangle \left\langle \sum_{|\mathbf{k}|=0}^{q} \frac{1}{\mathbf{k}!} D^{\mathbf{k}} f_j(\mathbf{μ}) (\mathbf{n}-\mathbf{μ})^\mathbf{k} + \dotsb \right\rangle \Bigg] \\ - &+ \frac{1}{2} \sum_{j=1}^N \sum_{k=1}^N \left\langle \frac{\partial^2 (\mathbf{n}-\mathbf{μ})^{\mathbf{i}}}{\partial(n_j-\mu_j)\partial(n_k-\mu_k)} \sum_{|\mathbf{l}|=0}^{q-|\mathbf{i}|+2} \frac{1}{\mathbf{l}!} D^{\,\mathbf{l}} \left( \mathbf{G}(\mathbf{μ}) \mathbf{G}(\mathbf{μ})^\top \right)_{jk} (\mathbf{n}-\mathbf{μ})^\mathbf{l} + \dotsc \right\rangle -\end{align*}\]

    References

    [1]: K. R. Ghusinga, M. Soltani, A. Lamperski, S. V. Dhople, and A. Singh, "Approximate moment dynamics for polynomial and trigonometric stochastic systems", IEEE 56th Annual Conference on Decision and Control (2017). https://doi.org/10.1109/CDC.2017.8263922

    [2]: D. C. C. Bover, "Moment Equation Methods for Nonlinear Stochastic Systems", Journal of Mathematical Analysis and Applications 65, 306-320 (1978). https://doi.org/10.1016/0022-247X(78)90182-8

    +Moment Expansion (SDE) · MomentClosure.jl

    Moment Expansion (SDE)

    Moment equations can be also written down for models described by $N$-dimensional Stochastic Differential Equations (SDEs) of the form

    \[\begin{align*} + d\mathbf{n} = \mathbf{f} \left(\mathbf{n}, t \right) dt + \mathbf{G}\left( \mathbf{n}, t \right) d\mathbf{w}_t, +\end{align*}\]

    where $\mathbf{n}=(n_1, \dotsc, n_N)$ is a $N \times 1$ state vector, $\mathbf{f} \left(\mathbf{n}, t \right) = \left( f_1(\mathbf{n}, t), \dotsc, f_N(\mathbf{n}, t) \right)^\top$ is the deterministic (drift) term, $\mathbf{G}(\mathbf{n}, t)$ is a $N \times m$ (diffusion) matrix and $\mathbf{w}_t$ is a $m \times 1$ vector of Wiener processes so that $\langle d\mathbf{w}_t \rangle = \mathbf{0}$ and $d\mathbf{w}_t d\mathbf{w}_t^\top = \mathbf{I}\,dt$, with $\mathbf{I}$ being an $m \times m$ identity matrix. Note that the notation used throughout is consistent with that of the previous section, and the state vector here is the same as for a chemical reaction network of $N$ species (the only difference being that its elements are now continuous variables). The derivations below are based on Ghusinga et al. (2017) [1] and Bover (1978) [2].

    Raw Moment Equations

    To obtain the raw moment equations, we begin with Itô's lemma stating that for any smooth scalar function $h(\mathbf{n})$ one has

    \[\begin{align*} + dh(\mathbf{n}) = \left\{ \sum_{i=1}^N \frac{\partial h(\mathbf{n}) }{\partial n_i} f_i + \frac{1}{2} \sum_{i=1}^N \sum_{j=1}^N \frac{\partial^2 h(\mathbf{n}) }{\partial n_i \partial n_j} (\mathbf{G}\mathbf{G}^\top)_{ij} \right\}dt + \sum_{i=1}^N \sum_{j=1}^N \frac{\partial h(\mathbf{n}) }{\partial n_i} \mathbf{G}_{ij} dw_j \,. +\end{align*}\]

    Taking the expectation of both sides we obtain

    \[\begin{align*} + \frac{d \langle h(\mathbf{n}) \rangle}{dt} = \sum_{i=1}^N \left\langle \frac{\partial h(\mathbf{n})}{\partial n_i} f_i \right\rangle + \frac{1}{2} \sum_{i=1}^N \sum_{j=1}^N \left\langle \frac{\partial^2 h(\mathbf{n})}{\partial n_i \partial n_j} (\mathbf{G}\mathbf{G}^\top)_{ij}\right\rangle \,, +\end{align*}\]

    where we have used the fact that $\langle d\mathbf{w} \rangle = \mathbf{0}$. Finally, the general form of raw moment equations up to $m^{\text{th}}$ order is obtained by setting $h(\mathbf{n}) = \mathbf{n}^{\mathbf{i}} = n_1^{i_1} \dotsm n_N^{i_N}$, so that $\langle h(\mathbf{n}) \rangle = \mu_{\mathbf{i}}$ and $|\mathbf{i}| = \sum_{j=1}^N i_j \leq m$, leading to

    \[\begin{align*} + \frac{d\mu_{\mathbf{i}}}{dt} = \sum_{j=1}^N \left\langle \frac{\partial \mathbf{n}^{\mathbf{i}} }{\partial n_j} f_j \right\rangle + \frac{1}{2} \sum_{j=1}^N \sum_{k=1}^N \left\langle \frac{\partial^2 \mathbf{n}^{\mathbf{i}} }{\partial n_j \partial n_k} (\mathbf{G}\mathbf{G}^\top)_{jk}\right\rangle \,. +\end{align*}\]

    The equation for the mean vector $\mathbf{μ} = \langle \mathbf{n} \rangle = (\mu_1, \dotsc, \mu_N)$ take a particularly simple form (as the second derivatives are zero):

    \[\begin{align*} + \frac{d\mathbf{μ}}{dt} = \langle \mathbf{f}(\mathbf{n}, t) \rangle. +\end{align*}\]

    Central Moment Equations

    Note that the raw moment expansion formulated above is valid only when the SDE terms $\mathbf{f} \left(\mathbf{n}, t \right)$ and $\mathbf{G}(\mathbf{n}, t)$ are polynomial functions. If these functions are non-polynomial, we have to consider central moment equations and Taylor expand both $\mathbf{f} \left(\mathbf{n}, t \right)$ and $\mathbf{G}(\mathbf{n}, t)$ around the mean $\mathbf{μ}$ up to the expansion order $q$ (as done in case of the CME with non-polynomial propensities).

    The corresponding Taylor expansions can be written down as:

    \[\begin{align*} + f_j(\mathbf{n}) &= \sum_{|\mathbf{k}|=0}^{q} \frac{1}{\mathbf{k}!}D^{\mathbf{k}} f_j(\mathbf{μ}) (\mathbf{n} - \mathbf{μ})^{\mathbf{k}} + \dotsb \,, \\ + \left( \mathbf{G}(\mathbf{n}) \mathbf{G}(\mathbf{n})^\top \right)_{jk} &= \sum_{|\mathbf{l}|=0}^{q} \frac{1}{\mathbf{l}!} D^{\mathbf{l}} \left( \mathbf{G}(\mathbf{μ})\mathbf{G}(\mathbf{μ})^\top \right)_{jk} (\mathbf{n} - \mathbf{μ})^{\mathbf{l}} + \dotsb \,, +\end{align*}\]

    and we remind the reader that we have previously introduced the notation

    \[\begin{align*} +\mathbf{k}! &= k_1!\dotsm k_N!, \\ +D^{\mathbf{k}} f &= \frac{\partial^{|\mathbf{k}|}}{\partial n_1^{k_1} \dotsm \partial n_N^{k_N}} f,\\ +(\mathbf{n} - \mathbf{μ})^{\mathbf{k}} &= (n_1-\mu_1)^{k_1} \dotsm (n_N-\mu_N)^{k_N} \;. +\end{align*}\]

    It follows that the equations for the means can now be written down as:

    \[\begin{align*} + \frac{d\mu_i}{dt} = \langle f_i \rangle = \sum_{|\mathbf{j}|=0}^q \frac{1}{\mathbf{j}!} D^{\,\mathbf{j}} f_i(\mathbf{μ}) M_{\mathbf{j}} + \dotsb \,, +\end{align*}\]

    where $M_{\mathbf{j}} = \langle (\mathbf{n}-\mathbf{μ})^{\mathbf{j}} \rangle$ are central moments.

    To obtain the central moment equations, we first perform a change of variables $\mathbf{y} = \mathbf{n} - \langle \mathbf{n} \rangle$ and note again that $d\langle \mathbf{n} \rangle/dt = \langle \mathbf{f}(\mathbf{n}, t) \rangle$, so that the SDE becomes

    \[\begin{align*} + d\mathbf{y} = \left[ \mathbf{f}\left(\mathbf{y} + \langle\mathbf{n}\rangle, t \right) - \left\langle \mathbf{f} \left(\mathbf{y} + \langle\mathbf{n}\rangle, t \right) \right\rangle \right] dt + \mathbf{G}\left(\mathbf{y} + \langle\mathbf{n}\rangle, t \right) d\mathbf{w}_t \,. +\end{align*}\]

    Then, using Itô's lemma for a smooth function $h(\mathbf{y})$ and taking the expectation of both sides we find

    \[\begin{align*} + \frac{d \langle h(\mathbf{y}) \rangle}{dt} = \sum_{i=1}^N \left[ \left\langle \frac{\partial h(\mathbf{y})}{\partial y_i} f_i \right\rangle - \left\langle \frac{\partial h(\mathbf{y})}{\partial y_i} \right\rangle \left\langle f_i \right\rangle \right] + \frac{1}{2} \sum_{i=1}^N \sum_{j=1}^N \left\langle \frac{\partial^2 h(\mathbf{y})}{\partial y_i \partial y_j} (\mathbf{G}\mathbf{G}^\top)_{ij}\right\rangle \,. +\end{align*}\]

    Letting $h(\mathbf{y}) = (\mathbf{n} - \mathbf{μ})^{\mathbf{i}}$ and substituting in the needed Taylor expansions we obtain the final form of central moment equations:

    \[\begin{align*} + \frac{d M_{\mathbf{i}}}{dt} &= \sum_{j=1}^N \Bigg[ \left\langle \frac{\partial (\mathbf{n} - \mathbf{μ})^{\mathbf{i}} }{\partial (n_j - \mu_j)} \sum_{|\mathbf{k}|=0}^{q-|\mathbf{i}|+1} \frac{1}{\mathbf{k}!} D^{\mathbf{k}} f_j(\mathbf{μ}) (\mathbf{n}-\mathbf{μ})^\mathbf{k} + \dotsb \right\rangle \\ + &- \left\langle \frac{\partial (\mathbf{n}-\mathbf{μ})^{\mathbf{i}} }{\partial(n_j - μ_j)} \right\rangle \left\langle \sum_{|\mathbf{k}|=0}^{q} \frac{1}{\mathbf{k}!} D^{\mathbf{k}} f_j(\mathbf{μ}) (\mathbf{n}-\mathbf{μ})^\mathbf{k} + \dotsb \right\rangle \Bigg] \\ + &+ \frac{1}{2} \sum_{j=1}^N \sum_{k=1}^N \left\langle \frac{\partial^2 (\mathbf{n}-\mathbf{μ})^{\mathbf{i}}}{\partial(n_j-\mu_j)\partial(n_k-\mu_k)} \sum_{|\mathbf{l}|=0}^{q-|\mathbf{i}|+2} \frac{1}{\mathbf{l}!} D^{\,\mathbf{l}} \left( \mathbf{G}(\mathbf{μ}) \mathbf{G}(\mathbf{μ})^\top \right)_{jk} (\mathbf{n}-\mathbf{μ})^\mathbf{l} + \dotsc \right\rangle +\end{align*}\]

    References

    [1]: K. R. Ghusinga, M. Soltani, A. Lamperski, S. V. Dhople, and A. Singh, "Approximate moment dynamics for polynomial and trigonometric stochastic systems", IEEE 56th Annual Conference on Decision and Control (2017). https://doi.org/10.1109/CDC.2017.8263922

    [2]: D. C. C. Bover, "Moment Equation Methods for Nonlinear Stochastic Systems", Journal of Mathematical Analysis and Applications 65, 306-320 (1978). https://doi.org/10.1016/0022-247X(78)90182-8

    diff --git a/dev/tutorials/LMA_example/index.html b/dev/tutorials/LMA_example/index.html index 371a316..b54a5d4 100644 --- a/dev/tutorials/LMA_example/index.html +++ b/dev/tutorials/LMA_example/index.html @@ -1,146 +1,146 @@ -LMA Example · MomentClosure.jl

    LMA Example

    In this example, we demonstrate how the Linear Mapping Approximation (LMA) can be applied on chemical reaction networks using MomentClosure. We illustrate the approach on models of a simple nonlinear feedback loop and a genetic toggle switch, in turn reproducing some of the results published in the original LMA paper by Cao and Grima [1].

    We start by considering a simple nonlinear gene regulatory network (GRN) shown in the diagram below (adapted from [1]):

    Here we have a two-state gene promoter which can be in either state $G$ or $G^*$. As in a previous example tutorial, we interpret the gene as a distinct species modelled as a Bernoulli variable $g$, associating the states $G$ and $G^*$ with values $g=1$ and $g=0$ respectively. Protein $P$ is produced from both gene states $G$ and $G^*$ (with different rates $ρ_u$ and $ρ_b$) and can subsequently decay. The switch between $G$ and $G^*$ (or the feedback) is introduced via protein binding to the gene in state $G$.

    The first step in applying the LMA is to transform the nonlinear GRN into a linear GRN. This can be done by removing the second-order reaction between $P$ and $G$, so that the reversible reaction $G+P \underset{σ_u}{\stackrel{σ_b}{\rightleftharpoons}} G^*$ is replaced by $G \underset{σ_u}{\stackrel{\bar{σ}_b}{\rightleftharpoons}} G^*$. This equivalent linear GRN can be visualised as (adapted from [1]):

    Note that MomentClosure cannot automate this linearisation step as the choice of how the other reactions in the network are changed due to the removal of nonlinear reactions is arbitrary. For this reason, we define both nonlinear and linear GRNs using Catalyst as follows:

    using Catalyst
    -
    -# NOTE: both models MUST preserve the same ordering of reactions in order to detect
    -# how the nonlinear reactions are to be transformed using LMA
    -
    -rn_nonlinear = @reaction_network begin
    -      @parameters σ_b σ_u ρ_b ρ_u
    -      σ_b, g + p → 0
    -      σ_u*(1-g), 0 ⇒ g + p
    -      ρ_u, g → g + p
    -      ρ_b*(1-g), 0 ⇒ p
    -      1, p → 0
    -end 
    -
    -rn_linear = @reaction_network begin
    -      @parameters σ_b_LMA σ_u ρ_b ρ_u
    -      σ_b_LMA, g → 0      # typing ̄σ_b is not allowed it seems
    -      σ_u*(1-g), 0 ⇒ g
    -      ρ_u, g → g+p
    -      (ρ_b*(1-g)), 0 ⇒ p
    -      1, p → 0
    -end 

    We can now apply the LMA to find the effective parameter $\bar{σ}_b$ and generate the corresponding moment equations of the linear GRN using MomentClosure's linear_mapping_approximation:

    using MomentClosure
    -
    -# NOTE: we have to provide the indices of binary variables in the system as they are ordered in the *nonlinear* GRN.
    -# The distinction here between linear and nonlinear GRNs is important as in some cases the internal ordering of variables of the two Catalyst models can differ
    -@parameters t
    -@variables g(t)
    -binary_vars = [speciesmap(rn_nonlinear)[g]]
    -
    -LMA_eqs, effective_params = linear_mapping_approximation(rn_nonlinear, rn_linear, binary_vars, combinatoric_ratelaws=false)
    -display(effective_params)
    OrderedDict{Any, Any} with 1 entry:
    -  σ_b_LMA => σ_b*μ₁₁(t)*(μ₁₀(t)^-1)

    We can also print out the moment equations:

    using Latexify
    -latexify(LMA_eqs)

    \[\begin{align*} -\frac{d\mu{_{10}}}{dt} =& \sigma_{u} - \sigma_{b} \mu{_{11}} - \sigma_{u} \mu{_{10}} \\ -\frac{d\mu{_{01}}}{dt} =& \rho_{b} + \rho_{u} \mu{_{10}} - \mu{_{01}} - \rho_{b} \mu{_{10}} \\ -\frac{d\mu{_{11}}}{dt} =& \rho_{u} \mu{_{10}} + \sigma_{u} \mu{_{01}} - \mu{_{11}} - \sigma_{u} \mu{_{11}} - \sigma_{b} \mu{_{10}}^{-1} \mu{_{11}}^{2} \\ -\frac{d\mu{_{02}}}{dt} =& \rho_{b} + \rho_{u} \mu{_{10}} + 2 \rho_{b} \mu{_{01}} + 2 \rho_{u} \mu{_{11}} + \mu{_{01}} - 2 \mu{_{02}} - \rho_{b} \mu{_{10}} - 2 \rho_{b} \mu{_{11}} -\end{align*}\]

    Note that the results agree with Eqs. (1) and (2) (after a corresponding substitution) given in [1]. The moment equations are already closed, so we can solve them numerically and plot the mean protein number over time:

    using OrdinaryDiffEq, Sundials, Plots
    -
    -# [g, p] as in `species(rn_nonlinear)`
    -u₀ = [1.0, 0.001]
    -p = [0.004, 0.25, 25.0, 60.0]
    -tspan = (0., 15.)
    -dt = 0.1
    -
    -u₀map = deterministic_IC(u₀, LMA_eqs)
    -oprob_LMA = ODEProblem(LMA_eqs, u₀map, tspan, p)
    -sol_LMA = solve(oprob_LMA, CVODE_BDF(), saveat=dt)
    -
    -plot(sol_LMA, idxs=[2], label="LMA", ylabel="⟨p⟩", xlabel="time", fmt="svg")

    LMA feedback loop mean protein number

    To compare the LMA result to the true moment dynamics we use the Finite State Projection (FSP) algorithm implemented in FiniteStateProjection.jl. FSP can be much more efficient than SSA in accurately approximating the full time-dependent probability distribution of the given chemical system when the system's state space is small (hence it is particularly effective for the nonlinear GRN here). Having obtained the FSP solution, we can extract the time-evolution of moments using get_moments_FSP function and finally compare it to the LMA prediction. This can all be done as follows:

    using FiniteStateProjection
    -
    -fsp_sys = FSPSystem(rn_nonlinear, combinatoric_ratelaw=false)
    -# Truncate the state space of the system
    -# The gene has two states (G or G*) whereas we consider protein number from 0 to 100
    -state_space = [2, 101]
    -
    -# The initial condition is the matrix of probabilities representing the state of the system
    -# We assume zero protein and the gene to be in the state G, hence the probability of this
    -# specific state should be set to 1 initially
    -u0 = zeros(state_space...)
    -u0[2, 1] = 1.0
    -
    -# construct an ODE problem from the FSPSystem and solve it
    -fsp_prob = ODEProblem(fsp_sys, u0, tspan, p)
    -sol_FSP = solve(fsp_prob, CVODE_BDF(), saveat=dt)
    -
    -# extract the 1st order raw moments from the FSP solution
    -μ_FSP = get_moments_FSP(sol_FSP, 1, "raw")
    -plot!(sol_FSP.t, μ_FSP[(0,1)], label="FSP", legend=:bottomright)

    LMA and FSP feedback loop mean protein number

    Using the LMA as implemented in MomentClosure, we can generate and solve the closed moment equations for any LMA-suitable nonlinear chemical reaction network, given that its linear equivalent is also provided. Proceeding further to obtain an approximate time-dependent probability distribution of the nonlinear network is more involved as only a handful of closed-form solutions of linear networks are known. Moreover, simply computing the solutions can be a challenge due to their complicated analytical form. For these reasons, MomentClosure does not provide an automated approach to computing the probability distributions of the relevant nonlinear systems using LMA—these steps have to performed manually on a case-by-case basis. Nevertheless, below we demonstrate how this could be done for the nonlinear GRN we have been considering so far.

    The CME of the nonlinear feedback loop can be solved exactly as described in [1] and, for completeness, we write down the main result here. The probability distribution of the number of proteins $n_p$ at time $t$ is given by (assuming the initial conditions to be zero protein in state $G$):

    \[P \left( n_p, t \right) = \frac{1}{n_p!} \frac{d^{n_p}}{dw^{n_p}}\left( G_0(w, t) + G_1(w, t) \right) |_{w=-1},\]

    where

    \[\begin{align*} -G_0(w, t) &= \exp(ρ_b w) \left[ f(we^{-t}) (-\rho_\Delta w)^{1-\Sigma} M(1-\bar{\sigma}_b, 2-\Sigma, -\rho_\Delta w) \\ -+ g(we^{-t})M(1+\sigma_u,\Sigma,-\rho_\Delta w) \right],\\ -G_1(w, t) &= \sigma_u^{-1} \exp(\rho_b w) \left[ -\sigma_u f(we^{-t})(-\rho_\Delta w)^{1-\Sigma} M(-\bar{\sigma}_b, 2-\Sigma, -\rho_\Delta w) \\ -+\bar{\sigma}_b g(we^{-t}) M(\sigma_u, \Sigma, -\rho_\Delta w) \right], -\end{align*}\]

    where $w=z-1$ and the probability generating functions are given by $G_i(z, t) = \sum_{n_p=0}^\infty z^{n_p} P_i(n_p, t)$. The function $M(\cdot,\cdot,\cdot)$ stands for the Kummer's (confluent hypergeometric) function and we also use the following definitions:

    \[\begin{align*} - \rho_\Delta &= \rho_b - \rho_u, \\ - \Sigma &= \sigma_u + \bar{\sigma}_b + 1, \\ - f(w) &= \frac{\bar{\sigma}_b}{\Sigma-1}(-\rho_\Delta w)^{\Sigma-1}e^{-\rho_u w}M(\sigma_u, \Sigma, -\rho_\Delta w), \\ - g(w) &= \frac{\sigma_u}{\Sigma-1}e^{-\rho_u w} M(-\bar{\sigma}_b, 2-\Sigma, -\rho_\Delta w). -\end{align*}\]

    One can observe that having a closed-form solution does not make life that much easier as now we have to find a way how to numerically evaluate these complicated mathematical expressions in a reasonably efficient manner. The main problem here is that in order to construct the probability distribution we have to take arbitrarily high $n^{th}$ order derivatives. Doing that symbolically is possible in principle but can be extremely computationally expensive as the symbolic expressions will be expanding exponentially in size with each higher derivative order: keeping them in memory is expensive and the same terms would have to be evaluated repeatedly many times. Similarly, naively nesting numerical derivative operations using an automatic differentiation framework is possible but still many redundant operations would need to be performed.

    As pointed out by the authors in [1], a more efficient way is to expand the generating functions $G_0(w, t) + G_1(w, t)$ around $w=-1$ as then the $n^{th}$ Taylor series coefficient will be equivalent to the probability of having $n$ proteins at time $t$. This approach can be particularly effective: recursion relations for the Taylor coefficients of various elementary functions can be defined and in turn utilised to minimise the amount of redundant work which has to be performed when Taylor expanding any given mathematical expression. Such higher-order automatic differentiation framework in Julia is provided by TaylorSeries.jl.

    However, TaylorSeries only supports elementary function operations at the time and hence evaluating the Kummer's function $M(\cdot,\cdot,\cdot)$ requires some more work (these specialised numerics are readily available in more established scientific computing frameworks such as Mathematica but there's no fun in that). We can extend the TaylorSeries framework by constructing a function t_pFq that implements a recurrence relation between the Taylor coefficients for the generalized hypergeometric function pFq as defined in HypergeometricFunctions.jl. This can be done as follows (note that our construction is valid only for a single-variable Taylor series Taylor1):

    using TaylorSeries, HypergeometricFunctions
    -using HypergeometricFunctions: pFqweniger
    -
    -# please let me know if a simpler and more efficient way to do this exists!
    -function t_pFq(α::AbstractVector, β::AbstractVector, a::Taylor1)
    -    order = a.order
    -    aux = pFqweniger(α, β, constant_term(a))
    -    c = Taylor1(aux, order)
    -
    -    iszero(order) && return c
    -
    -    coeffs = t_pFq(α.+1, β.+1, Taylor1(a[0:end-1], a.order-1))
    -    factor = prod(α)/prod(β)
    -    for k in 1:length(a)-1
    -        c[k] = sum(i * a[i] * coeffs[k-i] for i in 1:k) * factor / k
    -    end
    -
    -    return c
    -
    -end

    We can now move on with the LMA procedure to obtain the probability distribution of the nonlinear GRN for the number of proteins at a chosen time point $t=4$. Step 4 of the LMA involves obtaining the time-independent effective parameter $\bar{\sigma}_b$ which is given by its time-averaged value:

    # calculate the raw moments up to time t at a fine temporal resolution
    -T = 4.0
    -tspan = (0., T)
    -dt = 0.001
    -oprob_LMA = remake(oprob_LMA, tspan=tspan)
    -sol_LMA = solve(oprob_LMA, CVODE_BDF(), saveat=dt)
    -
    -# rebuild the symbolic expression for the effective parameter as a function of raw moments
    -μ_sym = [LMA_eqs.odes.states...]
    -p_sub = Dict.(Pair.(LMA_eqs.odes.ps, p)...)
    -avg_σ_b_sym = collect(values(effective_params))[1]
    -fn = build_function(substitute(avg_σ_b_sym, p_sub), μ_sym)
    -avg_σ_b = eval(fn)
    -# evaluate the time-averaged value of the effective parameter
    -@time σ_b_avg = sum(avg_σ_b.(sol_LMA.u)) * dt / T

    We proceed with the very last steps of the LMA to obtain the probability distribution:

    # need higher-precision numerics as Float64 can be unstable here due to very small numbers
    -# DoubleFloats is sufficient for this example and much more efficient than BigFloat
    -using DoubleFloats
    -
    -# define the numerical values of the parameters
    -σ_u = p[2]; ρ_b = p[3]; ρ_u = p[4]
    -Σ = 1 + σ_b_avg + σ_u
    -ρ_Δ = ρ_b - ρ_u
    -
    -n = 100 # expansion order (or max protein number to evaluate)
    -w₀ = -1 # value around which to expand
    -
    -# compute the Taylor expansion (note the use of Double64)
    -w = w₀ + Taylor1(Double64, n)
    -@time f = σ_b_avg/(Σ-1)*exp(-T*(Σ-1))*exp(-ρ_u*w*exp(-T))*t_pFq([σ_u], [Σ], -ρ_Δ*w*exp(-T))
    -@time g = σ_u/(Σ-1)*exp(-ρ_u*w*exp(-T))*t_pFq([-σ_b_avg], [2-Σ], -ρ_Δ*w*exp(-T))
    -
    -@time G00 = exp(ρ_b*w)*(f * t_pFq([1-σ_b_avg], [2-Σ], -ρ_Δ*w) +
    -                  g * t_pFq([1+σ_u], [Σ], -ρ_Δ*w) )
    -
    -@time G11 = σ_u^(-1) * exp(ρ_b*w) * (-σ_u*f*t_pFq([-σ_b_avg], [2-Σ], -ρ_Δ*w) +
    -                                σ_b_avg*g*t_pFq([σ_u], [Σ], -ρ_Δ*w))
    -
    -probs = (G00+G11).coeffs
    -
    -# check that the probability distribution is more or less normalised to 1
    -# need higher numerical precision if not
    -isapprox(sum(probs), 1.0, rtol=1e-2)
    0.009289 seconds (41.03 k allocations: 1.603 MiB)
    -0.009126 seconds (41.03 k allocations: 1.603 MiB)
    -0.067889 seconds (85.06 k allocations: 3.613 MiB)
    -0.066194 seconds (85.07 k allocations: 3.618 MiB)
    -true

    Finally, we can plot the distribution and compare it to the FSP result:

    plot(0:n, probs, xlabel="n", ylabel="P(n, t=4)", label="LMA", fmt="svg")
    -# plot the FSP probability of protein number by marginalising over the gene states
    -plot!(0:n, sum(sol_FSP[:, 41], dims=1)'[1:n+1], label="FSP")

    LMA FSP feedback loop distribution

    References

    [1]: Z. Cao and R. Grima, "Linear mapping approximation of gene regulatory networks with stochastic dynamics", Nature Communications 9, 3305 (2018). https://doi.org/10.1038/s41467-018-05822-0

    +LMA Example · MomentClosure.jl

    LMA Example

    In this example, we demonstrate how the Linear Mapping Approximation (LMA) can be applied on chemical reaction networks using MomentClosure. We illustrate the approach on models of a simple nonlinear feedback loop and a genetic toggle switch, in turn reproducing some of the results published in the original LMA paper by Cao and Grima [1].

    We start by considering a simple nonlinear gene regulatory network (GRN) shown in the diagram below (adapted from [1]):

    Here we have a two-state gene promoter which can be in either state $G$ or $G^*$. As in a previous example tutorial, we interpret the gene as a distinct species modelled as a Bernoulli variable $g$, associating the states $G$ and $G^*$ with values $g=1$ and $g=0$ respectively. Protein $P$ is produced from both gene states $G$ and $G^*$ (with different rates $ρ_u$ and $ρ_b$) and can subsequently decay. The switch between $G$ and $G^*$ (or the feedback) is introduced via protein binding to the gene in state $G$.

    The first step in applying the LMA is to transform the nonlinear GRN into a linear GRN. This can be done by removing the second-order reaction between $P$ and $G$, so that the reversible reaction $G+P \underset{σ_u}{\stackrel{σ_b}{\rightleftharpoons}} G^*$ is replaced by $G \underset{σ_u}{\stackrel{\bar{σ}_b}{\rightleftharpoons}} G^*$. This equivalent linear GRN can be visualised as (adapted from [1]):

    Note that MomentClosure cannot automate this linearisation step as the choice of how the other reactions in the network are changed due to the removal of nonlinear reactions is arbitrary. For this reason, we define both nonlinear and linear GRNs using Catalyst as follows:

    using Catalyst
    +
    +# NOTE: both models MUST preserve the same ordering of reactions in order to detect
    +# how the nonlinear reactions are to be transformed using LMA
    +
    +rn_nonlinear = @reaction_network begin
    +      @parameters σ_b σ_u ρ_b ρ_u
    +      σ_b, g + p → 0
    +      σ_u*(1-g), 0 ⇒ g + p
    +      ρ_u, g → g + p
    +      ρ_b*(1-g), 0 ⇒ p
    +      1, p → 0
    +end 
    +
    +rn_linear = @reaction_network begin
    +      @parameters σ_b_LMA σ_u ρ_b ρ_u
    +      σ_b_LMA, g → 0      # typing ̄σ_b is not allowed it seems
    +      σ_u*(1-g), 0 ⇒ g
    +      ρ_u, g → g+p
    +      (ρ_b*(1-g)), 0 ⇒ p
    +      1, p → 0
    +end 

    We can now apply the LMA to find the effective parameter $\bar{σ}_b$ and generate the corresponding moment equations of the linear GRN using MomentClosure's linear_mapping_approximation:

    using MomentClosure
    +
    +# NOTE: we have to provide the indices of binary variables in the system as they are ordered in the *nonlinear* GRN.
    +# The distinction here between linear and nonlinear GRNs is important as in some cases the internal ordering of variables of the two Catalyst models can differ
    +@parameters t
    +@variables g(t)
    +binary_vars = [speciesmap(rn_nonlinear)[g]]
    +
    +LMA_eqs, effective_params = linear_mapping_approximation(rn_nonlinear, rn_linear, binary_vars, combinatoric_ratelaws=false)
    +display(effective_params)
    OrderedDict{Any, Any} with 1 entry:
    +  σ_b_LMA => σ_b*μ₁₁(t)*(μ₁₀(t)^-1)

    We can also print out the moment equations:

    using Latexify
    +latexify(LMA_eqs)

    \[\begin{align*} +\frac{d\mu{_{10}}}{dt} =& \sigma_{u} - \sigma_{b} \mu{_{11}} - \sigma_{u} \mu{_{10}} \\ +\frac{d\mu{_{01}}}{dt} =& \rho_{b} + \rho_{u} \mu{_{10}} - \mu{_{01}} - \rho_{b} \mu{_{10}} \\ +\frac{d\mu{_{11}}}{dt} =& \rho_{u} \mu{_{10}} + \sigma_{u} \mu{_{01}} - \mu{_{11}} - \sigma_{u} \mu{_{11}} - \sigma_{b} \mu{_{10}}^{-1} \mu{_{11}}^{2} \\ +\frac{d\mu{_{02}}}{dt} =& \rho_{b} + \rho_{u} \mu{_{10}} + 2 \rho_{b} \mu{_{01}} + 2 \rho_{u} \mu{_{11}} + \mu{_{01}} - 2 \mu{_{02}} - \rho_{b} \mu{_{10}} - 2 \rho_{b} \mu{_{11}} +\end{align*}\]

    Note that the results agree with Eqs. (1) and (2) (after a corresponding substitution) given in [1]. The moment equations are already closed, so we can solve them numerically and plot the mean protein number over time:

    using OrdinaryDiffEq, Sundials, Plots
    +
    +# [g, p] as in `species(rn_nonlinear)`
    +u₀ = [1.0, 0.001]
    +p = [0.004, 0.25, 25.0, 60.0]
    +tspan = (0., 15.)
    +dt = 0.1
    +
    +u₀map = deterministic_IC(u₀, LMA_eqs)
    +oprob_LMA = ODEProblem(LMA_eqs, u₀map, tspan, p)
    +sol_LMA = solve(oprob_LMA, CVODE_BDF(), saveat=dt)
    +
    +plot(sol_LMA, idxs=[2], label="LMA", ylabel="⟨p⟩", xlabel="time", fmt="svg")

    LMA feedback loop mean protein number

    To compare the LMA result to the true moment dynamics we use the Finite State Projection (FSP) algorithm implemented in FiniteStateProjection.jl. FSP can be much more efficient than SSA in accurately approximating the full time-dependent probability distribution of the given chemical system when the system's state space is small (hence it is particularly effective for the nonlinear GRN here). Having obtained the FSP solution, we can extract the time-evolution of moments using get_moments_FSP function and finally compare it to the LMA prediction. This can all be done as follows:

    using FiniteStateProjection
    +
    +fsp_sys = FSPSystem(rn_nonlinear, combinatoric_ratelaw=false)
    +# Truncate the state space of the system
    +# The gene has two states (G or G*) whereas we consider protein number from 0 to 100
    +state_space = [2, 101]
    +
    +# The initial condition is the matrix of probabilities representing the state of the system
    +# We assume zero protein and the gene to be in the state G, hence the probability of this
    +# specific state should be set to 1 initially
    +u0 = zeros(state_space...)
    +u0[2, 1] = 1.0
    +
    +# construct an ODE problem from the FSPSystem and solve it
    +fsp_prob = ODEProblem(fsp_sys, u0, tspan, p)
    +sol_FSP = solve(fsp_prob, CVODE_BDF(), saveat=dt)
    +
    +# extract the 1st order raw moments from the FSP solution
    +μ_FSP = get_moments_FSP(sol_FSP, 1, "raw")
    +plot!(sol_FSP.t, μ_FSP[(0,1)], label="FSP", legend=:bottomright)

    LMA and FSP feedback loop mean protein number

    Using the LMA as implemented in MomentClosure, we can generate and solve the closed moment equations for any LMA-suitable nonlinear chemical reaction network, given that its linear equivalent is also provided. Proceeding further to obtain an approximate time-dependent probability distribution of the nonlinear network is more involved as only a handful of closed-form solutions of linear networks are known. Moreover, simply computing the solutions can be a challenge due to their complicated analytical form. For these reasons, MomentClosure does not provide an automated approach to computing the probability distributions of the relevant nonlinear systems using LMA—these steps have to performed manually on a case-by-case basis. Nevertheless, below we demonstrate how this could be done for the nonlinear GRN we have been considering so far.

    The CME of the nonlinear feedback loop can be solved exactly as described in [1] and, for completeness, we write down the main result here. The probability distribution of the number of proteins $n_p$ at time $t$ is given by (assuming the initial conditions to be zero protein in state $G$):

    \[P \left( n_p, t \right) = \frac{1}{n_p!} \frac{d^{n_p}}{dw^{n_p}}\left( G_0(w, t) + G_1(w, t) \right) |_{w=-1},\]

    where

    \[\begin{align*} +G_0(w, t) &= \exp(ρ_b w) \left[ f(we^{-t}) (-\rho_\Delta w)^{1-\Sigma} M(1-\bar{\sigma}_b, 2-\Sigma, -\rho_\Delta w) \\ ++ g(we^{-t})M(1+\sigma_u,\Sigma,-\rho_\Delta w) \right],\\ +G_1(w, t) &= \sigma_u^{-1} \exp(\rho_b w) \left[ -\sigma_u f(we^{-t})(-\rho_\Delta w)^{1-\Sigma} M(-\bar{\sigma}_b, 2-\Sigma, -\rho_\Delta w) \\ ++\bar{\sigma}_b g(we^{-t}) M(\sigma_u, \Sigma, -\rho_\Delta w) \right], +\end{align*}\]

    where $w=z-1$ and the probability generating functions are given by $G_i(z, t) = \sum_{n_p=0}^\infty z^{n_p} P_i(n_p, t)$. The function $M(\cdot,\cdot,\cdot)$ stands for the Kummer's (confluent hypergeometric) function and we also use the following definitions:

    \[\begin{align*} + \rho_\Delta &= \rho_b - \rho_u, \\ + \Sigma &= \sigma_u + \bar{\sigma}_b + 1, \\ + f(w) &= \frac{\bar{\sigma}_b}{\Sigma-1}(-\rho_\Delta w)^{\Sigma-1}e^{-\rho_u w}M(\sigma_u, \Sigma, -\rho_\Delta w), \\ + g(w) &= \frac{\sigma_u}{\Sigma-1}e^{-\rho_u w} M(-\bar{\sigma}_b, 2-\Sigma, -\rho_\Delta w). +\end{align*}\]

    One can observe that having a closed-form solution does not make life that much easier as now we have to find a way how to numerically evaluate these complicated mathematical expressions in a reasonably efficient manner. The main problem here is that in order to construct the probability distribution we have to take arbitrarily high $n^{th}$ order derivatives. Doing that symbolically is possible in principle but can be extremely computationally expensive as the symbolic expressions will be expanding exponentially in size with each higher derivative order: keeping them in memory is expensive and the same terms would have to be evaluated repeatedly many times. Similarly, naively nesting numerical derivative operations using an automatic differentiation framework is possible but still many redundant operations would need to be performed.

    As pointed out by the authors in [1], a more efficient way is to expand the generating functions $G_0(w, t) + G_1(w, t)$ around $w=-1$ as then the $n^{th}$ Taylor series coefficient will be equivalent to the probability of having $n$ proteins at time $t$. This approach can be particularly effective: recursion relations for the Taylor coefficients of various elementary functions can be defined and in turn utilised to minimise the amount of redundant work which has to be performed when Taylor expanding any given mathematical expression. Such higher-order automatic differentiation framework in Julia is provided by TaylorSeries.jl.

    However, TaylorSeries only supports elementary function operations at the time and hence evaluating the Kummer's function $M(\cdot,\cdot,\cdot)$ requires some more work (these specialised numerics are readily available in more established scientific computing frameworks such as Mathematica but there's no fun in that). We can extend the TaylorSeries framework by constructing a function t_pFq that implements a recurrence relation between the Taylor coefficients for the generalized hypergeometric function pFq as defined in HypergeometricFunctions.jl. This can be done as follows (note that our construction is valid only for a single-variable Taylor series Taylor1):

    using TaylorSeries, HypergeometricFunctions
    +using HypergeometricFunctions: pFqweniger
    +
    +# please let me know if a simpler and more efficient way to do this exists!
    +function t_pFq(α::AbstractVector, β::AbstractVector, a::Taylor1)
    +    order = a.order
    +    aux = pFqweniger(α, β, constant_term(a))
    +    c = Taylor1(aux, order)
    +
    +    iszero(order) && return c
    +
    +    coeffs = t_pFq(α.+1, β.+1, Taylor1(a[0:end-1], a.order-1))
    +    factor = prod(α)/prod(β)
    +    for k in 1:length(a)-1
    +        c[k] = sum(i * a[i] * coeffs[k-i] for i in 1:k) * factor / k
    +    end
    +
    +    return c
    +
    +end

    We can now move on with the LMA procedure to obtain the probability distribution of the nonlinear GRN for the number of proteins at a chosen time point $t=4$. Step 4 of the LMA involves obtaining the time-independent effective parameter $\bar{\sigma}_b$ which is given by its time-averaged value:

    # calculate the raw moments up to time t at a fine temporal resolution
    +T = 4.0
    +tspan = (0., T)
    +dt = 0.001
    +oprob_LMA = remake(oprob_LMA, tspan=tspan)
    +sol_LMA = solve(oprob_LMA, CVODE_BDF(), saveat=dt)
    +
    +# rebuild the symbolic expression for the effective parameter as a function of raw moments
    +μ_sym = [LMA_eqs.odes.states...]
    +p_sub = Dict.(Pair.(LMA_eqs.odes.ps, p)...)
    +avg_σ_b_sym = collect(values(effective_params))[1]
    +fn = build_function(substitute(avg_σ_b_sym, p_sub), μ_sym)
    +avg_σ_b = eval(fn)
    +# evaluate the time-averaged value of the effective parameter
    +@time σ_b_avg = sum(avg_σ_b.(sol_LMA.u)) * dt / T

    We proceed with the very last steps of the LMA to obtain the probability distribution:

    # need higher-precision numerics as Float64 can be unstable here due to very small numbers
    +# DoubleFloats is sufficient for this example and much more efficient than BigFloat
    +using DoubleFloats
    +
    +# define the numerical values of the parameters
    +σ_u = p[2]; ρ_b = p[3]; ρ_u = p[4]
    +Σ = 1 + σ_b_avg + σ_u
    +ρ_Δ = ρ_b - ρ_u
    +
    +n = 100 # expansion order (or max protein number to evaluate)
    +w₀ = -1 # value around which to expand
    +
    +# compute the Taylor expansion (note the use of Double64)
    +w = w₀ + Taylor1(Double64, n)
    +@time f = σ_b_avg/(Σ-1)*exp(-T*(Σ-1))*exp(-ρ_u*w*exp(-T))*t_pFq([σ_u], [Σ], -ρ_Δ*w*exp(-T))
    +@time g = σ_u/(Σ-1)*exp(-ρ_u*w*exp(-T))*t_pFq([-σ_b_avg], [2-Σ], -ρ_Δ*w*exp(-T))
    +
    +@time G00 = exp(ρ_b*w)*(f * t_pFq([1-σ_b_avg], [2-Σ], -ρ_Δ*w) +
    +                  g * t_pFq([1+σ_u], [Σ], -ρ_Δ*w) )
    +
    +@time G11 = σ_u^(-1) * exp(ρ_b*w) * (-σ_u*f*t_pFq([-σ_b_avg], [2-Σ], -ρ_Δ*w) +
    +                                σ_b_avg*g*t_pFq([σ_u], [Σ], -ρ_Δ*w))
    +
    +probs = (G00+G11).coeffs
    +
    +# check that the probability distribution is more or less normalised to 1
    +# need higher numerical precision if not
    +isapprox(sum(probs), 1.0, rtol=1e-2)
    0.009289 seconds (41.03 k allocations: 1.603 MiB)
    +0.009126 seconds (41.03 k allocations: 1.603 MiB)
    +0.067889 seconds (85.06 k allocations: 3.613 MiB)
    +0.066194 seconds (85.07 k allocations: 3.618 MiB)
    +true

    Finally, we can plot the distribution and compare it to the FSP result:

    plot(0:n, probs, xlabel="n", ylabel="P(n, t=4)", label="LMA", fmt="svg")
    +# plot the FSP probability of protein number by marginalising over the gene states
    +plot!(0:n, sum(sol_FSP[:, 41], dims=1)'[1:n+1], label="FSP")

    LMA FSP feedback loop distribution

    References

    [1]: Z. Cao and R. Grima, "Linear mapping approximation of gene regulatory networks with stochastic dynamics", Nature Communications 9, 3305 (2018). https://doi.org/10.1038/s41467-018-05822-0

    diff --git a/dev/tutorials/P53_system_example/index.html b/dev/tutorials/P53_system_example/index.html index d43fa89..82b9647 100644 --- a/dev/tutorials/P53_system_example/index.html +++ b/dev/tutorials/P53_system_example/index.html @@ -1,166 +1,166 @@ -P53 System Example · MomentClosure.jl

    P53 System Example

    In this example tutorial, we consider the oscillatory p53-Mdm2 system which has been studied by Lakatos et al. (2015) using central moment expansion up to 5th order with zero, normal, log-normal and gamma closures. We attempt to reproduce a number of results published in their paper.

    In contrast to the Brusselator we considered before, the p53-Mdm2 system contains non-polynomial propensities and hence is a good showcase for generating central moment equations using different values of $q$ and comparing their accuracy. Note that this was not considered by Lakatos et al. who set $q = m+1$ throughout their study. We remind the reader that $m$ denotes the moment expansion order and $q$ is the order of Taylor expansion of the propensity functions: the moment equations are generated up to $m^{\text{th}}$ order and may include central moments up $q^{\text{th}}$ order so that all moments of orders $m+1, \dotsc, q$ must be approximated using some moment closure method (see the Moment Expansion theory section for more details).

    The p53-Mdm2 reaction network is described by the stoichiometric matrix

    \[S = \begin{bmatrix} - 1 & -1 & -1 & 0 & 0 & 0\\ - 0 & 0 & 0 & 1 & -1 & 0 \\ - 0 & 0 & 0 & 0 & 1 & -1 - \end{bmatrix}\]

    and six reaction propensities

    \[\begin{align*} -a_1 &= k_1, \\ -a_2 &= k_2 x_, \\ -a_3 &= k_3 \frac{x y}{x + k_7}, \\ -a_4 &= k_4 x, \\ -a_5 &= k_5 y₀, \\ -a_6 &= k_6 y, -\end{align*}\]

    where the variables are

    • number of p53 molecules $x$
    • number of precursor of Mdm2 molecules $y_0$
    • number of Mdm2 molecules $y$

    with parameters

    • p53 production rate $k_1$
    • Mdm2-independent p53 degradation rate $k_2$
    • saturating p53 degradation rate $k_3$
    • p53-dependent Mdm2 production rate $k_4$
    • Mdm2 maturation rate $k_5$
    • Mdm2 degradation rate $k_6$
    • p53 threshold for degradation by Mdm2 $k_7$

    We begin by loading all the packages we will need

    using Catalyst, MomentClosure, OrdinaryDiffEq, JumpProcesses,
    -      DiffEqBase.EnsembleAnalysis, Plots, Plots.PlotMeasures

    and then build the model using Catalyst and set its parameters as follows:

    # → for mass-actions rate
    -# ⇒ for non mass-actions rate
    -rn = @reaction_network begin
    -    @parameters k₁ k₂ k₃ k₄ k₅ k₆ k₇
    -    (k₁), 0 → x
    -    (k₂), x → 0
    -    (k₃*x*y/(x+k₇)), x ⇒ 0
    -    (k₄*x), 0 ⇒ y₀
    -    (k₅), y₀ → y
    -    (k₆), y → 0
    -end
    -
    -# parameters [k₁, k₂, k₃, k₄, k₅, k₆, k₇]
    -p = [90, 0.002, 1.7, 1.1, 0.93, 0.96, 0.01]
    -
    -# initial molecule numbers [x, y₀, y]
    -u₀ = [70, 30, 60]

    Let's first simulate the reaction network using SSA in order to have a reference point of the real system dynamics. We choose a relatively long simulation time span in order to clearly see how the molecule numbers converge to their steady-state values and opt for $5 \times 10^4$ SSA realisations:

    # time interval to solve one on
    -tspan = (0., 200.)
    -
    -# constructing the discrete jump problem using DifferentialEquations
    -jsys = convert(JumpSystem, rn, combinatoric_ratelaws=false)
    -dprob = DiscreteProblem(jsys, u₀, tspan, p)
    -
    -jprob = JumpProblem(jsys, dprob, Direct(), save_positions=(false, false))
    -ensembleprob  = EnsembleProblem(jprob)
    -
    -# @time is only a rough estimate and not a proper benchmark
    -@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.2, trajectories=50000)
    1332.443829 seconds (2.90 G allocations: 69.838 GiB, 42.81% gc time)

    Single SSA trajectories show sustained oscillations in molecule numbers:

    plot(sol_SSA[666], labels=["p53" "pre-Mdm2" "Mdm2"], lw=2, tspan=(0., 100.),
    -     linecolor=[1 3 2], xlabel="Time [h]", ylabel="Number of molecules", size=(700, 400))

    P53-Mdm2 SSA one trajectory

    The mean population dynamics show damped oscillations as the single trajectories get dephased over time and eventually reach steady-state values:

    means_SSA, vars_SSA = timeseries_steps_meanvar(sol_SSA)
    -plot(means_SSA, labels=["p53" "pre-Mdm2" "Mdm2"], lw=2, linecolor=[1 3 2],
    -     xlabel="Time [h]", ylabel="Number of molecules", size=(700, 400))

    P53-Mdm2 SSA mean trajectories

    Note that many more SSA runs are needed to completely denoise the mean trajectories (especially at later times).

    Finally, we can look at the marginal distributions noting a high level of asymmetry at the chosen time point $t=25$:

    data = componentwise_vectors_timepoint(sol_SSA, 25.0)
    -h1 = histogram(data[1], normalize=true, xlabel="x", ylabel="P(x)")
    -h2 = histogram(data[2], normalize=true, xlabel="y₀", ylabel="P(y₀)")
    -h3 = histogram(data[3], normalize=true, xlabel="y", ylabel="P(y)")
    -using Plots.PlotMeasures
    -plot(h1, h2, h3, legend=false, layout=(1,3), size = (1050, 250),
    -     left_margin = 5PlotMeasures.mm, bottom_margin = 7PlotMeasures.mm, guidefontsize=10)

    P53-Mdm2 distribution

    Given the long runtime of the SSA above, it makes sense to turn to approximation methods such as moment closure which is usually much faster (suitable if only information about moments is needed). We start with the simplest second order, $m =2$, moment expansion and consider normal, log-normal and gamma closures. Our interest here is to see how the accuracy of each closure changes when the Taylor expansion order $q$ is increased. Note that zero closure is equivalent to normal closure when $q=3$ (as third order central moments and cumulants are equivalent) and does not change when $q$ is increased as all the higher order moments will be simply set to zero.

    We can generate the corresponding plots of the mean p53 molecule number, $x$, as follows:

    closures = ["normal", "log-normal", "gamma"]
    -
    -# initialise separate plot for each closure
    -plts = [plot() for i in 1:length(closures)]
    -
    -for q in 3:6
    -    eqs = generate_central_moment_eqs(rn, 2, q, combinatoric_ratelaws=false)
    -    for (closure, plt) in zip(closures, plts)
    -        closed_eqs = moment_closure(eqs, closure)
    -
    -        u₀map = deterministic_IC(u₀, closed_eqs)
    -        oprob = ODEProblem(closed_eqs, u₀map, tspan, p)
    -
    -        sol = solve(oprob, Tsit5(), saveat=0.1)
    -        plt = plot!(plt, sol, idxs=[1], lw=3, label  = "q = "*string(q))
    -    end
    -end
    -
    -for plt in plts
    -    plt = plot!(plt, xlabel = "Time [h]", ylabel = "Mean number of p53 molecules")
    -    plt = plot!(plt, means_SSA.t, means_SSA[1,:], lw=2, linestyle=:dash, label = "SSA", color="gray")
    -end

    Normal closure:

    plot(plts[1], size=(750, 450), leftmargin=2PlotMeasures.mm)

    P53-Mdm2 normal means 2nd order expansion

    Log-normal closure:

    plot(plts[2], size=(750, 450), leftmargin=2PlotMeasures.mm)

    P53-Mdm2 log-normal means 2nd order expansion

    Zoomed-in log-normal closure (to better see the initial dampening in trajectories):

    plot(plts[2], xlims=(0., 50.), lw=3)

    P53-Mdm2 log-normal means 2nd order expansion

    Gamma closure:

    plot(plts[3], size=(750, 450), leftmargin=2PlotMeasures.mm)

    P53-Mdm2 gamma means 2nd order expansion

    When using normal closure, including central moments all the way up to 6th order ($q=6$) is needed in order to obtain qualitatively correct system behaviour. As the true distribution (as plotted above) is highly asymmetric, one may expect that performing normal closure, i.e., assuming that the system has a (symmetric) Gaussian distribution, is not the most optimal choice. For log-normal and gamma closures, quite accurate predictions are obtained with $q=4$ whereas $q=6$ tends to overestimate the dampening initially but better captures the steady-state behaviour. Note that for odd values of $q$ log-normal and gamma closures introduced numerical instabilities and the moments could not be evaluated for the entire time course.

    We can also plot the variance predictions:

    # rerunning the same calculations as they are reasonably fast
    -plt = plot()
    -for q in [4,6]
    -    eqs = generate_central_moment_eqs(rn, 2, q, combinatoric_ratelaws=false)
    -    for closure in closures
    -        closed_eqs = moment_closure(eqs, closure)
    -
    -        u₀map = deterministic_IC(u₀, closed_eqs)
    -        oprob = ODEProblem(closed_eqs, u₀map, tspan, p)
    -        sol = solve(oprob, Tsit5(), saveat=0.1)
    -
    -        # index of M₂₀₀ can be checked with `u₀map` or `closed_eqs.odes.states`
    -        plt = plot!(plt, sol, idxs=[4], lw=3, label  = closure*" q = "*string(q))
    -    end
    -end
    -
    -plt = plot!(plt, xlabel = "Time [h]", ylabel = "Variance of p53 molecule number", legend=:topleft)
    -plt = plot!(plt, means_SSA.t, vars_SSA[1,:], lw=2, linestyle=:dash, label = "SSA", color="gray")
    -plot(plt, size=(750, 450))

    P53-Mdm2 variances 2nd order expansion

    Log-normal closure with $q=6$ clearly gives the best estimate of the variance. Therefore, including increasingly higher-order moment information in second-order moment expansion tends to leads to an overall more accurate statistical description of the P53-Mdm2 system.

    We can extend the analysis further by considering higher order moment expansions (increasing $m$). Let's look at third-order expansion with $q$ values 4 and 6 (odd $q$ leads to heavy numerical instabilities as before):

    closures = ["zero", "normal", "log-normal", "gamma"]
    -
    -plt_means = [plot() for i in 1:2]
    -plt_vars  = [plot() for i in 1:2]
    -
    -q_vals = [4, 6]
    -
    -for (q, plt_m, plt_v) in zip(q_vals, plt_means, plt_vars)
    -
    -    eqs = generate_central_moment_eqs(rn, 3, q, combinatoric_ratelaws=false)
    -    for closure in closures
    -
    -        closed_eqs = moment_closure(eqs, closure)
    -
    -        u₀map = deterministic_IC(u₀, closed_eqs)
    -        oprob = ODEProblem(closed_eqs, u₀map, tspan, p)
    -
    -        sol = solve(oprob, Tsit5(), saveat=0.1)
    -        plt_m = plot!(plt_m, sol, idxs=[1], label = closure)    
    -        plt_v = plot!(plt_v, sol, idxs=[4], label = closure)
    -
    -    end
    -
    -    plt_m = plot!(plt_m, means_SSA.t, means_SSA[1,:], title="m = 3, q = "*string(q),
    -                  linestyle=:dash, label = "SSA", color="gray", legend=false)
    -
    -    plt_v = plot!(plt_v, vars_SSA.t, vars_SSA[1,:], linestyle=:dash, label = "SSA", color="gray", legend=false)
    -
    -end
    -
    -plt_means[1] = plot(plt_means[1], ylabel = "Mean p53 molecule number")
    -plt_vars[1] = plot(plt_vars[1], ylabel = "Variance of p53 molecule number", legend=:topleft)
    -plot(plt_means..., plt_vars..., size=(1250, 750), lw=1.5, xlabel="Time [h]",
    -     guidefontsize=10, titlefontsize=12, legendfontsize=8, leftmargin=4mm, bottommargin=2mm)

    P53-Mdm2 3rd order expansion

    The results are rather interesting: the mean trajectories initially show the characteristic dampened oscillations, which, however, fail to converge to a steady-state value and instead start growing in amplitude as the time increases—this behaviour is also more pronounced for higher $q$. Surprisingly, log-normal and gamma closures still provide fairly accurate variance estimates. Note that zero closure ODEs fail to be evaluated for the entire time course at all, displaying strongly oscillatory mean trajectories and even exponentially growing variances. Therefore, third order moment expansion and all of the applied closure methods fail to give physically meaningful results.

    This outcome seems concerning as Lakatos et al. (2015) state that the same closures reached steady-state at extended simulation time (using identical parameter set). In order to investigate this discrepancy further, we turn to Python MEANS package, the implementation of which is fully based on the technical details presented in Lakatos et al. (2015). Note that the package has not been maintained for years, only works on Python 2 and setting up its dependencies may be fiddly. Nevertheless, having done that, we can generate and solve the moment equations up to third order running the following code in a separate Python 2 notebook:

    import means
    -import means.examples
    -import numpy as np
    -import matplotlib.pyplot as plt
    -
    -sys = means.examples.MODEL_P53
    -
    -ps = [90, 0.002, 1.7, 1.1, 0.93, 0.96, 0.01]
    -ic_values = [70, 30, 60]
    -
    -tspan = np.arange(0, 200, 0.1)
    -
    -plt.figure(figsize=(10,6))
    -
    -for closure in ["normal", "log-normal", "gamma"]:
    -    odes = means.mea_approximation(sys, 3, closure=closure, multivariate=True)
    -    simulation = means.Simulation(odes)
    -    trajectories = simulation.simulate_system(ps, ic_values, tspan)
    -    trajectories[0].plot(label=closure)
    -
    -plt.margins(x=0)
    -plt.xlabel('Time [h]', fontsize=12)
    -plt.ylabel('Mean p53 molecule number', fontsize=12)
    -plt.tick_params(axis='both', which='major', labelsize=10)
    -plt.legend(fontsize=12)
    -plt.show()

    P53-Mdm2 3rd order expansion MEANS

    We observe that the mean trajectories fail to converge after all, hinting that some of the results published in Lakatos et al. (2015) may benefit from a more critical analysis. Note that MEANS does not allow arbitrary $q$ values and automatically sets $q = m+1$, hence third-order moment expansion using MEANS is equivalent to our $m=3, q=4$ case.

    We stress that the obtained mean trajectories using the two packages are not identical due to different implementations of the closure methods (different solvers do not have a significant effect in this case). Lakatos et al. (2015) (and hence MEANS) formulate the normal, log-normal and gamma closure functions exclusively in terms of first and second order moments—higher order moments, whose corresponding ODEs are being solved for simultaneously, are not included in the construction of closure functions. One could say that such formulation makes a stronger assumption about the underlying distribution and does not utilise all the information available about the system—our implementation takes that into account. For example, in case of $m=3, q=4$ moment expansion, we approximate the fourth order central moments in terms of third and lower order moments, whereas MEANS would approximate it using only first and second order moments. Curiously, MEANS formulation appears to be more numerically stable (shows weaker oscillations) at longer times in this particular case, as can be seen from the plots above. Nevertheless, as both approaches failed to produce physically meaningful results, we do not investigate the numerical differences further—one would still generally expect that the inclusion of the computed higher-order moment values will improve the numerical stability of the ODEs and the accuracy of moment estimates.

    Finally, we can check whether better estimates can be obtained using even higher, fifth, order expansion with $q=6$:

    plt = plot()
    -closures = ["zero", "normal", "log-normal", "gamma"]
    -
    -eqs = generate_central_moment_eqs(rn, 5, 6, combinatoric_ratelaws=false)
    -# faster to store than recompute in case we want to try different solvers/params
    -oprobs = Dict()
    -
    -for closure in closures
    -    closed_eqs = moment_closure(eqs, closure)
    -
    -    u₀map = deterministic_IC(u₀, closed_eqs)
    -    oprobs[closure] = ODEProblem(closed_eqs, u₀map, tspan, p)
    -    sol = solve(oprobs[closure], Tsit5(), saveat=0.1)
    -
    -    plt = plot!(plt, sol, idxs=[1], label = closure)    
    -end
    -
    -plt = plot!(plt, xlabel = "Time [h]", ylabel = "Mean p53 molecule number")
    -plt = plot!(plt, means_SSA.t, means_SSA[1, :], linestyle=:dash, label = "SSA", color="gray")
    -plot(plt, size=(750, 450), lw=2)

    P53-Mdm2 5th order expansion

    All closures are highly numerically unstable and fail to provide physically meaningful results. Performing similar fifth order moment expansion using the MEANS package we obtain (full code can be found in the example Jupyter notebook):

    P53-Mdm2 5th order expansion MEANS

    Note that normal closure is not included in the plot as it failed to converge using MEANS while log-normal and gamma closures seem to be much more stable in comparison to MomentClosure results (albeit still unphysical). In contrast, normal closure is the only one which succeeded in being evaluated for the entire time course using MomentClosure (full time not shown in the plot) which again is a result of the implementational differences between the two packages.

    +P53 System Example · MomentClosure.jl

    P53 System Example

    In this example tutorial, we consider the oscillatory p53-Mdm2 system which has been studied by Lakatos et al. (2015) using central moment expansion up to 5th order with zero, normal, log-normal and gamma closures. We attempt to reproduce a number of results published in their paper.

    In contrast to the Brusselator we considered before, the p53-Mdm2 system contains non-polynomial propensities and hence is a good showcase for generating central moment equations using different values of $q$ and comparing their accuracy. Note that this was not considered by Lakatos et al. who set $q = m+1$ throughout their study. We remind the reader that $m$ denotes the moment expansion order and $q$ is the order of Taylor expansion of the propensity functions: the moment equations are generated up to $m^{\text{th}}$ order and may include central moments up $q^{\text{th}}$ order so that all moments of orders $m+1, \dotsc, q$ must be approximated using some moment closure method (see the Moment Expansion theory section for more details).

    The p53-Mdm2 reaction network is described by the stoichiometric matrix

    \[S = \begin{bmatrix} + 1 & -1 & -1 & 0 & 0 & 0\\ + 0 & 0 & 0 & 1 & -1 & 0 \\ + 0 & 0 & 0 & 0 & 1 & -1 + \end{bmatrix}\]

    and six reaction propensities

    \[\begin{align*} +a_1 &= k_1, \\ +a_2 &= k_2 x_, \\ +a_3 &= k_3 \frac{x y}{x + k_7}, \\ +a_4 &= k_4 x, \\ +a_5 &= k_5 y₀, \\ +a_6 &= k_6 y, +\end{align*}\]

    where the variables are

    • number of p53 molecules $x$
    • number of precursor of Mdm2 molecules $y_0$
    • number of Mdm2 molecules $y$

    with parameters

    • p53 production rate $k_1$
    • Mdm2-independent p53 degradation rate $k_2$
    • saturating p53 degradation rate $k_3$
    • p53-dependent Mdm2 production rate $k_4$
    • Mdm2 maturation rate $k_5$
    • Mdm2 degradation rate $k_6$
    • p53 threshold for degradation by Mdm2 $k_7$

    We begin by loading all the packages we will need

    using Catalyst, MomentClosure, OrdinaryDiffEq, JumpProcesses,
    +      DiffEqBase.EnsembleAnalysis, Plots, Plots.PlotMeasures

    and then build the model using Catalyst and set its parameters as follows:

    # → for mass-actions rate
    +# ⇒ for non mass-actions rate
    +rn = @reaction_network begin
    +    @parameters k₁ k₂ k₃ k₄ k₅ k₆ k₇
    +    (k₁), 0 → x
    +    (k₂), x → 0
    +    (k₃*x*y/(x+k₇)), x ⇒ 0
    +    (k₄*x), 0 ⇒ y₀
    +    (k₅), y₀ → y
    +    (k₆), y → 0
    +end
    +
    +# parameters [k₁, k₂, k₃, k₄, k₅, k₆, k₇]
    +p = [90, 0.002, 1.7, 1.1, 0.93, 0.96, 0.01]
    +
    +# initial molecule numbers [x, y₀, y]
    +u₀ = [70, 30, 60]

    Let's first simulate the reaction network using SSA in order to have a reference point of the real system dynamics. We choose a relatively long simulation time span in order to clearly see how the molecule numbers converge to their steady-state values and opt for $5 \times 10^4$ SSA realisations:

    # time interval to solve one on
    +tspan = (0., 200.)
    +
    +# constructing the discrete jump problem using DifferentialEquations
    +jsys = convert(JumpSystem, rn, combinatoric_ratelaws=false)
    +dprob = DiscreteProblem(jsys, u₀, tspan, p)
    +
    +jprob = JumpProblem(jsys, dprob, Direct(), save_positions=(false, false))
    +ensembleprob  = EnsembleProblem(jprob)
    +
    +# @time is only a rough estimate and not a proper benchmark
    +@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.2, trajectories=50000)
    1332.443829 seconds (2.90 G allocations: 69.838 GiB, 42.81% gc time)

    Single SSA trajectories show sustained oscillations in molecule numbers:

    plot(sol_SSA[666], labels=["p53" "pre-Mdm2" "Mdm2"], lw=2, tspan=(0., 100.),
    +     linecolor=[1 3 2], xlabel="Time [h]", ylabel="Number of molecules", size=(700, 400))

    P53-Mdm2 SSA one trajectory

    The mean population dynamics show damped oscillations as the single trajectories get dephased over time and eventually reach steady-state values:

    means_SSA, vars_SSA = timeseries_steps_meanvar(sol_SSA)
    +plot(means_SSA, labels=["p53" "pre-Mdm2" "Mdm2"], lw=2, linecolor=[1 3 2],
    +     xlabel="Time [h]", ylabel="Number of molecules", size=(700, 400))

    P53-Mdm2 SSA mean trajectories

    Note that many more SSA runs are needed to completely denoise the mean trajectories (especially at later times).

    Finally, we can look at the marginal distributions noting a high level of asymmetry at the chosen time point $t=25$:

    data = componentwise_vectors_timepoint(sol_SSA, 25.0)
    +h1 = histogram(data[1], normalize=true, xlabel="x", ylabel="P(x)")
    +h2 = histogram(data[2], normalize=true, xlabel="y₀", ylabel="P(y₀)")
    +h3 = histogram(data[3], normalize=true, xlabel="y", ylabel="P(y)")
    +using Plots.PlotMeasures
    +plot(h1, h2, h3, legend=false, layout=(1,3), size = (1050, 250),
    +     left_margin = 5PlotMeasures.mm, bottom_margin = 7PlotMeasures.mm, guidefontsize=10)

    P53-Mdm2 distribution

    Given the long runtime of the SSA above, it makes sense to turn to approximation methods such as moment closure which is usually much faster (suitable if only information about moments is needed). We start with the simplest second order, $m =2$, moment expansion and consider normal, log-normal and gamma closures. Our interest here is to see how the accuracy of each closure changes when the Taylor expansion order $q$ is increased. Note that zero closure is equivalent to normal closure when $q=3$ (as third order central moments and cumulants are equivalent) and does not change when $q$ is increased as all the higher order moments will be simply set to zero.

    We can generate the corresponding plots of the mean p53 molecule number, $x$, as follows:

    closures = ["normal", "log-normal", "gamma"]
    +
    +# initialise separate plot for each closure
    +plts = [plot() for i in 1:length(closures)]
    +
    +for q in 3:6
    +    eqs = generate_central_moment_eqs(rn, 2, q, combinatoric_ratelaws=false)
    +    for (closure, plt) in zip(closures, plts)
    +        closed_eqs = moment_closure(eqs, closure)
    +
    +        u₀map = deterministic_IC(u₀, closed_eqs)
    +        oprob = ODEProblem(closed_eqs, u₀map, tspan, p)
    +
    +        sol = solve(oprob, Tsit5(), saveat=0.1)
    +        plt = plot!(plt, sol, idxs=[1], lw=3, label  = "q = "*string(q))
    +    end
    +end
    +
    +for plt in plts
    +    plt = plot!(plt, xlabel = "Time [h]", ylabel = "Mean number of p53 molecules")
    +    plt = plot!(plt, means_SSA.t, means_SSA[1,:], lw=2, linestyle=:dash, label = "SSA", color="gray")
    +end

    Normal closure:

    plot(plts[1], size=(750, 450), leftmargin=2PlotMeasures.mm)

    P53-Mdm2 normal means 2nd order expansion

    Log-normal closure:

    plot(plts[2], size=(750, 450), leftmargin=2PlotMeasures.mm)

    P53-Mdm2 log-normal means 2nd order expansion

    Zoomed-in log-normal closure (to better see the initial dampening in trajectories):

    plot(plts[2], xlims=(0., 50.), lw=3)

    P53-Mdm2 log-normal means 2nd order expansion

    Gamma closure:

    plot(plts[3], size=(750, 450), leftmargin=2PlotMeasures.mm)

    P53-Mdm2 gamma means 2nd order expansion

    When using normal closure, including central moments all the way up to 6th order ($q=6$) is needed in order to obtain qualitatively correct system behaviour. As the true distribution (as plotted above) is highly asymmetric, one may expect that performing normal closure, i.e., assuming that the system has a (symmetric) Gaussian distribution, is not the most optimal choice. For log-normal and gamma closures, quite accurate predictions are obtained with $q=4$ whereas $q=6$ tends to overestimate the dampening initially but better captures the steady-state behaviour. Note that for odd values of $q$ log-normal and gamma closures introduced numerical instabilities and the moments could not be evaluated for the entire time course.

    We can also plot the variance predictions:

    # rerunning the same calculations as they are reasonably fast
    +plt = plot()
    +for q in [4,6]
    +    eqs = generate_central_moment_eqs(rn, 2, q, combinatoric_ratelaws=false)
    +    for closure in closures
    +        closed_eqs = moment_closure(eqs, closure)
    +
    +        u₀map = deterministic_IC(u₀, closed_eqs)
    +        oprob = ODEProblem(closed_eqs, u₀map, tspan, p)
    +        sol = solve(oprob, Tsit5(), saveat=0.1)
    +
    +        # index of M₂₀₀ can be checked with `u₀map` or `closed_eqs.odes.states`
    +        plt = plot!(plt, sol, idxs=[4], lw=3, label  = closure*" q = "*string(q))
    +    end
    +end
    +
    +plt = plot!(plt, xlabel = "Time [h]", ylabel = "Variance of p53 molecule number", legend=:topleft)
    +plt = plot!(plt, means_SSA.t, vars_SSA[1,:], lw=2, linestyle=:dash, label = "SSA", color="gray")
    +plot(plt, size=(750, 450))

    P53-Mdm2 variances 2nd order expansion

    Log-normal closure with $q=6$ clearly gives the best estimate of the variance. Therefore, including increasingly higher-order moment information in second-order moment expansion tends to leads to an overall more accurate statistical description of the P53-Mdm2 system.

    We can extend the analysis further by considering higher order moment expansions (increasing $m$). Let's look at third-order expansion with $q$ values 4 and 6 (odd $q$ leads to heavy numerical instabilities as before):

    closures = ["zero", "normal", "log-normal", "gamma"]
    +
    +plt_means = [plot() for i in 1:2]
    +plt_vars  = [plot() for i in 1:2]
    +
    +q_vals = [4, 6]
    +
    +for (q, plt_m, plt_v) in zip(q_vals, plt_means, plt_vars)
    +
    +    eqs = generate_central_moment_eqs(rn, 3, q, combinatoric_ratelaws=false)
    +    for closure in closures
    +
    +        closed_eqs = moment_closure(eqs, closure)
    +
    +        u₀map = deterministic_IC(u₀, closed_eqs)
    +        oprob = ODEProblem(closed_eqs, u₀map, tspan, p)
    +
    +        sol = solve(oprob, Tsit5(), saveat=0.1)
    +        plt_m = plot!(plt_m, sol, idxs=[1], label = closure)    
    +        plt_v = plot!(plt_v, sol, idxs=[4], label = closure)
    +
    +    end
    +
    +    plt_m = plot!(plt_m, means_SSA.t, means_SSA[1,:], title="m = 3, q = "*string(q),
    +                  linestyle=:dash, label = "SSA", color="gray", legend=false)
    +
    +    plt_v = plot!(plt_v, vars_SSA.t, vars_SSA[1,:], linestyle=:dash, label = "SSA", color="gray", legend=false)
    +
    +end
    +
    +plt_means[1] = plot(plt_means[1], ylabel = "Mean p53 molecule number")
    +plt_vars[1] = plot(plt_vars[1], ylabel = "Variance of p53 molecule number", legend=:topleft)
    +plot(plt_means..., plt_vars..., size=(1250, 750), lw=1.5, xlabel="Time [h]",
    +     guidefontsize=10, titlefontsize=12, legendfontsize=8, leftmargin=4mm, bottommargin=2mm)

    P53-Mdm2 3rd order expansion

    The results are rather interesting: the mean trajectories initially show the characteristic dampened oscillations, which, however, fail to converge to a steady-state value and instead start growing in amplitude as the time increases—this behaviour is also more pronounced for higher $q$. Surprisingly, log-normal and gamma closures still provide fairly accurate variance estimates. Note that zero closure ODEs fail to be evaluated for the entire time course at all, displaying strongly oscillatory mean trajectories and even exponentially growing variances. Therefore, third order moment expansion and all of the applied closure methods fail to give physically meaningful results.

    This outcome seems concerning as Lakatos et al. (2015) state that the same closures reached steady-state at extended simulation time (using identical parameter set). In order to investigate this discrepancy further, we turn to Python MEANS package, the implementation of which is fully based on the technical details presented in Lakatos et al. (2015). Note that the package has not been maintained for years, only works on Python 2 and setting up its dependencies may be fiddly. Nevertheless, having done that, we can generate and solve the moment equations up to third order running the following code in a separate Python 2 notebook:

    import means
    +import means.examples
    +import numpy as np
    +import matplotlib.pyplot as plt
    +
    +sys = means.examples.MODEL_P53
    +
    +ps = [90, 0.002, 1.7, 1.1, 0.93, 0.96, 0.01]
    +ic_values = [70, 30, 60]
    +
    +tspan = np.arange(0, 200, 0.1)
    +
    +plt.figure(figsize=(10,6))
    +
    +for closure in ["normal", "log-normal", "gamma"]:
    +    odes = means.mea_approximation(sys, 3, closure=closure, multivariate=True)
    +    simulation = means.Simulation(odes)
    +    trajectories = simulation.simulate_system(ps, ic_values, tspan)
    +    trajectories[0].plot(label=closure)
    +
    +plt.margins(x=0)
    +plt.xlabel('Time [h]', fontsize=12)
    +plt.ylabel('Mean p53 molecule number', fontsize=12)
    +plt.tick_params(axis='both', which='major', labelsize=10)
    +plt.legend(fontsize=12)
    +plt.show()

    P53-Mdm2 3rd order expansion MEANS

    We observe that the mean trajectories fail to converge after all, hinting that some of the results published in Lakatos et al. (2015) may benefit from a more critical analysis. Note that MEANS does not allow arbitrary $q$ values and automatically sets $q = m+1$, hence third-order moment expansion using MEANS is equivalent to our $m=3, q=4$ case.

    We stress that the obtained mean trajectories using the two packages are not identical due to different implementations of the closure methods (different solvers do not have a significant effect in this case). Lakatos et al. (2015) (and hence MEANS) formulate the normal, log-normal and gamma closure functions exclusively in terms of first and second order moments—higher order moments, whose corresponding ODEs are being solved for simultaneously, are not included in the construction of closure functions. One could say that such formulation makes a stronger assumption about the underlying distribution and does not utilise all the information available about the system—our implementation takes that into account. For example, in case of $m=3, q=4$ moment expansion, we approximate the fourth order central moments in terms of third and lower order moments, whereas MEANS would approximate it using only first and second order moments. Curiously, MEANS formulation appears to be more numerically stable (shows weaker oscillations) at longer times in this particular case, as can be seen from the plots above. Nevertheless, as both approaches failed to produce physically meaningful results, we do not investigate the numerical differences further—one would still generally expect that the inclusion of the computed higher-order moment values will improve the numerical stability of the ODEs and the accuracy of moment estimates.

    Finally, we can check whether better estimates can be obtained using even higher, fifth, order expansion with $q=6$:

    plt = plot()
    +closures = ["zero", "normal", "log-normal", "gamma"]
    +
    +eqs = generate_central_moment_eqs(rn, 5, 6, combinatoric_ratelaws=false)
    +# faster to store than recompute in case we want to try different solvers/params
    +oprobs = Dict()
    +
    +for closure in closures
    +    closed_eqs = moment_closure(eqs, closure)
    +
    +    u₀map = deterministic_IC(u₀, closed_eqs)
    +    oprobs[closure] = ODEProblem(closed_eqs, u₀map, tspan, p)
    +    sol = solve(oprobs[closure], Tsit5(), saveat=0.1)
    +
    +    plt = plot!(plt, sol, idxs=[1], label = closure)    
    +end
    +
    +plt = plot!(plt, xlabel = "Time [h]", ylabel = "Mean p53 molecule number")
    +plt = plot!(plt, means_SSA.t, means_SSA[1, :], linestyle=:dash, label = "SSA", color="gray")
    +plot(plt, size=(750, 450), lw=2)

    P53-Mdm2 5th order expansion

    All closures are highly numerically unstable and fail to provide physically meaningful results. Performing similar fifth order moment expansion using the MEANS package we obtain (full code can be found in the example Jupyter notebook):

    P53-Mdm2 5th order expansion MEANS

    Note that normal closure is not included in the plot as it failed to converge using MEANS while log-normal and gamma closures seem to be much more stable in comparison to MomentClosure results (albeit still unphysical). In contrast, normal closure is the only one which succeeded in being evaluated for the entire time course using MomentClosure (full time not shown in the plot) which again is a result of the implementational differences between the two packages.

    diff --git a/dev/tutorials/SIR_example/index.html b/dev/tutorials/SIR_example/index.html index 69bdf90..57ade8d 100644 --- a/dev/tutorials/SIR_example/index.html +++ b/dev/tutorials/SIR_example/index.html @@ -1,2 +1,2 @@ -SIR Model Example · MomentClosure.jl +SIR Model Example · MomentClosure.jl diff --git a/dev/tutorials/common_issues/index.html b/dev/tutorials/common_issues/index.html index 729ad31..c5966e6 100644 --- a/dev/tutorials/common_issues/index.html +++ b/dev/tutorials/common_issues/index.html @@ -1,63 +1,63 @@ -Common Issues · MomentClosure.jl

    Common Issues

    Moment closure approximations are based on ad hoc assumptions and no rigorous and general predictions can be made on whether the results will be accurate or even physically meaningful [1-2]. Moreover, the truncated moment equations are prone to numerical instabilities and it may not be possible to solve them for the entire time course [3]. In this tutorial, we walk through a number of such issues encountered in the analysis of the Brusselator model introduced in the previous tutorial.

    We first redefine the system and its parameters for completeness:

    using MomentClosure, Catalyst, OrdinaryDiffEq, Plots
    -
    -rn = @reaction_network begin
    -  @parameters c₁ c₂ c₃ c₄ Ω
    -  (c₁/Ω^2), 2X + Y → 3X
    -  (c₂), X → Y
    -  (c₃*Ω, c₄), 0 ↔ X
    -end
    -
    -p = [0.9, 2, 1, 1, 100]
    -u₀ = [1, 1]
    -tspan = (0., 100.)
    -
    -raw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=false)

    As we have seen earlier, second-order moment expansion using normal closure approximates the true system dynamics sufficiently accurately but it's interesting to see how other closures compare. Let's try applying zero closure:

    closed_raw_eqs = moment_closure(raw_eqs, "zero")
    -
    -u₀map = deterministic_IC(u₀, closed_raw_eqs)
    -oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)
    -sol = solve(oprob, Tsit5(), saveat=0.1)
    -
    -plot(sol, idxs=[1,2], lw=2)

    Brusselator issue 1

    The trajectory of $μ₀₁$ becomes negative and so zero closure fails to provide physically meaningful results for this parameter set. Note that is important to correctly choose the ODE solver depending on the stiffness of the system and the accuracy required. We tried a number of recommended DifferentialEquations solvers here but none seemed to improve the results.

    Let's apply log-normal closure next:

    closed_raw_eqs = moment_closure(raw_eqs, "log-normal")
    -
    -u₀map = deterministic_IC(u₀, closed_raw_eqs)
    -oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)
    -sol = solve(oprob, Tsit5(), saveat=0.1)
    -
    -plot(sol, idxs=[1,2], lw=2, legend=:bottomright)

    Brusselator issue 2

    We observe sustained oscillatory behaviour instead of the expected damped oscillations. This result is unphysical: single SSA trajectories (that may display sustained oscillations) get dephased over time and hence the ensemble average should always show damped or overdamped oscillations [1].

    Normal closure is also quite fragile. This can be seen by simply including the combinatorial scaling of the mass-action propensity functions with combinatoric_ratelaw=true which leads to unphysical sustained oscillatory trajectories:

    raw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=true)
    -closed_raw_eqs = moment_closure(raw_eqs, "normal")
    -
    -u₀map = deterministic_IC(u₀, closed_raw_eqs)
    -oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)
    -sol = solve(oprob, Tsit5(), saveat=0.1)
    -
    -plot(sol, idxs=[1,2], lw=2)

    Brusselator issue 3

    Nevertheless, this can be improved upon by increasing the order of moment expansion:

    raw_eqs = generate_raw_moment_eqs(rn, 3, combinatoric_ratelaws=true)
    -closed_raw_eqs = moment_closure(raw_eqs, "normal")
    -
    -u₀map = deterministic_IC(u₀, closed_raw_eqs)
    -oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)
    -sol = solve(oprob, Tsit5(), saveat=0.1)
    -
    -plot(sol, idxs=[1,2], lw=2, legend=:bottomright)

    Brusselator issue 4

    Some dampening in the system is now visible. Increasing the expansion order to 4 finally leads to physically sensible results:

    raw_eqs = generate_raw_moment_eqs(rn, 4, combinatoric_ratelaws=true)
    -closed_raw_eqs = moment_closure(raw_eqs, "normal")
    -
    -u₀map = deterministic_IC(u₀, closed_raw_eqs)
    -oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)
    -sol = solve(oprob, Tsit5(), saveat=0.1)
    -
    -plot(sol, idxs=[1,2], lw=2)

    Brusselator issue 5

    For dessert, we consider unphysical divergent trajectories—a frequent problem with moment equations [3]. A good example is the second-order moment expansion including the combinatorial scaling of propensities with log-normal closure applied:

    raw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=true)
    -closed_raw_eqs = moment_closure(raw_eqs, "log-normal")
    -
    -u₀map = deterministic_IC(u₀, closed_raw_eqs)
    -oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)
    -sol = solve(oprob, Rodas4P(), saveat=0.1)
    -
    -plot(sol, idxs=[1,2], lw=2)

    Brusselator issue 6

    In contrast to normal closure, increasing the expansion order makes the problem worse:

    raw_eqs = generate_raw_moment_eqs(rn, 3, combinatoric_ratelaws=true)
    -closed_raw_eqs = moment_closure(raw_eqs, "log-normal")
    -
    -u₀map = deterministic_IC(u₀, closed_raw_eqs)
    -oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)
    -sol = solve(oprob, Rodas4P(), saveat=0.1)
    -
    -plot(sol, idxs=[1,2], lw=2)
    ┌ Warning: Interrupted. Larger maxiters is needed.
    -└ @ SciMLBase C:\Users\asukys\.julia\packages\SciMLBase\Afx1r\src\integrator_interface.jl:331

    Brusselator issue 7

    Note that the solver throws a warning being unable to evaluate the trajectories for the entire time course (other solvers perform similarly in this case). This usually implies that the moment ODE system is too stiff and cannot be solved: the time derivatives grow unboundedly and the solver timestep is being constantly reduced, requiring an ever-increasing number of the solver iterations (hence the maxiters warning).

    References

    [1]: D. Schnoerr, G. Sanguinetti, and R. Grima, "Comparison of different moment-closure approximations for stochastic chemical kinetics", The Journal of Chemical Physics 143, 185101 (2015). https://doi.org/10.1063/1.4934990

    [2]: D. Schnoerr, G. Sanguinetti, and R. Grima, "Validity conditions for moment closure approximations in stochastic chemical kinetics", The Journal of Chemical Physics 141, 084103 (2014). https://doi.org/10.1063/1.4892838

    [3]: E. Lakatos, A. Ale, P. D. W. Kirk, and M. P. H. Stumpf, "Multivariate moment closure techniques for stochastic kinetic models", The Journal of Chemical Physics 143, 094107 (2015). https://doi.org/10.1063/1.4929837

    +Common Issues · MomentClosure.jl

    Common Issues

    Moment closure approximations are based on ad hoc assumptions and no rigorous and general predictions can be made on whether the results will be accurate or even physically meaningful [1-2]. Moreover, the truncated moment equations are prone to numerical instabilities and it may not be possible to solve them for the entire time course [3]. In this tutorial, we walk through a number of such issues encountered in the analysis of the Brusselator model introduced in the previous tutorial.

    We first redefine the system and its parameters for completeness:

    using MomentClosure, Catalyst, OrdinaryDiffEq, Plots
    +
    +rn = @reaction_network begin
    +  @parameters c₁ c₂ c₃ c₄ Ω
    +  (c₁/Ω^2), 2X + Y → 3X
    +  (c₂), X → Y
    +  (c₃*Ω, c₄), 0 ↔ X
    +end
    +
    +p = [0.9, 2, 1, 1, 100]
    +u₀ = [1, 1]
    +tspan = (0., 100.)
    +
    +raw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=false)

    As we have seen earlier, second-order moment expansion using normal closure approximates the true system dynamics sufficiently accurately but it's interesting to see how other closures compare. Let's try applying zero closure:

    closed_raw_eqs = moment_closure(raw_eqs, "zero")
    +
    +u₀map = deterministic_IC(u₀, closed_raw_eqs)
    +oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)
    +sol = solve(oprob, Tsit5(), saveat=0.1)
    +
    +plot(sol, idxs=[1,2], lw=2)

    Brusselator issue 1

    The trajectory of $μ₀₁$ becomes negative and so zero closure fails to provide physically meaningful results for this parameter set. Note that is important to correctly choose the ODE solver depending on the stiffness of the system and the accuracy required. We tried a number of recommended DifferentialEquations solvers here but none seemed to improve the results.

    Let's apply log-normal closure next:

    closed_raw_eqs = moment_closure(raw_eqs, "log-normal")
    +
    +u₀map = deterministic_IC(u₀, closed_raw_eqs)
    +oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)
    +sol = solve(oprob, Tsit5(), saveat=0.1)
    +
    +plot(sol, idxs=[1,2], lw=2, legend=:bottomright)

    Brusselator issue 2

    We observe sustained oscillatory behaviour instead of the expected damped oscillations. This result is unphysical: single SSA trajectories (that may display sustained oscillations) get dephased over time and hence the ensemble average should always show damped or overdamped oscillations [1].

    Normal closure is also quite fragile. This can be seen by simply including the combinatorial scaling of the mass-action propensity functions with combinatoric_ratelaw=true which leads to unphysical sustained oscillatory trajectories:

    raw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=true)
    +closed_raw_eqs = moment_closure(raw_eqs, "normal")
    +
    +u₀map = deterministic_IC(u₀, closed_raw_eqs)
    +oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)
    +sol = solve(oprob, Tsit5(), saveat=0.1)
    +
    +plot(sol, idxs=[1,2], lw=2)

    Brusselator issue 3

    Nevertheless, this can be improved upon by increasing the order of moment expansion:

    raw_eqs = generate_raw_moment_eqs(rn, 3, combinatoric_ratelaws=true)
    +closed_raw_eqs = moment_closure(raw_eqs, "normal")
    +
    +u₀map = deterministic_IC(u₀, closed_raw_eqs)
    +oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)
    +sol = solve(oprob, Tsit5(), saveat=0.1)
    +
    +plot(sol, idxs=[1,2], lw=2, legend=:bottomright)

    Brusselator issue 4

    Some dampening in the system is now visible. Increasing the expansion order to 4 finally leads to physically sensible results:

    raw_eqs = generate_raw_moment_eqs(rn, 4, combinatoric_ratelaws=true)
    +closed_raw_eqs = moment_closure(raw_eqs, "normal")
    +
    +u₀map = deterministic_IC(u₀, closed_raw_eqs)
    +oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)
    +sol = solve(oprob, Tsit5(), saveat=0.1)
    +
    +plot(sol, idxs=[1,2], lw=2)

    Brusselator issue 5

    For dessert, we consider unphysical divergent trajectories—a frequent problem with moment equations [3]. A good example is the second-order moment expansion including the combinatorial scaling of propensities with log-normal closure applied:

    raw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=true)
    +closed_raw_eqs = moment_closure(raw_eqs, "log-normal")
    +
    +u₀map = deterministic_IC(u₀, closed_raw_eqs)
    +oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)
    +sol = solve(oprob, Rodas4P(), saveat=0.1)
    +
    +plot(sol, idxs=[1,2], lw=2)

    Brusselator issue 6

    In contrast to normal closure, increasing the expansion order makes the problem worse:

    raw_eqs = generate_raw_moment_eqs(rn, 3, combinatoric_ratelaws=true)
    +closed_raw_eqs = moment_closure(raw_eqs, "log-normal")
    +
    +u₀map = deterministic_IC(u₀, closed_raw_eqs)
    +oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)
    +sol = solve(oprob, Rodas4P(), saveat=0.1)
    +
    +plot(sol, idxs=[1,2], lw=2)
    ┌ Warning: Interrupted. Larger maxiters is needed.
    +└ @ SciMLBase C:\Users\asukys\.julia\packages\SciMLBase\Afx1r\src\integrator_interface.jl:331

    Brusselator issue 7

    Note that the solver throws a warning being unable to evaluate the trajectories for the entire time course (other solvers perform similarly in this case). This usually implies that the moment ODE system is too stiff and cannot be solved: the time derivatives grow unboundedly and the solver timestep is being constantly reduced, requiring an ever-increasing number of the solver iterations (hence the maxiters warning).

    References

    [1]: D. Schnoerr, G. Sanguinetti, and R. Grima, "Comparison of different moment-closure approximations for stochastic chemical kinetics", The Journal of Chemical Physics 143, 185101 (2015). https://doi.org/10.1063/1.4934990

    [2]: D. Schnoerr, G. Sanguinetti, and R. Grima, "Validity conditions for moment closure approximations in stochastic chemical kinetics", The Journal of Chemical Physics 141, 084103 (2014). https://doi.org/10.1063/1.4892838

    [3]: E. Lakatos, A. Ale, P. D. W. Kirk, and M. P. H. Stumpf, "Multivariate moment closure techniques for stochastic kinetic models", The Journal of Chemical Physics 143, 094107 (2015). https://doi.org/10.1063/1.4929837

    diff --git a/dev/tutorials/derivative_matching_example/index.html b/dev/tutorials/derivative_matching_example/index.html index 7671992..ab247cb 100644 --- a/dev/tutorials/derivative_matching_example/index.html +++ b/dev/tutorials/derivative_matching_example/index.html @@ -1,108 +1,108 @@ -Derivative Matching Example · MomentClosure.jl

    Derivative Matching Example

    In this example, we aim to reproduce a number of results from the original derivative matching paper by Singh and Hespanha [1]. We consider the bimolecular reaction system given by:

    \[\begin{align*} -X_1 &\stackrel{c_1}{\rightarrow} 2X_1 + X_2, \\ -X_1 + X_2&\stackrel{c_2}{\rightarrow} X_2. -\end{align*}\]

    The reaction network and its parameters can be defined as follows:

    using Catalyst
    -
    -rn = @reaction_network begin
    -    @parameters c₁ c₂
    -    (c₁), x₁ → 2x₁+x₂
    -    (c₂), x₁+x₂ → x₂
    -end
    -
    -# parameter values
    -p = [1.0, 1.0]
    -# initial conditions
    -u0 = [20, 10]
    -# time interval to solve on
    -tspan = (0., 0.5)

    We are interested in extracting the time-evolution of a specific third order cumulant, $κ_{03}$, using second and third order moment expansions with derivative matching, and comparing the obtained estimates to the SSA prediction.

    Let's start with a second order moment expansion and print out the third-order moment closure functions obtained with derivative matching:

    using MomentClosure, Latexify
    -
    -eqs2 = generate_raw_moment_eqs(rn, 2)
    -dm2_eqs = moment_closure(eqs2, "derivative matching")
    -latexify(dm2_eqs, :closure, print_all=true)

    \[\begin{align*} -\mu{_{30}} =& \mu{_{10}}^{-3} \mu{_{20}}^{3} \\ -\mu{_{21}} =& \mu{_{20}} \mu{_{01}}^{-1} \mu{_{10}}^{-2} \mu{_{11}}^{2} \\ -\mu{_{12}} =& \mu{_{02}} \mu{_{01}}^{-2} \mu{_{10}}^{-1} \mu{_{11}}^{2} \\ -\mu{_{03}} =& \mu{_{01}}^{-3} \mu{_{02}}^{3} -\end{align*}\]

    Note that all closure functions are consistent with the ones shown in Table II of [1]. We can then move on to solving the generated system of moment ODEs:

    using OrdinaryDiffEq
    -
    -u0map = deterministic_IC(u0, dm2_eqs) # assuming deterministic initial conditions
    -oprob = ODEProblem(dm2_eqs, u0map, tspan, p)
    -dm2_sol = solve(oprob, Tsit5(), saveat=0.01)

    Now the question is how can we extract the time evolution of the cumulant $\kappa_{03}$. Firstly, note that using the standard moment relationships it can be expressed in terms of raw moments as:

    \[\begin{align*} -\kappa_{03} = 2 \mu_{01}^3 - 3\mu_{02}\mu_{01} + \mu_{03} -\end{align*}\]

    As we were solving for moments up to second order, we do not have any direct information on the third order moment $\mu_{03}$. Nevertheless, we can manually approximate it using the corresponding closure function given above, i.e., $\mu_{03} = \mu_{01}^{-3} \mu_{02}^{3}$. The time trajectories of $\mu_{01}$ and $\mu_{02}$ can be extracted from dm2_sol and their order in the array can be checked with:

    dm2_eqs.odes.states
    5-element Array{Term{Real,Nothing},1}:
    - μ₁₀(t)
    - μ₀₁(t)
    - μ₂₀(t)
    - μ₁₁(t)
    - μ₀₂(t)

    Finally, we can combine all the steps to obtain the $\kappa_{03}$ estimate:

    μ₀₁ = dm2_sol[2, :]
    -μ₀₂ = dm2_sol[5, :]
    -μ₀₃ = (μ₀₁ .^(-3)) .* (μ₀₂ .^3)
    -dm2_κ₀₃ = 2 .* μ₀₁ .^3 .- 3 .* μ₀₂ .* μ₀₁ .+ μ₀₃

    Next we consider a third order moment expansion:

    eqs3 = generate_raw_moment_eqs(rn, 3)
    -dm3_eqs = moment_closure(eqs3, "derivative matching")
    -latexify(dm3_eqs, :closure, print_all=true)

    \[\begin{align*} -\mu{_{40}} =& \mu{_{10}}^{4} \mu{_{20}}^{-6} \mu{_{30}}^{4} \\ -\mu{_{31}} =& \mu{_{01}} \mu{_{30}} \mu{_{10}}^{3} \mu{_{11}}^{-3} \mu{_{20}}^{-3} \mu{_{21}}^{3} \\ -\mu{_{22}} =& \mu{_{01}}^{2} \mu{_{02}}^{-1} \mu{_{10}}^{2} \mu{_{11}}^{-4} \mu{_{12}}^{2} \mu{_{20}}^{-1} \mu{_{21}}^{2} \\ -\mu{_{13}} =& \mu{_{03}} \mu{_{10}} \mu{_{01}}^{3} \mu{_{02}}^{-3} \mu{_{11}}^{-3} \mu{_{12}}^{3} \\ -\mu{_{04}} =& \mu{_{01}}^{4} \mu{_{02}}^{-6} \mu{_{03}}^{4} -\end{align*}\]

    As expected, the closure functions agree with those given in Table III of [1]. We again check the order of variables

    dm3_eqs.odes.states
    9-element Array{Term{Real,Nothing},1}:
    - μ₁₀(t)
    - μ₀₁(t)
    - μ₂₀(t)
    - μ₁₁(t)
    - μ₀₂(t)
    - μ₃₀(t)
    - μ₂₁(t)
    - μ₁₂(t)
    - μ₀₃(t)

    and solve the moment equations, computing the required cumulant:

    u0map = deterministic_IC(u0, dm3_eqs)
    -oprob = ODEProblem(dm3_eqs, u0map, tspan, p)
    -dm3_sol = solve(oprob, Tsit5(), saveat=0.01, abstol=1e-8, reltol=1e-8)
    -
    -μ₀₁ = dm3_sol[2,:]
    -μ₀₂ = dm3_sol[5,:]
    -μ₀₃ = dm3_sol[9,:]
    -dm3_κ₀₃ = 2 .* μ₀₁ .^ 3 - 3 .* μ₀₂ .* μ₀₁ .+ μ₀₃

    Note that we could have also obtained $\kappa_{03}$ estimate in an easier way by using central moment equations, as third order central moments are equal to the corresponding third order cumulants:

    central_eqs3 = generate_central_moment_eqs(rn, 3)
    -dm3_central_eqs = moment_closure(central_eqs3, "derivative matching")
    -
    -u0map = deterministic_IC(u0, dm3_central_eqs)
    -oprob = ODEProblem(dm3_central_eqs, u0map, tspan, p)
    -dm3_central_sol = solve(oprob, Tsit5(), saveat=0.01, abstol=1e-8, reltol=1e-8)
    -
    -# check that the two estimates are equivalent
    -dm3_κ₀₃ ≈ dm3_central_sol[9,:]
    true

    The last ingredient we need for a proper comparison between the second and third order moment expansions is a reference value predicted by the SSA. We can simulate $10^5$ SSA trajectories as follows:

    using JumpProcesses
    -
    -dprob = DiscreteProblem(rn, u0, tspan, p)
    -jprob = JumpProblem(rn, dprob, Direct(), save_positions=(false, false))
    -
    -ensembleprob  = EnsembleProblem(jprob)
    -@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.01, trajectories=100000)
    3.874558 seconds (7.45 M allocations: 714.845 MiB, 46.60% gc time)

    The time evolution of $\kappa_{03}$ can be extracted from SSA data using the get_cumulants function:

    ssa_κ₀₃ = get_cumulants(sol_SSA, 3)[0, 3]

    Finally, we plot the results:

    using Plots, LaTeXStrings
    -
    -plot(dm2_sol.t, dm2_κ₀₃, lw=2, label="2nd order DM")
    -plot!(dm2_sol.t, dm3_κ₀₃, lw=2, label="3rd order DM")
    -plot!(dm2_sol.t, ssa_κ₀₃, lw=2, label="SSA")
    -plot!(ylabel=L"\kappa_{03}", xlabel=L"t", guidefontsize=14, legend=:bottomright)

    Derivative Matching cumulant

    We observe that the third order moment truncation using derivative matching performs significantly better than the second order truncation, accurately matching the true SSA prediction (consistent with the figure in [1]).

    It is also interesting to note that the closure functions of third order moments obtained using derivative matching and log-normal closures are equivalent. We can see that it is indeed the case by printing out the log-normal closure functions

    ln2_eqs = moment_closure(eqs2, "log-normal")
    -latexify(ln2_eqs, :closure, print_all=true)

    \[\begin{align*} -\mu{_{30}} =& \mu{_{10}}^{-3} \mu{_{20}}^{3} \\ -\mu{_{21}} =& \mu{_{20}} \mu{_{01}}^{-1} \mu{_{10}}^{-2} \mu{_{11}}^{2} \\ -\mu{_{12}} =& \mu{_{02}} \mu{_{01}}^{-2} \mu{_{10}}^{-1} \mu{_{11}}^{2} \\ -\mu{_{03}} =& \mu{_{01}}^{-3} \mu{_{02}}^{3} -\end{align*}\]

    and the corresponding derivative matching functions obtained previously:

    latexify(dm2_eqs, :closure, print_all=true)

    \[\begin{align*} -\mu{_{30}} =& \mu{_{10}}^{-3} \mu{_{20}}^{3} \\ -\mu{_{21}} =& \mu{_{20}} \mu{_{01}}^{-1} \mu{_{10}}^{-2} \mu{_{11}}^{2} \\ -\mu{_{12}} =& \mu{_{02}} \mu{_{01}}^{-2} \mu{_{10}}^{-1} \mu{_{11}}^{2} \\ -\mu{_{03}} =& \mu{_{01}}^{-3} \mu{_{02}}^{3} -\end{align*}\]

    However, the equivalence holds only for third order moments. For example, the closure functions of fourth order moments differ:

    ln3_eqs = moment_closure(eqs3, "log-normal")
    -latexify(ln3_eqs, :closure, print_all=true)

    \[\begin{align*} -\mu{_{40}} =& \mu{_{10}}^{-8} \mu{_{20}}^{6} \\ -\mu{_{31}} =& \mu{_{01}}^{-2} \mu{_{10}}^{-6} \mu{_{11}}^{3} \mu{_{20}}^{3} \\ -\mu{_{22}} =& \mu{_{02}} \mu{_{20}} \mu{_{01}}^{-4} \mu{_{10}}^{-4} \mu{_{11}}^{4} \\ -\mu{_{13}} =& \mu{_{01}}^{-6} \mu{_{02}}^{3} \mu{_{10}}^{-2} \mu{_{11}}^{3} \\ -\mu{_{04}} =& \mu{_{01}}^{-8} \mu{_{02}}^{6} -\end{align*}\]

    latexify(dm3_eqs, :closure, print_all=true)

    \[\begin{align*} -\mu{_{40}} =& \mu{_{10}}^{4} \mu{_{20}}^{-6} \mu{_{30}}^{4} \\ -\mu{_{31}} =& \mu{_{01}} \mu{_{30}} \mu{_{10}}^{3} \mu{_{11}}^{-3} \mu{_{20}}^{-3} \mu{_{21}}^{3} \\ -\mu{_{22}} =& \mu{_{01}}^{2} \mu{_{02}}^{-1} \mu{_{10}}^{2} \mu{_{11}}^{-4} \mu{_{12}}^{2} \mu{_{20}}^{-1} \mu{_{21}}^{2} \\ -\mu{_{13}} =& \mu{_{03}} \mu{_{10}} \mu{_{01}}^{3} \mu{_{02}}^{-3} \mu{_{11}}^{-3} \mu{_{12}}^{3} \\ -\mu{_{04}} =& \mu{_{01}}^{4} \mu{_{02}}^{-6} \mu{_{03}}^{4} -\end{align*}\]

    This difference is expected as fourth order moments using log-normal closure are expressed exclusively in terms of first and second order moments, whereas derivative matching additionally incorporates third order moment information. Singh and Hespanha [1, 2] elaborate on this point: as there is no unique way to define higher order moment closure functions for log-normal distribution, both closures are consistent with the assumption that the population is jointly log-normally distributed. We urge the reader to consult the mentioned papers [1, 2] and the references therein for a more complete discussion comparing the two approaches.

    References

    [1]: A. Singh and J. P. Hespanha, "Lognormal Moment Closures for Biochemical Reactions", in Proceedings of the 45th IEEE Conference on Decision and Control, ISSN:0191-2216 (Dec. 2006), pp. 2063–2068. https://doi.org/10.1109/CDC.2006.376994

    [2]: A. Singh and J. P. Hespanha, "Approximate Moment Dynamics for Chemically Reacting Systems", IEEE Transactions on Automatic Control 56, 414–418 (2011). https://doi.org/10.1109/TAC.2010.2088631

    +Derivative Matching Example · MomentClosure.jl

    Derivative Matching Example

    In this example, we aim to reproduce a number of results from the original derivative matching paper by Singh and Hespanha [1]. We consider the bimolecular reaction system given by:

    \[\begin{align*} +X_1 &\stackrel{c_1}{\rightarrow} 2X_1 + X_2, \\ +X_1 + X_2&\stackrel{c_2}{\rightarrow} X_2. +\end{align*}\]

    The reaction network and its parameters can be defined as follows:

    using Catalyst
    +
    +rn = @reaction_network begin
    +    @parameters c₁ c₂
    +    (c₁), x₁ → 2x₁+x₂
    +    (c₂), x₁+x₂ → x₂
    +end
    +
    +# parameter values
    +p = [1.0, 1.0]
    +# initial conditions
    +u0 = [20, 10]
    +# time interval to solve on
    +tspan = (0., 0.5)

    We are interested in extracting the time-evolution of a specific third order cumulant, $κ_{03}$, using second and third order moment expansions with derivative matching, and comparing the obtained estimates to the SSA prediction.

    Let's start with a second order moment expansion and print out the third-order moment closure functions obtained with derivative matching:

    using MomentClosure, Latexify
    +
    +eqs2 = generate_raw_moment_eqs(rn, 2)
    +dm2_eqs = moment_closure(eqs2, "derivative matching")
    +latexify(dm2_eqs, :closure, print_all=true)

    \[\begin{align*} +\mu{_{30}} =& \mu{_{10}}^{-3} \mu{_{20}}^{3} \\ +\mu{_{21}} =& \mu{_{20}} \mu{_{01}}^{-1} \mu{_{10}}^{-2} \mu{_{11}}^{2} \\ +\mu{_{12}} =& \mu{_{02}} \mu{_{01}}^{-2} \mu{_{10}}^{-1} \mu{_{11}}^{2} \\ +\mu{_{03}} =& \mu{_{01}}^{-3} \mu{_{02}}^{3} +\end{align*}\]

    Note that all closure functions are consistent with the ones shown in Table II of [1]. We can then move on to solving the generated system of moment ODEs:

    using OrdinaryDiffEq
    +
    +u0map = deterministic_IC(u0, dm2_eqs) # assuming deterministic initial conditions
    +oprob = ODEProblem(dm2_eqs, u0map, tspan, p)
    +dm2_sol = solve(oprob, Tsit5(), saveat=0.01)

    Now the question is how can we extract the time evolution of the cumulant $\kappa_{03}$. Firstly, note that using the standard moment relationships it can be expressed in terms of raw moments as:

    \[\begin{align*} +\kappa_{03} = 2 \mu_{01}^3 - 3\mu_{02}\mu_{01} + \mu_{03} +\end{align*}\]

    As we were solving for moments up to second order, we do not have any direct information on the third order moment $\mu_{03}$. Nevertheless, we can manually approximate it using the corresponding closure function given above, i.e., $\mu_{03} = \mu_{01}^{-3} \mu_{02}^{3}$. The time trajectories of $\mu_{01}$ and $\mu_{02}$ can be extracted from dm2_sol and their order in the array can be checked with:

    dm2_eqs.odes.states
    5-element Array{Term{Real,Nothing},1}:
    + μ₁₀(t)
    + μ₀₁(t)
    + μ₂₀(t)
    + μ₁₁(t)
    + μ₀₂(t)

    Finally, we can combine all the steps to obtain the $\kappa_{03}$ estimate:

    μ₀₁ = dm2_sol[2, :]
    +μ₀₂ = dm2_sol[5, :]
    +μ₀₃ = (μ₀₁ .^(-3)) .* (μ₀₂ .^3)
    +dm2_κ₀₃ = 2 .* μ₀₁ .^3 .- 3 .* μ₀₂ .* μ₀₁ .+ μ₀₃

    Next we consider a third order moment expansion:

    eqs3 = generate_raw_moment_eqs(rn, 3)
    +dm3_eqs = moment_closure(eqs3, "derivative matching")
    +latexify(dm3_eqs, :closure, print_all=true)

    \[\begin{align*} +\mu{_{40}} =& \mu{_{10}}^{4} \mu{_{20}}^{-6} \mu{_{30}}^{4} \\ +\mu{_{31}} =& \mu{_{01}} \mu{_{30}} \mu{_{10}}^{3} \mu{_{11}}^{-3} \mu{_{20}}^{-3} \mu{_{21}}^{3} \\ +\mu{_{22}} =& \mu{_{01}}^{2} \mu{_{02}}^{-1} \mu{_{10}}^{2} \mu{_{11}}^{-4} \mu{_{12}}^{2} \mu{_{20}}^{-1} \mu{_{21}}^{2} \\ +\mu{_{13}} =& \mu{_{03}} \mu{_{10}} \mu{_{01}}^{3} \mu{_{02}}^{-3} \mu{_{11}}^{-3} \mu{_{12}}^{3} \\ +\mu{_{04}} =& \mu{_{01}}^{4} \mu{_{02}}^{-6} \mu{_{03}}^{4} +\end{align*}\]

    As expected, the closure functions agree with those given in Table III of [1]. We again check the order of variables

    dm3_eqs.odes.states
    9-element Array{Term{Real,Nothing},1}:
    + μ₁₀(t)
    + μ₀₁(t)
    + μ₂₀(t)
    + μ₁₁(t)
    + μ₀₂(t)
    + μ₃₀(t)
    + μ₂₁(t)
    + μ₁₂(t)
    + μ₀₃(t)

    and solve the moment equations, computing the required cumulant:

    u0map = deterministic_IC(u0, dm3_eqs)
    +oprob = ODEProblem(dm3_eqs, u0map, tspan, p)
    +dm3_sol = solve(oprob, Tsit5(), saveat=0.01, abstol=1e-8, reltol=1e-8)
    +
    +μ₀₁ = dm3_sol[2,:]
    +μ₀₂ = dm3_sol[5,:]
    +μ₀₃ = dm3_sol[9,:]
    +dm3_κ₀₃ = 2 .* μ₀₁ .^ 3 - 3 .* μ₀₂ .* μ₀₁ .+ μ₀₃

    Note that we could have also obtained $\kappa_{03}$ estimate in an easier way by using central moment equations, as third order central moments are equal to the corresponding third order cumulants:

    central_eqs3 = generate_central_moment_eqs(rn, 3)
    +dm3_central_eqs = moment_closure(central_eqs3, "derivative matching")
    +
    +u0map = deterministic_IC(u0, dm3_central_eqs)
    +oprob = ODEProblem(dm3_central_eqs, u0map, tspan, p)
    +dm3_central_sol = solve(oprob, Tsit5(), saveat=0.01, abstol=1e-8, reltol=1e-8)
    +
    +# check that the two estimates are equivalent
    +dm3_κ₀₃ ≈ dm3_central_sol[9,:]
    true

    The last ingredient we need for a proper comparison between the second and third order moment expansions is a reference value predicted by the SSA. We can simulate $10^5$ SSA trajectories as follows:

    using JumpProcesses
    +
    +dprob = DiscreteProblem(rn, u0, tspan, p)
    +jprob = JumpProblem(rn, dprob, Direct(), save_positions=(false, false))
    +
    +ensembleprob  = EnsembleProblem(jprob)
    +@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.01, trajectories=100000)
    3.874558 seconds (7.45 M allocations: 714.845 MiB, 46.60% gc time)

    The time evolution of $\kappa_{03}$ can be extracted from SSA data using the get_cumulants function:

    ssa_κ₀₃ = get_cumulants(sol_SSA, 3)[0, 3]

    Finally, we plot the results:

    using Plots, LaTeXStrings
    +
    +plot(dm2_sol.t, dm2_κ₀₃, lw=2, label="2nd order DM")
    +plot!(dm2_sol.t, dm3_κ₀₃, lw=2, label="3rd order DM")
    +plot!(dm2_sol.t, ssa_κ₀₃, lw=2, label="SSA")
    +plot!(ylabel=L"\kappa_{03}", xlabel=L"t", guidefontsize=14, legend=:bottomright)

    Derivative Matching cumulant

    We observe that the third order moment truncation using derivative matching performs significantly better than the second order truncation, accurately matching the true SSA prediction (consistent with the figure in [1]).

    It is also interesting to note that the closure functions of third order moments obtained using derivative matching and log-normal closures are equivalent. We can see that it is indeed the case by printing out the log-normal closure functions

    ln2_eqs = moment_closure(eqs2, "log-normal")
    +latexify(ln2_eqs, :closure, print_all=true)

    \[\begin{align*} +\mu{_{30}} =& \mu{_{10}}^{-3} \mu{_{20}}^{3} \\ +\mu{_{21}} =& \mu{_{20}} \mu{_{01}}^{-1} \mu{_{10}}^{-2} \mu{_{11}}^{2} \\ +\mu{_{12}} =& \mu{_{02}} \mu{_{01}}^{-2} \mu{_{10}}^{-1} \mu{_{11}}^{2} \\ +\mu{_{03}} =& \mu{_{01}}^{-3} \mu{_{02}}^{3} +\end{align*}\]

    and the corresponding derivative matching functions obtained previously:

    latexify(dm2_eqs, :closure, print_all=true)

    \[\begin{align*} +\mu{_{30}} =& \mu{_{10}}^{-3} \mu{_{20}}^{3} \\ +\mu{_{21}} =& \mu{_{20}} \mu{_{01}}^{-1} \mu{_{10}}^{-2} \mu{_{11}}^{2} \\ +\mu{_{12}} =& \mu{_{02}} \mu{_{01}}^{-2} \mu{_{10}}^{-1} \mu{_{11}}^{2} \\ +\mu{_{03}} =& \mu{_{01}}^{-3} \mu{_{02}}^{3} +\end{align*}\]

    However, the equivalence holds only for third order moments. For example, the closure functions of fourth order moments differ:

    ln3_eqs = moment_closure(eqs3, "log-normal")
    +latexify(ln3_eqs, :closure, print_all=true)

    \[\begin{align*} +\mu{_{40}} =& \mu{_{10}}^{-8} \mu{_{20}}^{6} \\ +\mu{_{31}} =& \mu{_{01}}^{-2} \mu{_{10}}^{-6} \mu{_{11}}^{3} \mu{_{20}}^{3} \\ +\mu{_{22}} =& \mu{_{02}} \mu{_{20}} \mu{_{01}}^{-4} \mu{_{10}}^{-4} \mu{_{11}}^{4} \\ +\mu{_{13}} =& \mu{_{01}}^{-6} \mu{_{02}}^{3} \mu{_{10}}^{-2} \mu{_{11}}^{3} \\ +\mu{_{04}} =& \mu{_{01}}^{-8} \mu{_{02}}^{6} +\end{align*}\]

    latexify(dm3_eqs, :closure, print_all=true)

    \[\begin{align*} +\mu{_{40}} =& \mu{_{10}}^{4} \mu{_{20}}^{-6} \mu{_{30}}^{4} \\ +\mu{_{31}} =& \mu{_{01}} \mu{_{30}} \mu{_{10}}^{3} \mu{_{11}}^{-3} \mu{_{20}}^{-3} \mu{_{21}}^{3} \\ +\mu{_{22}} =& \mu{_{01}}^{2} \mu{_{02}}^{-1} \mu{_{10}}^{2} \mu{_{11}}^{-4} \mu{_{12}}^{2} \mu{_{20}}^{-1} \mu{_{21}}^{2} \\ +\mu{_{13}} =& \mu{_{03}} \mu{_{10}} \mu{_{01}}^{3} \mu{_{02}}^{-3} \mu{_{11}}^{-3} \mu{_{12}}^{3} \\ +\mu{_{04}} =& \mu{_{01}}^{4} \mu{_{02}}^{-6} \mu{_{03}}^{4} +\end{align*}\]

    This difference is expected as fourth order moments using log-normal closure are expressed exclusively in terms of first and second order moments, whereas derivative matching additionally incorporates third order moment information. Singh and Hespanha [1, 2] elaborate on this point: as there is no unique way to define higher order moment closure functions for log-normal distribution, both closures are consistent with the assumption that the population is jointly log-normally distributed. We urge the reader to consult the mentioned papers [1, 2] and the references therein for a more complete discussion comparing the two approaches.

    References

    [1]: A. Singh and J. P. Hespanha, "Lognormal Moment Closures for Biochemical Reactions", in Proceedings of the 45th IEEE Conference on Decision and Control, ISSN:0191-2216 (Dec. 2006), pp. 2063–2068. https://doi.org/10.1109/CDC.2006.376994

    [2]: A. Singh and J. P. Hespanha, "Approximate Moment Dynamics for Chemically Reacting Systems", IEEE Transactions on Automatic Control 56, 414–418 (2011). https://doi.org/10.1109/TAC.2010.2088631

    diff --git a/dev/tutorials/geometric_reactions+conditional_closures/index.html b/dev/tutorials/geometric_reactions+conditional_closures/index.html index 081dac5..f9a46eb 100644 --- a/dev/tutorials/geometric_reactions+conditional_closures/index.html +++ b/dev/tutorials/geometric_reactions+conditional_closures/index.html @@ -1,211 +1,211 @@ -Geometrically Distributed Reaction Products and Conditional Closures · MomentClosure.jl

    Geometrically Distributed Reaction Products and Conditional Closures

    In this tutorial, we demonstrate using Catalyst how to define chemical systems involving reactions which products are geometrically distributed random variables. As an example, we consider an autoregulatory (repressive) genetic feedback loop where proteins are expressed in bursts with a geometric burst size distribution, as described by Soltani et al. [1]. Moreover, the state of the gene is modelled as a binary variable—we demonstrate how conditional derivative matching and conditional gaussian closures can be used to approximate such systems, in turn reproducing a number of results from Ref. [1].

    We consider a negative feedback loop described by the following reactions:

    \[\begin{align*} -G^* &\stackrel{k_{on}}{\rightarrow} G, \\ -G + &\stackrel{k_{off}*P^2}{\rightarrow} G^*, \\ -G &\stackrel{k_p}{\rightarrow} G + mP, \\ -P &\stackrel{\gamma_p}{\rightarrow} ∅. -\end{align*}\]

    A gene in the network switches between ON ($G$) and OFF ($G^{\\*}$) states: proteins are produced in the transcriptionally active ON state but the gene can be turned OFF by two protein molecules binding to the promoter region and thus blocking transcription (proteins decay at a constant rate irrespective of the gene state). Note that the gene state can be interpreted as a distinct species that have either zero or one copy number per cell. In other words, it is a Bernoulli random variable: $0$ in the OFF state and $1$ in the ON state.

    The transcription (mRNA) dynamics are not modelled explicitly in this gene circuit. Instead, under the assumption of fast mRNA decay, proteins are taken to be produced in bursts of size $m$, where $m$ is a random variable sampled from the geometric distribution $\phi(m) = b^m/(1+b)^{m+1}$ (with $b$ denoting the mean burst size) [2]. Chemical reaction networks that include reactions which products are independent geometrically distributed random variables (or other symbolic variables) can be defined using Catalyst as demonstrated in this tutorial. Note that the referenced tutorial refers back to this tutorial because in the ancient times Catalyst did not provided such functionality and the previous iteration of MomentClosure implemented a ReactionSystemMod type that offered limited support for such systems (now deprecated as Catalyst does it better in a unified API).

    Using Catalyst, our gene network model can be constructed as follows:

    # load all the packages we will need
    -using MomentClosure, Catalyst, Distributions, JumpProcesses, DiffEqBase, OrdinaryDiffEq, DiffEqBase.EnsembleAnalysis, Plots, Latexify
    -
    -# Proteins are produced in bursts of size m, where m is a geometric random variable with mean b.
    -# Note that if b is the mean burst size, then p = 1/(1+b). 
    -# Implemented by first registering the distribution with Symbolics
    -@register_symbolic Distributions.Geometric(b)
    -@parameters b
    -m = rand(Distributions.Geometric(1/(1+b)))
    -
    -rn = @reaction_network begin
    -      @parameters k_on k_off k_p γ_p
    -      k_on*(1-g), 0 --> g  # G* -> G
    -      k_off*P^2, g --> 0   # G -> G*
    -      k_p, g --> g + $m*P  # G -> G + mP, m ~ Geometric(p)
    -      γ_p, P --> 0         # P -> ∅
    -end

    We can now generate the raw moment equations up to third order:

    eqs = generate_raw_moment_eqs(rn, 3)
    -latexify(eqs)

    \[\begin{align*} -\frac{d\mu_{1 0}}{dt} =& k_{on} - k_{off} \mu_{1 2} - k_{on} \mu_{1 0} \\ -\frac{d\mu_{0 1}}{dt} =& b k_{p} \mu_{1 0} - \gamma_{p} \mu_{0 1} \\ -\frac{d\mu_{2 0}}{dt} =& k_{on} + k_{off} \mu_{1 2} + k_{on} \mu_{1 0} - 2 k_{on} \mu_{2 0} - 2 k_{off} \mu_{2 2} \\ -\frac{d\mu_{1 1}}{dt} =& k_{on} \mu_{0 1} + b k_{p} \mu_{2 0} - k_{on} \mu_{1 1} - \gamma_{p} \mu_{1 1} - k_{off} \mu_{1 3} \\ -\frac{d\mu_{0 2}}{dt} =& \gamma_{p} \mu_{0 1} + b k_{p} \mu_{1 0} + 2 b k_{p} \mu_{1 1} + 2 k_{p} b^{2} \mu_{1 0} - 2 \gamma_{p} \mu_{0 2} \\ -\frac{d\mu_{3 0}}{dt} =& k_{on} + 3 k_{off} \mu_{2 2} + 2 k_{on} \mu_{1 0} - k_{off} \mu_{1 2} - 3 k_{off} \mu_{3 2} - 3 k_{on} \mu_{3 0} \\ -\frac{d\mu_{2 1}}{dt} =& k_{on} \mu_{0 1} + k_{on} \mu_{1 1} + k_{off} \mu_{1 3} + b k_{p} \mu_{3 0} - 2 k_{on} \mu_{2 1} - \gamma_{p} \mu_{2 1} - 2 k_{off} \mu_{2 3} \\ -\frac{d\mu_{1 2}}{dt} =& k_{on} \mu_{0 2} + \gamma_{p} \mu_{1 1} + b k_{p} \mu_{2 0} + 2 k_{p} b^{2} \mu_{2 0} + 2 b k_{p} \mu_{2 1} - k_{off} \mu_{1 4} - k_{on} \mu_{1 2} - 2 \gamma_{p} \mu_{1 2} \\ -\frac{d\mu_{0 3}}{dt} =& b k_{p} \mu_{1 0} + 3 \gamma_{p} \mu_{0 2} + 3 b k_{p} \mu_{1 1} + 3 b k_{p} \mu_{1 2} + 6 k_{p} b^{2} \mu_{1 0} + 6 k_{p} b^{3} \mu_{1 0} + 6 k_{p} b^{2} \mu_{1 1} - \gamma_{p} \mu_{0 1} - 3 \gamma_{p} \mu_{0 3} -\end{align*}\]

    A lot of information in this system of ODEs is redundant as the gene state is a Bernoulli variable that (in our case) has the following properties:

    \[\begin{align*} -μ_{j0} &= μ_{10}, \quad j \in {2, 3, \dotsc}, \\ -μ_{jk} &= μ_{1k}, \quad j,k \in {1, 2, 3, \dotsc} -\end{align*}\]

    We can clean the moment equations accordingly by specifying which molecule numbers are Bernoulli variables and using the bernoulli_moment_eqs function:

    # specify the indices of species which molecule numbers are binary
    -binary_vars = [1]
    -# simplify the moment equations using properties of Bernoulli variables
    -clean_eqs = bernoulli_moment_eqs(eqs, binary_vars)
    -latexify(clean_eqs)

    \[\begin{align*} -\frac{d\mu_{1 0}}{dt} =& k_{on} - k_{off} \mu_{1 2} - k_{on} \mu_{1 0} \\ -\frac{d\mu_{0 1}}{dt} =& b k_{p} \mu_{1 0} - \gamma_{p} \mu_{0 1} \\ -\frac{d\mu_{1 1}}{dt} =& k_{on} \mu_{0 1} + b k_{p} \mu_{1 0} - k_{on} \mu_{1 1} - \gamma_{p} \mu_{1 1} - k_{off} \mu_{1 3} \\ -\frac{d\mu_{0 2}}{dt} =& \gamma_{p} \mu_{0 1} + b k_{p} \mu_{1 0} + 2 b k_{p} \mu_{1 1} + 2 k_{p} b^{2} \mu_{1 0} - 2 \gamma_{p} \mu_{0 2} \\ -\frac{d\mu_{1 2}}{dt} =& k_{on} \mu_{0 2} + \gamma_{p} \mu_{1 1} + b k_{p} \mu_{1 0} + 2 b k_{p} \mu_{1 1} + 2 k_{p} b^{2} \mu_{1 0} - k_{off} \mu_{1 4} - k_{on} \mu_{1 2} - 2 \gamma_{p} \mu_{1 2} \\ -\frac{d\mu_{0 3}}{dt} =& b k_{p} \mu_{1 0} + 3 \gamma_{p} \mu_{0 2} + 3 b k_{p} \mu_{1 1} + 3 b k_{p} \mu_{1 2} + 6 k_{p} b^{2} \mu_{1 0} + 6 k_{p} b^{3} \mu_{1 0} + 6 k_{p} b^{2} \mu_{1 1} - \gamma_{p} \mu_{0 1} - 3 \gamma_{p} \mu_{0 3} -\end{align*}\]

    The system of ODEs is now much simpler and we can see that there are two higher-order moments we need to truncate: $\mu_{13}$ and $μ_{14}$. We consider normal, derivative matching, conditional gaussian and conditional derivative matching closures to see how well they compare. First we apply different closures and print out the corresponding higher-order moment expressions in order to check that our results are consistent with those published in [1].

    For normal closure:

    normal_eqs = moment_closure(eqs, "normal", binary_vars)
    -latexify(normal_eqs, :closure)

    \[\begin{align*} -\mu{_{13}} =& \mu{_{03}} \mu{_{10}} + 3 \mu{_{01}} \mu{_{12}} + 3 \mu{_{02}} \mu{_{11}} + 6 \mu{_{10}} \mu{_{01}}^{3} - 6 \mu{_{11}} \mu{_{01}}^{2} - 6 \mu{_{01}} \mu{_{02}} \mu{_{10}} \\ -\mu{_{14}} =& \mu{_{04}} \mu{_{10}} + 4 \mu{_{01}} \mu{_{13}} + 6 \mu{_{02}} \mu{_{12}} + 4 \mu{_{03}} \mu{_{11}} + 24 \mu{_{11}} \mu{_{01}}^{3} + 36 \mu{_{02}} \mu{_{10}} \mu{_{01}}^{2} - 24 \mu{_{10}} \mu{_{01}}^{4} - 6 \mu{_{10}} \mu{_{02}}^{2} - 12 \mu{_{12}} \mu{_{01}}^{2} - 24 \mu{_{01}} \mu{_{02}} \mu{_{11}} - 8 \mu{_{01}} \mu{_{03}} \mu{_{10}} -\end{align*}\]

    Note that our expression for $μ_{14}$ is different from the equivalent $\langle gp^4 \rangle$ in Eq. (8) of [1] as it seems that the authors introduced a mistake considering the central moment and cumulant relationship in Eq. (7).

    Using derivative matching, we obtain:

    dm_eqs = moment_closure(eqs, "derivative matching", binary_vars)
    -latexify(dm_eqs, :closure)

    \[\begin{align*} -\mu_{1 3} =& \frac{\mu_{0 1}^{3} \mu_{1 2}^{3} \mu_{0 3} \mu_{1 0}}{\mu_{0 2}^{3} \mu_{1 1}^{3}} \\ -\mu_{1 4} =& \frac{\mu_{0 2}^{6} \mu_{1 1}^{4} \mu_{1 3}^{4} \mu_{0 4}}{\mu_{0 1}^{4} \mu_{0 3}^{4} \mu_{1 2}^{6} \mu_{1 0}} -\end{align*}\]

    For conditional gaussian closure:

    cond_gaussian_eqs = moment_closure(eqs, "conditional gaussian", binary_vars)
    -latexify(cond_gaussian_eqs, :closure)

    \[\begin{align*} -\mu_{1 3} =& \frac{-2 \mu_{1 1}^{3}}{\mu_{1 0}^{2}} + \frac{3 \mu_{1 1} \mu_{1 2}}{\mu_{1 0}} \\ -\mu_{1 4} =& \frac{3 \mu_{1 2}^{2}}{\mu_{1 0}} + \frac{6 \mu_{1 1}^{4}}{\mu_{1 0}^{3}} + \frac{-12 \mu_{1 1}^{2} \mu_{1 2}}{\mu_{1 0}^{2}} + \frac{4 \mu_{1 1} \mu_{1 3}}{\mu_{1 0}} -\end{align*}\]

    And, finally, for conditional derivative matching:

    cond_dm_eqs = moment_closure(eqs, "conditional derivative matching", binary_vars)
    -latexify(cond_dm_eqs, :closure)

    \[\begin{align*} -\mu_{1 3} =& \frac{\mu_{0 1}^{3} \mu_{1 2}^{3} \mu_{0 3} \mu_{1 0}}{\mu_{0 2}^{3} \mu_{1 1}^{3}} \\ -\mu_{1 4} =& \frac{\mu_{0 2}^{6} \mu_{1 1}^{4} \mu_{1 3}^{4} \mu_{0 4}}{\mu_{0 1}^{4} \mu_{0 3}^{4} \mu_{1 2}^{6} \mu_{1 0}} -\end{align*}\]

    All these results are consistent with [1], reassuring that the model and closures are implemented as intended. Finally, we can proceed to solve the resulting ODEs and compare the resulting means and standard deviations to the SSA. Following Soltani et al. [1], we define all model parameters as:

    mean_p = 200
    -mean_b = 70
    -γ_p_val = 1
    -k_off_val = 0.001
    -k_on_val = 0.05
    -
    -k_p_val = mean_p * γ_p_val * (k_off_val * mean_p^2 + k_on_val) / (k_on_val * mean_b)
    -
    -symmap = [:k_on => k_on_val,
    -          :k_off => k_off_val,
    -          :k_p => k_p_val,
    -          :γ_p => γ_p_val,
    -          :b => mean_b]
    -pmap = symmap_to_varmap(rn, symmap)
    -
    -# initial gene state and protein number, order [g, p]
    -u₀ = [1, 1]
    -
    -# time interval to solve on
    -tspan = (0., 6.0)

    The reaction network with geometric bursts can be simulated using the SSA as usual:

    # convert the reaction network into a system of jump processes
    -jsys = convert(JumpSystem, rn; combinatoric_ratelaws=false)
    -
    -# create a discrete problem setting the simulation parameters
    -dprob = DiscreteProblem(u₀, tspan, pmap)
    -
    -# create a JumpProblem compatible with ReactionSystemMod
    -jprob = JumpProblem(rn, dprob, Direct(), save_positions=(false, false))
    -
    -# simulate 2×10⁴ SSA trajectories
    -ensembleprob  = EnsembleProblem(jprob)
    -@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.1, trajectories=20000)
    -# compute the means and variances
    -means_ssa, vars_ssa = timeseries_steps_meanvar(sol_SSA)
    4.858357 seconds (14.30 M allocations: 901.032 MiB, 6.25% gc time, 63.45% compilation time)

    We continue to solve the moment equations for each closure:

    plt_m = plot()   # plot mean protein number
    -plt_std = plot() # plot ssd of protein number
    -
    -# construct the initial molecule number mapping
    -u₀map = deterministic_IC(u₀, dm_eqs)
    -
    -# solve moment ODEs for each closure and plot the results
    -for closure in ["normal", "derivative matching",
    -                "conditional gaussian", "conditional derivative matching"]
    -
    -    # it is very quick so we just apply all closures again
    -    closed_eqs = moment_closure(eqs, closure, binary_vars)
    -
    -    # solve the system of moment ODEs
    -    oprob = ODEProblem(closed_eqs, u₀map, tspan, pmap)
    -    sol = solve(oprob, AutoTsit5(Rosenbrock23()), saveat=0.01)
    -
    -    # μ₀₁ is 2nd and μ₀₂ is 4th element in sol
    -    # can check the order with `closed_eqs.odes.states`
    -    plt_m = plot!(plt_m, sol, idxs=[2], label=closure)
    -    plt_std = plot!(plt_std, sol.t, sqrt.(sol[4, :] .- sol[2, :].^2), label=closure)
    -
    -end
    -
    -plt_m = plot!(plt_m, xlabel="Time [hr]", ylabel="Protein mean level")
    -plt_m = plot!(plt_m, means_ssa.t, means_ssa[2,:], label="SSA", linestyle=:dash, color="gray")
    -plt_std = plot!(plt_std, xlabel="Time [hr]", ylabel="Protein standard deviation")
    -plt_std = plot!(plt_std, vars_ssa.t, sqrt.(vars_ssa[2,:]), label="SSA", linestyle=:dash, color="gray")
    plot(plt_m, lw=2)

    Gene 1 means

    plot(plt_std, lw=2)

    Gene 2 stds

    We observe that the two conditional closures give the most accurate results. Therefore, closing moments conditioned on the gene being active is an effective approximation in this case. Note that our results for normal closure are different from [1], most likely due to the incorrect fifth-order moment closure function given in the paper.

    We now turn to a more complex network involving two genes (two Bernoulli variables), a repressor-activator circuit: an activator protein $Y$ expressed by one gene can turn ON another gene which produces a repressor protein $X$, that subsequently can bind to the gene promoter region of the activator-producing gene turning it OFF (see [1] for more details). As before, $X$ and $Y$ proteins are expressed in geometrically-distributed bursts. The system can be specified as follows:

    @parameters b_x b_y
    -# could redefine in terms of success probabilities p_x and p_y as above
    -m = rand(Distributions.Geometric(1/(1+b_x)))
    -l = rand(Distributions.Geometric(1/(1+b_y)))
    -
    -# g_x - gene state of X protein producing gene
    -# g_y - gene state of Y protein producing gene
    -# x, y - proteins X and Y
    -rn = @reaction_network begin
    -      @parameters kx_on kx_off ky_on ky_off k_x γ_x k_y γ_y
    -      kx_on*(1-g_x)*y, 0 --> g_x  # 0   -> g_x
    -      kx_off,          g_x --> 0  # g_x -> 0
    -      ky_on*(1-g_y),   0 --> g_y  # 0 -> g_y
    -      ky_off*x,        g_y --> 0  # g_y -> 0
    -      k_x*g_x,         0 --> $m*x # 0 -> mx, m ~ Geometric(mean=b_x)
    -      γ_x,             x --> 0    # x -> 0
    -      k_y*g_y,         0 --> $l*y # 0 -> ly, l ~ Geometric(mean_b_y)
    -      γ_y,             y --> 0    # y -> 0
    -end
    -
    -# both g_x and g_y are Bernoulli random variables
    -binary_vars = [1, 2]
    -
    -# Parameter initialisation
    -
    -mean_x = 100
    -mean_y = 100
    -mean_b_x = 5
    -mean_b_y = 5
    -γ_x_val = 1
    -γ_y_val = 1
    -kx_off_val = 4
    -ky_on_val = 0.3
    -kx_on_val = 0.05
    -ky_off_val = 0.05
    -
    -k_x_val = mean_x * γ_x_val * (kx_off_val * mean_y^2 + kx_on_val) / (kx_on_val * mean_b_x)
    -k_y_val = mean_y * γ_y_val * (ky_off_val * mean_x^2 + ky_on_val) / (ky_on_val * mean_b_y)
    -
    -# unclear if Soltani et al. (2015) actually used this parameter set as X numbers
    -# jump to millions making SSA extremely slow...
    -
    -# introduce additional rescaling (otherwise rate coefficients are too high)
    -k_x_val *= 0.00003
    -k_y_val *= 0.01
    -
    -# parameter mapping
    -symmap = [:kx_on => kx_on_val,
    -          :kx_off => kx_off_val,
    -          :ky_on => ky_on_val,
    -          :ky_off => ky_off_val,
    -          :k_x => k_x_val,
    -          :k_y => k_y_val,
    -          :γ_x => γ_x_val,
    -          :γ_y => γ_y_val,
    -          :b_x => mean_b_x,
    -          :b_y => mean_b_y]
    -pmap = symmap_to_varmap(rn, symmap)
    -
    -# initial gene state and protein number, order [g_x, g_y, x, y]
    -u₀ = [1, 1, 1, 1]
    -
    -# time interval to solve on
    -tspan = (0., 12.0)

    Note that here we use a different parameter set from the one considered in [1] as otherwise the number of $X$ proteins goes into millions, making the comparison between closure results difficult due to SSA being extremely slow—it appears that either we have included a mistake setting the parameter values or there is a typo in the paper.

    We can run SSA as follows:

    jsys = convert(JumpSystem, rn, combinatoric_ratelaws=false)
    -dprob = DiscreteProblem(jsys, u₀, tspan, pmap)
    -jprob = JumpProblem(jsys, dprob, Direct(), save_positions=(false, false))
    -
    -ensembleprob  = EnsembleProblem(jprob)
    -@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.1, trajectories=10000)
    -means_ssa, vars_ssa = timeseries_steps_meanvar(sol_SSA)
    13.712331 seconds (43.27 M allocations: 1.697 GiB, 6.56% gc time, 10.01% compilation time)

    We use fourth order moment expansion and apply different closure methods as done for the negative feedback loop, considering the number of activator proteins $Y$ and its standard deviation:

    plt_m = plot()   # plot mean activator protein number
    -plt_std = plot() # plot ssd of activator protein number
    -
    -for closure in ["derivative matching", "conditional derivative matching"]
    -
    -    closed_eqs = moment_closure(eqs, closure, binary_vars)
    -
    -    u₀map = deterministic_IC(u₀, closed_eqs)
    -    oprob = ODEProblem(closed_eqs, u₀map, tspan, pmap)
    -    sol = solve(oprob, Tsit5(), saveat=0.1)
    -
    -    # μ₀₀₀₁ is the 4th and μ₀₀₀₂ is the 12th element in sol (can check with closed_eqs.odes.states)
    -    plt_m = plot!(plt_m, sol, idxs=[4], label=closure)
    -    plt_std = plot!(plt_std, sol.t, sqrt.(sol[12, :] .- sol[4, :].^2), label=closure)
    -end
    -
    -plt_m = plot!(plt_m, xlabel="Time [hr]", ylabel="Activator mean level")
    -plt_m = plot!(plt_m, means_ssa.t, means_ssa[4,:], label="SSA", linestyle=:dash, color="gray")
    -plt_std = plot!(plt_std, xlabel="Time [hr]", ylabel="Activator standard deviation")
    -plt_std = plot!(plt_std, vars_ssa.t, sqrt.(vars_ssa[4,:]), label="SSA", linestyle=:dash, color="gray")

    Note that here we apply only derivative matching and conditional derivative matching, as both normal and conditional gaussian closures failed to be evaluated for the entire time course (irrespective of the solver used). Finally, we can plot the results:

    plot(plt_m, lw=2)

    Gene 2 means

    plot(plt_std, lw=2, xlims=(0., 12.))

    Gene 2 stds

    The trajectories obtained with conditional derivative matching quite accurately match the true dynamics, showing that it is indeed a powerful closure method for reaction networks involving species with very low (binary) copy numbers.

    References

    [1]: M. Soltani, C. A. Vargas-Garcia, and A. Singh, "Conditional Moment Closure Schemes for Studying Stochastic Dynamics of Genetic Circuits", IEEE Transactions on Biomedical Circuits and Systems 9, 518–526 (2015). https://doi.org/10.1109/tbcas.2015.2453158

    [2]: D. Schnoerr, G. Sanguinetti, and R. Grima, "Approximation and inference methods for stochastic biochemical kinetics - a tutorial review", Journal of Physics A: Mathematical and Theoretical 50, 093001 (2017). https://doi.org/10.1088/1751-8121/aa54d9

    +Geometrically Distributed Reaction Products and Conditional Closures · MomentClosure.jl

    Geometrically Distributed Reaction Products and Conditional Closures

    In this tutorial, we demonstrate using Catalyst how to define chemical systems involving reactions which products are geometrically distributed random variables. As an example, we consider an autoregulatory (repressive) genetic feedback loop where proteins are expressed in bursts with a geometric burst size distribution, as described by Soltani et al. [1]. Moreover, the state of the gene is modelled as a binary variable—we demonstrate how conditional derivative matching and conditional gaussian closures can be used to approximate such systems, in turn reproducing a number of results from Ref. [1].

    We consider a negative feedback loop described by the following reactions:

    \[\begin{align*} +G^* &\stackrel{k_{on}}{\rightarrow} G, \\ +G + &\stackrel{k_{off}*P^2}{\rightarrow} G^*, \\ +G &\stackrel{k_p}{\rightarrow} G + mP, \\ +P &\stackrel{\gamma_p}{\rightarrow} ∅. +\end{align*}\]

    A gene in the network switches between ON ($G$) and OFF ($G^{\\*}$) states: proteins are produced in the transcriptionally active ON state but the gene can be turned OFF by two protein molecules binding to the promoter region and thus blocking transcription (proteins decay at a constant rate irrespective of the gene state). Note that the gene state can be interpreted as a distinct species that have either zero or one copy number per cell. In other words, it is a Bernoulli random variable: $0$ in the OFF state and $1$ in the ON state.

    The transcription (mRNA) dynamics are not modelled explicitly in this gene circuit. Instead, under the assumption of fast mRNA decay, proteins are taken to be produced in bursts of size $m$, where $m$ is a random variable sampled from the geometric distribution $\phi(m) = b^m/(1+b)^{m+1}$ (with $b$ denoting the mean burst size) [2]. Chemical reaction networks that include reactions which products are independent geometrically distributed random variables (or other symbolic variables) can be defined using Catalyst as demonstrated in this tutorial. Note that the referenced tutorial refers back to this tutorial because in the ancient times Catalyst did not provided such functionality and the previous iteration of MomentClosure implemented a ReactionSystemMod type that offered limited support for such systems (now deprecated as Catalyst does it better in a unified API).

    Using Catalyst, our gene network model can be constructed as follows:

    # load all the packages we will need
    +using MomentClosure, Catalyst, Distributions, JumpProcesses, DiffEqBase, OrdinaryDiffEq, DiffEqBase.EnsembleAnalysis, Plots, Latexify
    +
    +# Proteins are produced in bursts of size m, where m is a geometric random variable with mean b.
    +# Note that if b is the mean burst size, then p = 1/(1+b). 
    +# Implemented by first registering the distribution with Symbolics
    +@register_symbolic Distributions.Geometric(b)
    +@parameters b
    +m = rand(Distributions.Geometric(1/(1+b)))
    +
    +rn = @reaction_network begin
    +      @parameters k_on k_off k_p γ_p
    +      k_on*(1-g), 0 --> g  # G* -> G
    +      k_off*P^2, g --> 0   # G -> G*
    +      k_p, g --> g + $m*P  # G -> G + mP, m ~ Geometric(p)
    +      γ_p, P --> 0         # P -> ∅
    +end

    We can now generate the raw moment equations up to third order:

    eqs = generate_raw_moment_eqs(rn, 3)
    +latexify(eqs)

    \[\begin{align*} +\frac{d\mu_{1 0}}{dt} =& k_{on} - k_{off} \mu_{1 2} - k_{on} \mu_{1 0} \\ +\frac{d\mu_{0 1}}{dt} =& b k_{p} \mu_{1 0} - \gamma_{p} \mu_{0 1} \\ +\frac{d\mu_{2 0}}{dt} =& k_{on} + k_{off} \mu_{1 2} + k_{on} \mu_{1 0} - 2 k_{on} \mu_{2 0} - 2 k_{off} \mu_{2 2} \\ +\frac{d\mu_{1 1}}{dt} =& k_{on} \mu_{0 1} + b k_{p} \mu_{2 0} - k_{on} \mu_{1 1} - \gamma_{p} \mu_{1 1} - k_{off} \mu_{1 3} \\ +\frac{d\mu_{0 2}}{dt} =& \gamma_{p} \mu_{0 1} + b k_{p} \mu_{1 0} + 2 b k_{p} \mu_{1 1} + 2 k_{p} b^{2} \mu_{1 0} - 2 \gamma_{p} \mu_{0 2} \\ +\frac{d\mu_{3 0}}{dt} =& k_{on} + 3 k_{off} \mu_{2 2} + 2 k_{on} \mu_{1 0} - k_{off} \mu_{1 2} - 3 k_{off} \mu_{3 2} - 3 k_{on} \mu_{3 0} \\ +\frac{d\mu_{2 1}}{dt} =& k_{on} \mu_{0 1} + k_{on} \mu_{1 1} + k_{off} \mu_{1 3} + b k_{p} \mu_{3 0} - 2 k_{on} \mu_{2 1} - \gamma_{p} \mu_{2 1} - 2 k_{off} \mu_{2 3} \\ +\frac{d\mu_{1 2}}{dt} =& k_{on} \mu_{0 2} + \gamma_{p} \mu_{1 1} + b k_{p} \mu_{2 0} + 2 k_{p} b^{2} \mu_{2 0} + 2 b k_{p} \mu_{2 1} - k_{off} \mu_{1 4} - k_{on} \mu_{1 2} - 2 \gamma_{p} \mu_{1 2} \\ +\frac{d\mu_{0 3}}{dt} =& b k_{p} \mu_{1 0} + 3 \gamma_{p} \mu_{0 2} + 3 b k_{p} \mu_{1 1} + 3 b k_{p} \mu_{1 2} + 6 k_{p} b^{2} \mu_{1 0} + 6 k_{p} b^{3} \mu_{1 0} + 6 k_{p} b^{2} \mu_{1 1} - \gamma_{p} \mu_{0 1} - 3 \gamma_{p} \mu_{0 3} +\end{align*}\]

    A lot of information in this system of ODEs is redundant as the gene state is a Bernoulli variable that (in our case) has the following properties:

    \[\begin{align*} +μ_{j0} &= μ_{10}, \quad j \in {2, 3, \dotsc}, \\ +μ_{jk} &= μ_{1k}, \quad j,k \in {1, 2, 3, \dotsc} +\end{align*}\]

    We can clean the moment equations accordingly by specifying which molecule numbers are Bernoulli variables and using the bernoulli_moment_eqs function:

    # specify the indices of species which molecule numbers are binary
    +binary_vars = [1]
    +# simplify the moment equations using properties of Bernoulli variables
    +clean_eqs = bernoulli_moment_eqs(eqs, binary_vars)
    +latexify(clean_eqs)

    \[\begin{align*} +\frac{d\mu_{1 0}}{dt} =& k_{on} - k_{off} \mu_{1 2} - k_{on} \mu_{1 0} \\ +\frac{d\mu_{0 1}}{dt} =& b k_{p} \mu_{1 0} - \gamma_{p} \mu_{0 1} \\ +\frac{d\mu_{1 1}}{dt} =& k_{on} \mu_{0 1} + b k_{p} \mu_{1 0} - k_{on} \mu_{1 1} - \gamma_{p} \mu_{1 1} - k_{off} \mu_{1 3} \\ +\frac{d\mu_{0 2}}{dt} =& \gamma_{p} \mu_{0 1} + b k_{p} \mu_{1 0} + 2 b k_{p} \mu_{1 1} + 2 k_{p} b^{2} \mu_{1 0} - 2 \gamma_{p} \mu_{0 2} \\ +\frac{d\mu_{1 2}}{dt} =& k_{on} \mu_{0 2} + \gamma_{p} \mu_{1 1} + b k_{p} \mu_{1 0} + 2 b k_{p} \mu_{1 1} + 2 k_{p} b^{2} \mu_{1 0} - k_{off} \mu_{1 4} - k_{on} \mu_{1 2} - 2 \gamma_{p} \mu_{1 2} \\ +\frac{d\mu_{0 3}}{dt} =& b k_{p} \mu_{1 0} + 3 \gamma_{p} \mu_{0 2} + 3 b k_{p} \mu_{1 1} + 3 b k_{p} \mu_{1 2} + 6 k_{p} b^{2} \mu_{1 0} + 6 k_{p} b^{3} \mu_{1 0} + 6 k_{p} b^{2} \mu_{1 1} - \gamma_{p} \mu_{0 1} - 3 \gamma_{p} \mu_{0 3} +\end{align*}\]

    The system of ODEs is now much simpler and we can see that there are two higher-order moments we need to truncate: $\mu_{13}$ and $μ_{14}$. We consider normal, derivative matching, conditional gaussian and conditional derivative matching closures to see how well they compare. First we apply different closures and print out the corresponding higher-order moment expressions in order to check that our results are consistent with those published in [1].

    For normal closure:

    normal_eqs = moment_closure(eqs, "normal", binary_vars)
    +latexify(normal_eqs, :closure)

    \[\begin{align*} +\mu{_{13}} =& \mu{_{03}} \mu{_{10}} + 3 \mu{_{01}} \mu{_{12}} + 3 \mu{_{02}} \mu{_{11}} + 6 \mu{_{10}} \mu{_{01}}^{3} - 6 \mu{_{11}} \mu{_{01}}^{2} - 6 \mu{_{01}} \mu{_{02}} \mu{_{10}} \\ +\mu{_{14}} =& \mu{_{04}} \mu{_{10}} + 4 \mu{_{01}} \mu{_{13}} + 6 \mu{_{02}} \mu{_{12}} + 4 \mu{_{03}} \mu{_{11}} + 24 \mu{_{11}} \mu{_{01}}^{3} + 36 \mu{_{02}} \mu{_{10}} \mu{_{01}}^{2} - 24 \mu{_{10}} \mu{_{01}}^{4} - 6 \mu{_{10}} \mu{_{02}}^{2} - 12 \mu{_{12}} \mu{_{01}}^{2} - 24 \mu{_{01}} \mu{_{02}} \mu{_{11}} - 8 \mu{_{01}} \mu{_{03}} \mu{_{10}} +\end{align*}\]

    Note that our expression for $μ_{14}$ is different from the equivalent $\langle gp^4 \rangle$ in Eq. (8) of [1] as it seems that the authors introduced a mistake considering the central moment and cumulant relationship in Eq. (7).

    Using derivative matching, we obtain:

    dm_eqs = moment_closure(eqs, "derivative matching", binary_vars)
    +latexify(dm_eqs, :closure)

    \[\begin{align*} +\mu_{1 3} =& \frac{\mu_{0 1}^{3} \mu_{1 2}^{3} \mu_{0 3} \mu_{1 0}}{\mu_{0 2}^{3} \mu_{1 1}^{3}} \\ +\mu_{1 4} =& \frac{\mu_{0 2}^{6} \mu_{1 1}^{4} \mu_{1 3}^{4} \mu_{0 4}}{\mu_{0 1}^{4} \mu_{0 3}^{4} \mu_{1 2}^{6} \mu_{1 0}} +\end{align*}\]

    For conditional gaussian closure:

    cond_gaussian_eqs = moment_closure(eqs, "conditional gaussian", binary_vars)
    +latexify(cond_gaussian_eqs, :closure)

    \[\begin{align*} +\mu_{1 3} =& \frac{-2 \mu_{1 1}^{3}}{\mu_{1 0}^{2}} + \frac{3 \mu_{1 1} \mu_{1 2}}{\mu_{1 0}} \\ +\mu_{1 4} =& \frac{3 \mu_{1 2}^{2}}{\mu_{1 0}} + \frac{6 \mu_{1 1}^{4}}{\mu_{1 0}^{3}} + \frac{-12 \mu_{1 1}^{2} \mu_{1 2}}{\mu_{1 0}^{2}} + \frac{4 \mu_{1 1} \mu_{1 3}}{\mu_{1 0}} +\end{align*}\]

    And, finally, for conditional derivative matching:

    cond_dm_eqs = moment_closure(eqs, "conditional derivative matching", binary_vars)
    +latexify(cond_dm_eqs, :closure)

    \[\begin{align*} +\mu_{1 3} =& \frac{\mu_{0 1}^{3} \mu_{1 2}^{3} \mu_{0 3} \mu_{1 0}}{\mu_{0 2}^{3} \mu_{1 1}^{3}} \\ +\mu_{1 4} =& \frac{\mu_{0 2}^{6} \mu_{1 1}^{4} \mu_{1 3}^{4} \mu_{0 4}}{\mu_{0 1}^{4} \mu_{0 3}^{4} \mu_{1 2}^{6} \mu_{1 0}} +\end{align*}\]

    All these results are consistent with [1], reassuring that the model and closures are implemented as intended. Finally, we can proceed to solve the resulting ODEs and compare the resulting means and standard deviations to the SSA. Following Soltani et al. [1], we define all model parameters as:

    mean_p = 200
    +mean_b = 70
    +γ_p_val = 1
    +k_off_val = 0.001
    +k_on_val = 0.05
    +
    +k_p_val = mean_p * γ_p_val * (k_off_val * mean_p^2 + k_on_val) / (k_on_val * mean_b)
    +
    +symmap = [:k_on => k_on_val,
    +          :k_off => k_off_val,
    +          :k_p => k_p_val,
    +          :γ_p => γ_p_val,
    +          :b => mean_b]
    +pmap = symmap_to_varmap(rn, symmap)
    +
    +# initial gene state and protein number, order [g, p]
    +u₀ = [1, 1]
    +
    +# time interval to solve on
    +tspan = (0., 6.0)

    The reaction network with geometric bursts can be simulated using the SSA as usual:

    # convert the reaction network into a system of jump processes
    +jsys = convert(JumpSystem, rn; combinatoric_ratelaws=false)
    +
    +# create a discrete problem setting the simulation parameters
    +dprob = DiscreteProblem(u₀, tspan, pmap)
    +
    +# create a JumpProblem compatible with ReactionSystemMod
    +jprob = JumpProblem(rn, dprob, Direct(), save_positions=(false, false))
    +
    +# simulate 2×10⁴ SSA trajectories
    +ensembleprob  = EnsembleProblem(jprob)
    +@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.1, trajectories=20000)
    +# compute the means and variances
    +means_ssa, vars_ssa = timeseries_steps_meanvar(sol_SSA)
    4.858357 seconds (14.30 M allocations: 901.032 MiB, 6.25% gc time, 63.45% compilation time)

    We continue to solve the moment equations for each closure:

    plt_m = plot()   # plot mean protein number
    +plt_std = plot() # plot ssd of protein number
    +
    +# construct the initial molecule number mapping
    +u₀map = deterministic_IC(u₀, dm_eqs)
    +
    +# solve moment ODEs for each closure and plot the results
    +for closure in ["normal", "derivative matching",
    +                "conditional gaussian", "conditional derivative matching"]
    +
    +    # it is very quick so we just apply all closures again
    +    closed_eqs = moment_closure(eqs, closure, binary_vars)
    +
    +    # solve the system of moment ODEs
    +    oprob = ODEProblem(closed_eqs, u₀map, tspan, pmap)
    +    sol = solve(oprob, AutoTsit5(Rosenbrock23()), saveat=0.01)
    +
    +    # μ₀₁ is 2nd and μ₀₂ is 4th element in sol
    +    # can check the order with `closed_eqs.odes.states`
    +    plt_m = plot!(plt_m, sol, idxs=[2], label=closure)
    +    plt_std = plot!(plt_std, sol.t, sqrt.(sol[4, :] .- sol[2, :].^2), label=closure)
    +
    +end
    +
    +plt_m = plot!(plt_m, xlabel="Time [hr]", ylabel="Protein mean level")
    +plt_m = plot!(plt_m, means_ssa.t, means_ssa[2,:], label="SSA", linestyle=:dash, color="gray")
    +plt_std = plot!(plt_std, xlabel="Time [hr]", ylabel="Protein standard deviation")
    +plt_std = plot!(plt_std, vars_ssa.t, sqrt.(vars_ssa[2,:]), label="SSA", linestyle=:dash, color="gray")
    plot(plt_m, lw=2)

    Gene 1 means

    plot(plt_std, lw=2)

    Gene 2 stds

    We observe that the two conditional closures give the most accurate results. Therefore, closing moments conditioned on the gene being active is an effective approximation in this case. Note that our results for normal closure are different from [1], most likely due to the incorrect fifth-order moment closure function given in the paper.

    We now turn to a more complex network involving two genes (two Bernoulli variables), a repressor-activator circuit: an activator protein $Y$ expressed by one gene can turn ON another gene which produces a repressor protein $X$, that subsequently can bind to the gene promoter region of the activator-producing gene turning it OFF (see [1] for more details). As before, $X$ and $Y$ proteins are expressed in geometrically-distributed bursts. The system can be specified as follows:

    @parameters b_x b_y
    +# could redefine in terms of success probabilities p_x and p_y as above
    +m = rand(Distributions.Geometric(1/(1+b_x)))
    +l = rand(Distributions.Geometric(1/(1+b_y)))
    +
    +# g_x - gene state of X protein producing gene
    +# g_y - gene state of Y protein producing gene
    +# x, y - proteins X and Y
    +rn = @reaction_network begin
    +      @parameters kx_on kx_off ky_on ky_off k_x γ_x k_y γ_y
    +      kx_on*(1-g_x)*y, 0 --> g_x  # 0   -> g_x
    +      kx_off,          g_x --> 0  # g_x -> 0
    +      ky_on*(1-g_y),   0 --> g_y  # 0 -> g_y
    +      ky_off*x,        g_y --> 0  # g_y -> 0
    +      k_x*g_x,         0 --> $m*x # 0 -> mx, m ~ Geometric(mean=b_x)
    +      γ_x,             x --> 0    # x -> 0
    +      k_y*g_y,         0 --> $l*y # 0 -> ly, l ~ Geometric(mean_b_y)
    +      γ_y,             y --> 0    # y -> 0
    +end
    +
    +# both g_x and g_y are Bernoulli random variables
    +binary_vars = [1, 2]
    +
    +# Parameter initialisation
    +
    +mean_x = 100
    +mean_y = 100
    +mean_b_x = 5
    +mean_b_y = 5
    +γ_x_val = 1
    +γ_y_val = 1
    +kx_off_val = 4
    +ky_on_val = 0.3
    +kx_on_val = 0.05
    +ky_off_val = 0.05
    +
    +k_x_val = mean_x * γ_x_val * (kx_off_val * mean_y^2 + kx_on_val) / (kx_on_val * mean_b_x)
    +k_y_val = mean_y * γ_y_val * (ky_off_val * mean_x^2 + ky_on_val) / (ky_on_val * mean_b_y)
    +
    +# unclear if Soltani et al. (2015) actually used this parameter set as X numbers
    +# jump to millions making SSA extremely slow...
    +
    +# introduce additional rescaling (otherwise rate coefficients are too high)
    +k_x_val *= 0.00003
    +k_y_val *= 0.01
    +
    +# parameter mapping
    +symmap = [:kx_on => kx_on_val,
    +          :kx_off => kx_off_val,
    +          :ky_on => ky_on_val,
    +          :ky_off => ky_off_val,
    +          :k_x => k_x_val,
    +          :k_y => k_y_val,
    +          :γ_x => γ_x_val,
    +          :γ_y => γ_y_val,
    +          :b_x => mean_b_x,
    +          :b_y => mean_b_y]
    +pmap = symmap_to_varmap(rn, symmap)
    +
    +# initial gene state and protein number, order [g_x, g_y, x, y]
    +u₀ = [1, 1, 1, 1]
    +
    +# time interval to solve on
    +tspan = (0., 12.0)

    Note that here we use a different parameter set from the one considered in [1] as otherwise the number of $X$ proteins goes into millions, making the comparison between closure results difficult due to SSA being extremely slow—it appears that either we have included a mistake setting the parameter values or there is a typo in the paper.

    We can run SSA as follows:

    jsys = convert(JumpSystem, rn, combinatoric_ratelaws=false)
    +dprob = DiscreteProblem(jsys, u₀, tspan, pmap)
    +jprob = JumpProblem(jsys, dprob, Direct(), save_positions=(false, false))
    +
    +ensembleprob  = EnsembleProblem(jprob)
    +@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.1, trajectories=10000)
    +means_ssa, vars_ssa = timeseries_steps_meanvar(sol_SSA)
    13.712331 seconds (43.27 M allocations: 1.697 GiB, 6.56% gc time, 10.01% compilation time)

    We use fourth order moment expansion and apply different closure methods as done for the negative feedback loop, considering the number of activator proteins $Y$ and its standard deviation:

    plt_m = plot()   # plot mean activator protein number
    +plt_std = plot() # plot ssd of activator protein number
    +
    +for closure in ["derivative matching", "conditional derivative matching"]
    +
    +    closed_eqs = moment_closure(eqs, closure, binary_vars)
    +
    +    u₀map = deterministic_IC(u₀, closed_eqs)
    +    oprob = ODEProblem(closed_eqs, u₀map, tspan, pmap)
    +    sol = solve(oprob, Tsit5(), saveat=0.1)
    +
    +    # μ₀₀₀₁ is the 4th and μ₀₀₀₂ is the 12th element in sol (can check with closed_eqs.odes.states)
    +    plt_m = plot!(plt_m, sol, idxs=[4], label=closure)
    +    plt_std = plot!(plt_std, sol.t, sqrt.(sol[12, :] .- sol[4, :].^2), label=closure)
    +end
    +
    +plt_m = plot!(plt_m, xlabel="Time [hr]", ylabel="Activator mean level")
    +plt_m = plot!(plt_m, means_ssa.t, means_ssa[4,:], label="SSA", linestyle=:dash, color="gray")
    +plt_std = plot!(plt_std, xlabel="Time [hr]", ylabel="Activator standard deviation")
    +plt_std = plot!(plt_std, vars_ssa.t, sqrt.(vars_ssa[4,:]), label="SSA", linestyle=:dash, color="gray")

    Note that here we apply only derivative matching and conditional derivative matching, as both normal and conditional gaussian closures failed to be evaluated for the entire time course (irrespective of the solver used). Finally, we can plot the results:

    plot(plt_m, lw=2)

    Gene 2 means

    plot(plt_std, lw=2, xlims=(0., 12.))

    Gene 2 stds

    The trajectories obtained with conditional derivative matching quite accurately match the true dynamics, showing that it is indeed a powerful closure method for reaction networks involving species with very low (binary) copy numbers.

    References

    [1]: M. Soltani, C. A. Vargas-Garcia, and A. Singh, "Conditional Moment Closure Schemes for Studying Stochastic Dynamics of Genetic Circuits", IEEE Transactions on Biomedical Circuits and Systems 9, 518–526 (2015). https://doi.org/10.1109/tbcas.2015.2453158

    [2]: D. Schnoerr, G. Sanguinetti, and R. Grima, "Approximation and inference methods for stochastic biochemical kinetics - a tutorial review", Journal of Physics A: Mathematical and Theoretical 50, 093001 (2017). https://doi.org/10.1088/1751-8121/aa54d9

    diff --git a/dev/tutorials/parameter_estimation_SDE/index.html b/dev/tutorials/parameter_estimation_SDE/index.html index f890fbb..6b206f1 100644 --- a/dev/tutorials/parameter_estimation_SDE/index.html +++ b/dev/tutorials/parameter_estimation_SDE/index.html @@ -1,5 +1,5 @@ -Parameter Estimation of Diffusion Processes · MomentClosure.jl

    Parameter Estimation of Diffusion Processes

    In this tutorial, we look at the problem of model parameter identification of a diffusion process given timeseries data of its moments. Namely, we use moment closure approximations (MAs) to make the optimisation process more efficient by reducing the model evaluation time. All credit for this tutorial goes to Flemming Holtorf!

    We consider a noisy variation of the Lotka-Volterra model, describing the interaction between a predator and prey species:

    \[\begin{align*} +Parameter Estimation of Diffusion Processes · MomentClosure.jl

    Parameter Estimation of Diffusion Processes

    In this tutorial, we look at the problem of model parameter identification of a diffusion process given timeseries data of its moments. Namely, we use moment closure approximations (MAs) to make the optimisation process more efficient by reducing the model evaluation time. All credit for this tutorial goes to Flemming Holtorf!

    We consider a noisy variation of the Lotka-Volterra model, describing the interaction between a predator and prey species:

    \[\begin{align*} \begin{bmatrix} dx \\ dy \end{bmatrix} = \begin{bmatrix} \gamma_1 x(t) - \gamma_2 x(t) y(t) \\ \gamma_4 x(t) y(t) - \gamma_3 y(t) - \frac{1}{2} y(t) \end{bmatrix} \, dt + \begin{bmatrix} \gamma_5 x(t) \\ 0 \end{bmatrix} \, dW_t @@ -125,4 +125,4 @@ plot!(var_comp, t_detail, [m[3] - m[1]^2 for m in opt_sol_approx.u], linewidth = 2, color = :black, linestyle = :dash, label = "log-normal MA") plot!(var_comp, t_detail, [m[5] - m[2]^2 for m in opt_sol_approx.u], linewidth = 2, color = :black, linestyle = :dash, label = nothing) -plot(mean_comp, var_comp, size = (1200.0, 400.0))

    LV SDE fig2

    Finally, note that the parameter estimation is much faster using moment equations (compare to 120 s using the basic approach)

    opt_MCA.time_run
    0.10686397552490234
    +plot(mean_comp, var_comp, size = (1200.0, 400.0))

    LV SDE fig2

    Finally, note that the parameter estimation is much faster using moment equations (compare to 120 s using the basic approach)

    opt_MCA.time_run
    0.10686397552490234
    diff --git a/dev/tutorials/time-dependent_propensities/index.html b/dev/tutorials/time-dependent_propensities/index.html index 7264791..d8de5e4 100644 --- a/dev/tutorials/time-dependent_propensities/index.html +++ b/dev/tutorials/time-dependent_propensities/index.html @@ -1,70 +1,70 @@ -Time-dependent Propensity Functions · MomentClosure.jl

    Time-dependent Propensity Functions

    Here we consider an example of using time-dependent propensities in modelling chemical reaction networks using MomentClosure and DifferentialEquations. Following Schnoerr et al. (2015), we modify the Brusellator introduced earlier to include entrainment:

    \[\begin{align*} -2X + Y &\stackrel{c_1}{\rightarrow} 3X, \\ -X &\stackrel{c_2(t)}{\rightarrow} Y, \\ -∅ &\underset{c_4}{\stackrel{c_3}{\rightleftharpoons}} X. -\end{align*}\]

    The rate constant of the second reaction is now a sinusoidal function of time:

    \[\begin{align*} - c_2(t) &= c_2^0\left(1+\frac{1}{2}\sin(\omega t) \right), \quad \text{if} \; t \leq \tau, \\ - c_2(t) &= c_2^0, \quad \; \text{if} \; t > \tau, -\end{align*}\]

    where $c_2^0$ is a fixed value and the sinusoidal modulation with frequency $\omega$ is switched off after a certain time $\tau$. We can define the model and generate the corresponding moment equations as follows:

    using Catalyst, MomentClosure, Latexify
    -
    -rn = @reaction_network begin
    -  @parameters c₁ c₂ c₃ c₄ Ω ω τ
    -  (c₁/Ω^2), 2X + Y → 3X
    -  (c₂*(1+0.5*sin(ω*(t<τ)*t))), X → Y
    -  (c₃*Ω, c₄), 0 ↔ X
    -end
    -
    -raw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=false)
    -latexify(raw_eqs)

    \[\begin{align*} -\frac{d\mu{_{10}}}{dt} =& c{_3} \Omega + c{_1} \mu{_{21}} \Omega^{-2} - c{_2} \mu{_{10}} - c{_4} \mu{_{10}} - c{_1} \mu{_{11}} \Omega^{-2} - 0.5 c{_2} \mu{_{10}} \sin\left( t \omega \left( t < \tau \right) \right) \\ -\frac{d\mu{_{01}}}{dt} =& c{_2} \mu{_{10}} + c{_1} \mu{_{11}} \Omega^{-2} + 0.5 c{_2} \mu{_{10}} \sin\left( t \omega \left( t < \tau \right) \right) - c{_1} \mu{_{21}} \Omega^{-2} \\ -\frac{d\mu{_{20}}}{dt} =& c{_2} \mu{_{10}} + c{_3} \Omega + c{_4} \mu{_{10}} + 2 c{_1} \mu{_{31}} \Omega^{-2} + 0.5 c{_2} \mu{_{10}} \sin\left( t \omega \left( t < \tau \right) \right) + 2 c{_3} \Omega \mu{_{10}} - 2 c{_2} \mu{_{20}} - 2 c{_4} \mu{_{20}} - c{_1} \mu{_{11}} \Omega^{-2} - c{_1} \mu{_{21}} \Omega^{-2} - c{_2} \mu{_{20}} \sin\left( t \omega \left( t < \tau \right) \right) \\ -\frac{d\mu{_{11}}}{dt} =& c{_2} \mu{_{20}} + c{_1} \mu{_{11}} \Omega^{-2} + c{_1} \mu{_{22}} \Omega^{-2} + c{_3} \Omega \mu{_{01}} + 0.5 c{_2} \mu{_{20}} \sin\left( t \omega \left( t < \tau \right) \right) - c{_2} \mu{_{10}} - c{_2} \mu{_{11}} - c{_4} \mu{_{11}} - c{_1} \mu{_{12}} \Omega^{-2} - c{_1} \mu{_{31}} \Omega^{-2} - 0.5 c{_2} \mu{_{10}} \sin\left( t \omega \left( t < \tau \right) \right) - 0.5 c{_2} \mu{_{11}} \sin\left( t \omega \left( t < \tau \right) \right) \\ -\frac{d\mu{_{02}}}{dt} =& c{_2} \mu{_{10}} + c{_1} \mu{_{21}} \Omega^{-2} + c{_2} \mu{_{11}} \sin\left( t \omega \left( t < \tau \right) \right) + 2 c{_2} \mu{_{11}} + 2 c{_1} \mu{_{12}} \Omega^{-2} + 0.5 c{_2} \mu{_{10}} \sin\left( t \omega \left( t < \tau \right) \right) - c{_1} \mu{_{11}} \Omega^{-2} - 2 c{_1} \mu{_{22}} \Omega^{-2} -\end{align*}\]

    We can now easily close the moment equations using normal closure and solve the resulting system of ODEs:

    using OrdinaryDiffEq, Plots
    -
    -closed_raw_eqs = moment_closure(raw_eqs, "normal")
    -
    -# parameter values [c₁, c₂, c₃, c₄, Ω, ω, τ]
    -p = [0.9, 2., 1., 1., 5., 1., 40.]
    -
    -# initial molecule numbers of species [X, Y]
    -u₀ = [1., 1.]
    -
    -# deterministic initial conditions
    -u₀map = deterministic_IC(u₀, closed_raw_eqs)
    -
    -# time interval to solve one on
    -tspan = (0., 100.)
    -
    -# convert the closed raw moment equations into a DifferentialEquations ODEProblem
    -oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)
    -
    -# solve using Tsit5 solver
    -sol = solve(oprob, Tsit5(), saveat=0.2)
    -plot(sol, idxs=[1,2], lw=2)

    Time-dependent Brusselator normal

    It would be great to compare our results to the true dynamics. Using DifferentialEquations, we can run a modified SSA taking into account the time-dependent propensity functions (VariableRateJumps). This requires some care and is done by combining an ODEProblem with a JumpProblem:

    using JumpProcesses
    -
    -# convert ReactionSystem into JumpSystem
    -jsys = convert(JumpSystem, rn, combinatoric_ratelaws=false)
    -
    -# Define an ODEProblem to integrate between reaction events
    -# note that u₀ elements must be Floats (otherwise throws an error)
    -f(du,u,p,t) = du .= 0
    -oprob = ODEProblem(f, u₀, tspan, p)
    -
    -# Create a modified SSA problem that now correctly incorporates VariableRateJumps
    -jprob = JumpProblem(jsys, oprob, Direct())

    Finally, we can define a corresponding EnsembleProblem to simulate multiple SSA trajectories. However, the saveat argument does not work with VariableRateJumps (a known bug): without it, the solution is saved at each reaction event, in turn generating large data arrays that can get extremely memory-intensive when many trajectories are considered. Our workaround is to simply modify the output_func in EnsembleProblem so that each SSA trajectory is saved to the output array only at the specified timepoints (albeit a lot of garbage collection must be done):

    # timestep at which the solution data is saved
    -dt = 0.2
    -# the corresponding time iterator (0:0.2:100 in our case)
    -ts = tspan[1]:dt:tspan[2]
    -# save data for each trajectory only at the specified timepoints (interpolating the ODESolution)
    -fout = (sol, i) -> (sol(ts), false)
    -ensembleprob  = EnsembleProblem(jprob, output_func=fout)
    -
    -# simulate 10000 SSA trajectories (can get very slow...)
    -@time sol_SSA = solve(ensembleprob, Tsit5(), trajectories=10000)
    2975.249760 seconds (1.07 G allocations: 105.883 GiB, 81.30% gc time, 0.02% compilation time)

    Finally, we can compute the mean SSA trajectories and compare to the moment closure estimates:

    using SciMLBase.EnsembleAnalysis
    -
    -means_SSA = timeseries_steps_mean(sol_SSA)
    -plot!(means_SSA.t, [means_SSA[1,:], means_SSA[2,:]], lw=1.5, labels=["SSA μ₁₀(t)" "SSA μ₀₁(t)"], linestyle=:dash,
    -      linecolor=[1 2], background_color_legend=nothing, legend=:bottomright)

    Time-dependent Brusselator SSA

    +Time-dependent Propensity Functions · MomentClosure.jl

    Time-dependent Propensity Functions

    Here we consider an example of using time-dependent propensities in modelling chemical reaction networks using MomentClosure and DifferentialEquations. Following Schnoerr et al. (2015), we modify the Brusellator introduced earlier to include entrainment:

    \[\begin{align*} +2X + Y &\stackrel{c_1}{\rightarrow} 3X, \\ +X &\stackrel{c_2(t)}{\rightarrow} Y, \\ +∅ &\underset{c_4}{\stackrel{c_3}{\rightleftharpoons}} X. +\end{align*}\]

    The rate constant of the second reaction is now a sinusoidal function of time:

    \[\begin{align*} + c_2(t) &= c_2^0\left(1+\frac{1}{2}\sin(\omega t) \right), \quad \text{if} \; t \leq \tau, \\ + c_2(t) &= c_2^0, \quad \; \text{if} \; t > \tau, +\end{align*}\]

    where $c_2^0$ is a fixed value and the sinusoidal modulation with frequency $\omega$ is switched off after a certain time $\tau$. We can define the model and generate the corresponding moment equations as follows:

    using Catalyst, MomentClosure, Latexify
    +
    +rn = @reaction_network begin
    +  @parameters c₁ c₂ c₃ c₄ Ω ω τ
    +  (c₁/Ω^2), 2X + Y → 3X
    +  (c₂*(1+0.5*sin(ω*(t<τ)*t))), X → Y
    +  (c₃*Ω, c₄), 0 ↔ X
    +end
    +
    +raw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=false)
    +latexify(raw_eqs)

    \[\begin{align*} +\frac{d\mu{_{10}}}{dt} =& c{_3} \Omega + c{_1} \mu{_{21}} \Omega^{-2} - c{_2} \mu{_{10}} - c{_4} \mu{_{10}} - c{_1} \mu{_{11}} \Omega^{-2} - 0.5 c{_2} \mu{_{10}} \sin\left( t \omega \left( t < \tau \right) \right) \\ +\frac{d\mu{_{01}}}{dt} =& c{_2} \mu{_{10}} + c{_1} \mu{_{11}} \Omega^{-2} + 0.5 c{_2} \mu{_{10}} \sin\left( t \omega \left( t < \tau \right) \right) - c{_1} \mu{_{21}} \Omega^{-2} \\ +\frac{d\mu{_{20}}}{dt} =& c{_2} \mu{_{10}} + c{_3} \Omega + c{_4} \mu{_{10}} + 2 c{_1} \mu{_{31}} \Omega^{-2} + 0.5 c{_2} \mu{_{10}} \sin\left( t \omega \left( t < \tau \right) \right) + 2 c{_3} \Omega \mu{_{10}} - 2 c{_2} \mu{_{20}} - 2 c{_4} \mu{_{20}} - c{_1} \mu{_{11}} \Omega^{-2} - c{_1} \mu{_{21}} \Omega^{-2} - c{_2} \mu{_{20}} \sin\left( t \omega \left( t < \tau \right) \right) \\ +\frac{d\mu{_{11}}}{dt} =& c{_2} \mu{_{20}} + c{_1} \mu{_{11}} \Omega^{-2} + c{_1} \mu{_{22}} \Omega^{-2} + c{_3} \Omega \mu{_{01}} + 0.5 c{_2} \mu{_{20}} \sin\left( t \omega \left( t < \tau \right) \right) - c{_2} \mu{_{10}} - c{_2} \mu{_{11}} - c{_4} \mu{_{11}} - c{_1} \mu{_{12}} \Omega^{-2} - c{_1} \mu{_{31}} \Omega^{-2} - 0.5 c{_2} \mu{_{10}} \sin\left( t \omega \left( t < \tau \right) \right) - 0.5 c{_2} \mu{_{11}} \sin\left( t \omega \left( t < \tau \right) \right) \\ +\frac{d\mu{_{02}}}{dt} =& c{_2} \mu{_{10}} + c{_1} \mu{_{21}} \Omega^{-2} + c{_2} \mu{_{11}} \sin\left( t \omega \left( t < \tau \right) \right) + 2 c{_2} \mu{_{11}} + 2 c{_1} \mu{_{12}} \Omega^{-2} + 0.5 c{_2} \mu{_{10}} \sin\left( t \omega \left( t < \tau \right) \right) - c{_1} \mu{_{11}} \Omega^{-2} - 2 c{_1} \mu{_{22}} \Omega^{-2} +\end{align*}\]

    We can now easily close the moment equations using normal closure and solve the resulting system of ODEs:

    using OrdinaryDiffEq, Plots
    +
    +closed_raw_eqs = moment_closure(raw_eqs, "normal")
    +
    +# parameter values [c₁, c₂, c₃, c₄, Ω, ω, τ]
    +p = [0.9, 2., 1., 1., 5., 1., 40.]
    +
    +# initial molecule numbers of species [X, Y]
    +u₀ = [1., 1.]
    +
    +# deterministic initial conditions
    +u₀map = deterministic_IC(u₀, closed_raw_eqs)
    +
    +# time interval to solve one on
    +tspan = (0., 100.)
    +
    +# convert the closed raw moment equations into a DifferentialEquations ODEProblem
    +oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)
    +
    +# solve using Tsit5 solver
    +sol = solve(oprob, Tsit5(), saveat=0.2)
    +plot(sol, idxs=[1,2], lw=2)

    Time-dependent Brusselator normal

    It would be great to compare our results to the true dynamics. Using DifferentialEquations, we can run a modified SSA taking into account the time-dependent propensity functions (VariableRateJumps). This requires some care and is done by combining an ODEProblem with a JumpProblem:

    using JumpProcesses
    +
    +# convert ReactionSystem into JumpSystem
    +jsys = convert(JumpSystem, rn, combinatoric_ratelaws=false)
    +
    +# Define an ODEProblem to integrate between reaction events
    +# note that u₀ elements must be Floats (otherwise throws an error)
    +f(du,u,p,t) = du .= 0
    +oprob = ODEProblem(f, u₀, tspan, p)
    +
    +# Create a modified SSA problem that now correctly incorporates VariableRateJumps
    +jprob = JumpProblem(jsys, oprob, Direct())

    Finally, we can define a corresponding EnsembleProblem to simulate multiple SSA trajectories. However, the saveat argument does not work with VariableRateJumps (a known bug): without it, the solution is saved at each reaction event, in turn generating large data arrays that can get extremely memory-intensive when many trajectories are considered. Our workaround is to simply modify the output_func in EnsembleProblem so that each SSA trajectory is saved to the output array only at the specified timepoints (albeit a lot of garbage collection must be done):

    # timestep at which the solution data is saved
    +dt = 0.2
    +# the corresponding time iterator (0:0.2:100 in our case)
    +ts = tspan[1]:dt:tspan[2]
    +# save data for each trajectory only at the specified timepoints (interpolating the ODESolution)
    +fout = (sol, i) -> (sol(ts), false)
    +ensembleprob  = EnsembleProblem(jprob, output_func=fout)
    +
    +# simulate 10000 SSA trajectories (can get very slow...)
    +@time sol_SSA = solve(ensembleprob, Tsit5(), trajectories=10000)
    2975.249760 seconds (1.07 G allocations: 105.883 GiB, 81.30% gc time, 0.02% compilation time)

    Finally, we can compute the mean SSA trajectories and compare to the moment closure estimates:

    using SciMLBase.EnsembleAnalysis
    +
    +means_SSA = timeseries_steps_mean(sol_SSA)
    +plot!(means_SSA.t, [means_SSA[1,:], means_SSA[2,:]], lw=1.5, labels=["SSA μ₁₀(t)" "SSA μ₀₁(t)"], linestyle=:dash,
    +      linecolor=[1 2], background_color_legend=nothing, legend=:bottomright)

    Time-dependent Brusselator SSA

    diff --git a/dev/tutorials/using_momentclosure/index.html b/dev/tutorials/using_momentclosure/index.html index 4d7dc01..654ba9c 100644 --- a/dev/tutorials/using_momentclosure/index.html +++ b/dev/tutorials/using_momentclosure/index.html @@ -1,80 +1,80 @@ -Using MomentClosure · MomentClosure.jl

    Using MomentClosure

    This tutorial is an introduction to using MomentClosure to define chemical reaction network models, generate the corresponding moment equations, apply moment closure approximations and finally solve the resulting system of ODEs. To demonstrate this functionality, we will consider a specific case of an oscillatory chemical system known as the Brusselator, characterised by the reactions

    \[\begin{align*} -2X + Y &\stackrel{c_1}{\rightarrow} 3X, \\ -X &\stackrel{c_2}{\rightarrow} Y, \\ -∅ &\underset{c_4}{\stackrel{c_3}{\rightleftharpoons}} X. -\end{align*}\]

    We have chosen this particular model to start with as it has been studied with different moment closures before by Schnoerr et al. (2015) and so it is useful as a reference point. The plots of moment trajectories we obtain in this tutorial fully reproduce some of the figures published in the paper, hence (partially) proving the validity of our implementation.

    The terminology and the notation used throughout is consistent with the Theory section of the docs and we advise giving it a skim-through.

    Model Initialisation

    Catalyst.jl provides a comprehensive interface to modelling chemical reaction networks in Julia and can be used to construct models fully-compatible with MomentClosure. For more details on how to do so we recommend reading Catalyst's tutorial. This way, the Brusselator can be defined as:

    using Catalyst
    -rn = @reaction_network begin
    -  # including system-size parameter Ω
    -  @parameters c₁ c₂ c₃ c₄ Ω
    -  (c₁/Ω^2), 2X + Y → 3X
    -  (c₂), X → Y
    -  (c₃*Ω, c₄), 0 ↔ X
    -end

    The returned rn is an instance of ModelingToolkit.ReactionSystem. The net stoichiometry matrix and an array of the corresponding propensities, if needed, can be extracted directly from the model using Catalyst.netstoichmat and MomentClosure function propensities respectively.

    Note that MomentClosure also supports systems containing geometrically distributed reaction products that can be defined using Catalyst—see this tutorial for more details.

    Generating Moment Equations

    We can now obtain the moment equations. The system follows the law of mass action, i.e., all propensity functions are polynomials in molecule numbers $X(t)$ and $Y(t)$, and so we can generate either raw or central moment equations, as described in the Theory section on moment expansion.

    Raw Moment Equations

    Let's start with the raw moment equations which we choose to generate up to second order ($m=2$):

    using MomentClosure
    -raw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=false)

    Note that we have set combinatoric_ratelaw=false in order to ignore the factorial scaling factors which Catalyst adds to mass-action reactions. The function generate_raw_moment_eqs returns an instance of RawMomentEquations that contains a ModelingToolkit.ODESystem composed of all the moment equations (accessed by raw_eqs.odes).

    We can use Latexify to look at the generated moment equations:

    using Latexify
    -latexify(raw_eqs)

    \[\begin{align*} -\frac{d\mu_{1 0}}{dt} =& c_3 \Omega + c_1 \Omega^{-2} \mu_{2 1} - c_2 \mu_{1 0} - c_4 \mu_{1 0} - c_1 \Omega^{-2} \mu_{1 1} \\ -\frac{d\mu_{0 1}}{dt} =& c_2 \mu_{1 0} + c_1 \Omega^{-2} \mu_{1 1} - c_1 \Omega^{-2} \mu_{2 1} \\ -\frac{d\mu_{2 0}}{dt} =& c_2 \mu_{1 0} + c_3 \Omega + c_4 \mu_{1 0} + 2 c_3 \Omega \mu_{1 0} + 2 c_1 \Omega^{-2} \mu_{3 1} - 2 c_2 \mu_{2 0} - 2 c_4 \mu_{2 0} - c_1 \Omega^{-2} \mu_{1 1} - c_1 \Omega^{-2} \mu_{2 1} \\ -\frac{d\mu_{1 1}}{dt} =& c_2 \mu_{2 0} + c_3 \Omega \mu_{0 1} + c_1 \Omega^{-2} \mu_{1 1} + c_1 \Omega^{-2} \mu_{2 2} - c_2 \mu_{1 0} - c_2 \mu_{1 1} - c_4 \mu_{1 1} - c_1 \Omega^{-2} \mu_{1 2} - c_1 \Omega^{-2} \mu_{3 1} \\ -\frac{d\mu_{0 2}}{dt} =& c_2 \mu_{1 0} + 2 c_2 \mu_{1 1} + c_1 \Omega^{-2} \mu_{2 1} + 2 c_1 \Omega^{-2} \mu_{1 2} - c_1 \Omega^{-2} \mu_{1 1} - 2 c_1 \Omega^{-2} \mu_{2 2} -\end{align*}\]

    The raw moments are defined as

    \[\mu_{ij}(t) = \langle X(t)^i Y(t)^j \rangle\]

    where $\langle \rangle$ denote the expectation value and we have explicitly included the time-dependence for completeness (made implicit in the formatted moment equations). Note that the ordering of species ($X$ first and $Y$ second) is consistent with the order these variables appear within the Catalyst.@reaction_network macro. The ordering can also be checked using Catalyst.speciesmap function:

    speciesmap(rn)
    Dict{Term{Real},Int64} with 2 entries:
    -  X(t) => 1
    -  Y(t) => 2

    Coming back to the generated moment equations, we observe that they depend on higher-order moments. For example, the ODE for $\mu_{02}$ depends on third order moments $μ_{12}$ and $μ_{21}$ and the fourth order moment $\mu_{22}$. Consider the general case of raw moment equations: if a network involves reactions that are polynomials (in molecule numbers) of at most order $k$, then its $m^{\text{th}}$ order moment equations will depend on moments up to order $m+k-1$. Hence the relationship seen above is expected as the Brusselator involves a trimolecular reaction whose corresponding propensity function is a third order polynomial in $X(t)$ and $Y(t)$. The number denoting the highest order of moments encountered in the generated RawMomentEquations can also be accessed as raw_eqs.q_order (returning 4 in this case).

    Central Moment Equations

    The corresponding central moment equations can also be easily generated:

    central_eqs = generate_central_moment_eqs(rn, 2, combinatoric_ratelaws=false)

    Note that in case of non-polynomial propensity functions the Taylor expansion order $q$ must also be specified, see the P53 system example for more details. Luckily, the Brusselator contains only mass-action reactions and hence $q$ is automatically determined by the highest order (polynomial) propensity. The function generate_central_moment_eqs returns an instance of CentralMomentEquations. As before, we can visualise the central moment equations:

    latexify(central_eqs)

    \[\begin{align*} -\frac{d\mu_{1 0}}{dt} =& c_3 \Omega + c_1 \Omega^{-2} M_{2 1} + c_1 \Omega^{-2} \mu_{1 0}^{2} \mu_{0 1} + c_1 \Omega^{-2} M_{2 0} \mu_{0 1} + 2 c_1 \Omega^{-2} M_{1 1} \mu_{1 0} - c_2 \mu_{1 0} - c_4 \mu_{1 0} - c_1 \Omega^{-2} M_{1 1} - c_1 \Omega^{-2} \mu_{0 1} \mu_{1 0} \\ -\frac{d\mu_{0 1}}{dt} =& c_2 \mu_{1 0} + c_1 \Omega^{-2} M_{1 1} + c_1 \Omega^{-2} \mu_{0 1} \mu_{1 0} - c_1 \Omega^{-2} M_{2 1} - c_1 \Omega^{-2} \mu_{1 0}^{2} \mu_{0 1} - c_1 \Omega^{-2} M_{2 0} \mu_{0 1} - \frac{2}{1} c_1 \Omega^{-2} M_{1 1} \mu_{1 0} \\ -\frac{dM_{2 0}}{dt} =& c_3 \Omega + c_2 \mu_{1 0} + c_4 \mu_{1 0} + 2 c_1 \Omega^{-2} M_{3 1} + c_1 \Omega^{-2} \mu_{1 0}^{2} \mu_{0 1} + 2 c_1 \Omega^{-2} \mu_{1 0}^{2} M_{1 1} + 2 c_1 \Omega^{-2} M_{3 0} \mu_{0 1} + 4 c_1 \Omega^{-2} M_{2 1} \mu_{1 0} + 4 c_1 \Omega^{-2} M_{2 0} \mu_{0 1} \mu_{1 0} - 2 c_2 M_{2 0} - 2 c_4 M_{2 0} - c_1 \Omega^{-2} M_{1 1} - c_1 \Omega^{-2} M_{2 1} - c_1 \Omega^{-2} M_{2 0} \mu_{0 1} - c_1 \Omega^{-2} \mu_{0 1} \mu_{1 0} \\ -\frac{dM_{1 1}}{dt} =& c_2 M_{2 0} + c_1 \Omega^{-2} M_{1 1} + c_1 \Omega^{-2} M_{2 2} + c_1 \Omega^{-2} \mu_{1 0}^{2} M_{0 2} + c_1 \Omega^{-2} M_{2 1} \mu_{0 1} + c_1 \Omega^{-2} \mu_{0 1} \mu_{1 0} + 2 c_1 \Omega^{-2} M_{1 2} \mu_{1 0} + 2 c_1 \Omega^{-2} M_{1 1} \mu_{0 1} \mu_{1 0} - c_2 M_{1 1} - c_4 M_{1 1} - c_2 \mu_{1 0} - c_1 \Omega^{-2} M_{1 2} - c_1 \Omega^{-2} M_{3 1} - c_1 \Omega^{-2} \mu_{1 0}^{2} M_{1 1} - c_1 \Omega^{-2} \mu_{1 0}^{2} \mu_{0 1} - c_1 \Omega^{-2} M_{0 2} \mu_{1 0} - c_1 \Omega^{-2} M_{1 1} \mu_{0 1} - c_1 \Omega^{-2} M_{3 0} \mu_{0 1} - c_1 \Omega^{-2} M_{1 1} \mu_{1 0} - 2 c_1 \Omega^{-2} M_{2 1} \mu_{1 0} - 2 c_1 \Omega^{-2} M_{2 0} \mu_{0 1} \mu_{1 0} \\ -\frac{dM_{0 2}}{dt} =& c_2 \mu_{1 0} + 2 c_2 M_{1 1} + c_1 \Omega^{-2} M_{2 1} + 2 c_1 \Omega^{-2} M_{1 2} + c_1 \Omega^{-2} \mu_{1 0}^{2} \mu_{0 1} + c_1 \Omega^{-2} M_{2 0} \mu_{0 1} + 2 c_1 \Omega^{-2} M_{0 2} \mu_{1 0} + 2 c_1 \Omega^{-2} M_{1 1} \mu_{0 1} + 2 c_1 \Omega^{-2} M_{1 1} \mu_{1 0} - c_1 \Omega^{-2} M_{1 1} - 2 c_1 \Omega^{-2} M_{2 2} - 2 c_1 \Omega^{-2} \mu_{1 0}^{2} M_{0 2} - c_1 \Omega^{-2} \mu_{0 1} \mu_{1 0} - 2 c_1 \Omega^{-2} M_{2 1} \mu_{0 1} - 4 c_1 \Omega^{-2} M_{1 2} \mu_{1 0} - 4 c_1 \Omega^{-2} M_{1 1} \mu_{0 1} \mu_{1 0} -\end{align*}\]

    Unfortunately, central moment equations often take a visually painful form. Note that the first two ODEs, as before, indicate the means, and the central moments are denoted as

    \[M_{ij}(t) = \langle (X(t)-\mu_{10}(t))^i (Y(t)-\mu_{01}(t))^j \rangle.\]

    Applying Moment Closure

    As observed above, the moment equations of the Brusselator are coupled and depend on higher order moments—we have an infinite hierarchy of ODEs in our hands which cannot be solved directly and requires approximate treatment. One way of approaching the problem is to apply moment closure approximations (MAs), in which higher order moments are expressed as functions of lower order moments, thus effectively truncating the hierarchy and enabling a numerical solution. A variety of MAs have been proposed in literature and are implemented in MomentClosure.jl, see the Theory section on MAs for more details.

    Let's apply normal closure to the raw moment equations raw_eqs we have generated earlier using moment_closure function:

    closed_raw_eqs = moment_closure(raw_eqs, "normal")

    The function returns ClosedMomentEquations that consists of both the ModelingToolkit.ODESystem containing all closed moment equations as well as the specific closure functions for each higher order raw moments. We can use Latexify again to look at the closed ODEs:

    latexify(closed_raw_eqs)

    \[\begin{align*} -\frac{d\mu{_{10}}}{dt} =& c{_3} \Omega + c{_1} \mu{_{01}} \mu{_{20}} \Omega^{-2} + 2 c{_1} \mu{_{10}} \mu{_{11}} \Omega^{-2} - c{_2} \mu{_{10}} - c{_4} \mu{_{10}} - c{_1} \mu{_{11}} \Omega^{-2} - 2 c{_1} \mu{_{01}} \Omega^{-2} \mu{_{10}}^{2} \\ -\frac{d\mu{_{01}}}{dt} =& c{_2} \mu{_{10}} + c{_1} \mu{_{11}} \Omega^{-2} + 2 c{_1} \mu{_{01}} \Omega^{-2} \mu{_{10}}^{2} - c{_1} \mu{_{01}} \mu{_{20}} \Omega^{-2} - 2 c{_1} \mu{_{10}} \mu{_{11}} \Omega^{-2} \\ -\frac{d\mu{_{20}}}{dt} =& c{_2} \mu{_{10}} + c{_3} \Omega + c{_4} \mu{_{10}} + 2 c{_3} \Omega \mu{_{10}} + 2 c{_1} \mu{_{01}} \Omega^{-2} \mu{_{10}}^{2} + 6 c{_1} \mu{_{11}} \mu{_{20}} \Omega^{-2} - 2 c{_2} \mu{_{20}} - 2 c{_4} \mu{_{20}} - c{_1} \mu{_{11}} \Omega^{-2} - c{_1} \mu{_{01}} \mu{_{20}} \Omega^{-2} - 4 c{_1} \mu{_{01}} \Omega^{-2} \mu{_{10}}^{3} - 2 c{_1} \mu{_{10}} \mu{_{11}} \Omega^{-2} \\ -\frac{d\mu{_{11}}}{dt} =& c{_2} \mu{_{20}} + c{_1} \mu{_{11}} \Omega^{-2} + c{_3} \Omega \mu{_{01}} + c{_1} \mu{_{02}} \mu{_{20}} \Omega^{-2} + 2 c{_1} \Omega^{-2} \mu{_{11}}^{2} + 2 c{_1} \mu{_{01}} \Omega^{-2} \mu{_{10}}^{3} + 2 c{_1} \mu{_{10}} \Omega^{-2} \mu{_{01}}^{2} - c{_2} \mu{_{10}} - c{_2} \mu{_{11}} - c{_4} \mu{_{11}} - 2 c{_1} \mu{_{01}} \mu{_{11}} \Omega^{-2} - c{_1} \mu{_{02}} \mu{_{10}} \Omega^{-2} - 3 c{_1} \mu{_{11}} \mu{_{20}} \Omega^{-2} - 2 c{_1} \Omega^{-2} \mu{_{01}}^{2} \mu{_{10}}^{2} \\ -\frac{d\mu{_{02}}}{dt} =& c{_2} \mu{_{10}} + 2 c{_2} \mu{_{11}} + c{_1} \mu{_{01}} \mu{_{20}} \Omega^{-2} + 4 c{_1} \mu{_{01}} \mu{_{11}} \Omega^{-2} + 2 c{_1} \mu{_{02}} \mu{_{10}} \Omega^{-2} + 2 c{_1} \mu{_{10}} \mu{_{11}} \Omega^{-2} + 4 c{_1} \Omega^{-2} \mu{_{01}}^{2} \mu{_{10}}^{2} - c{_1} \mu{_{11}} \Omega^{-2} - 4 c{_1} \Omega^{-2} \mu{_{11}}^{2} - 2 c{_1} \mu{_{01}} \Omega^{-2} \mu{_{10}}^{2} - 2 c{_1} \mu{_{02}} \mu{_{20}} \Omega^{-2} - 4 c{_1} \mu{_{10}} \Omega^{-2} \mu{_{01}}^{2} -\end{align*}\]

    The closure functions can also be displayed by adding :closure argument:

    latexify(closed_raw_eqs, :closure)

    \[\begin{align*} -\mu{_{21}} =& \mu{_{01}} \mu{_{20}} + 2 \mu{_{10}} \mu{_{11}} - 2 \mu{_{01}} \mu{_{10}}^{2} \\ -\mu{_{12}} =& \mu{_{02}} \mu{_{10}} + 2 \mu{_{01}} \mu{_{11}} - 2 \mu{_{10}} \mu{_{01}}^{2} \\ -\mu{_{31}} =& \mu{_{01}} \mu{_{30}} + 6 \mu{_{01}} \mu{_{10}}^{3} + 3 \mu{_{10}} \mu{_{21}} + 3 \mu{_{11}} \mu{_{20}} - 6 \mu{_{11}} \mu{_{10}}^{2} - 6 \mu{_{01}} \mu{_{10}} \mu{_{20}} \\ -\mu{_{22}} =& \mu{_{02}} \mu{_{20}} + 2 \mu{_{11}}^{2} + 2 \mu{_{01}} \mu{_{21}} + 2 \mu{_{10}} \mu{_{12}} + 6 \mu{_{01}}^{2} \mu{_{10}}^{2} - 2 \mu{_{02}} \mu{_{10}}^{2} - 2 \mu{_{20}} \mu{_{01}}^{2} - 8 \mu{_{01}} \mu{_{10}} \mu{_{11}} -\end{align*}\]

    Similarly, we can close central moment equations using

    closed_central_eqs = moment_closure(central_eqs, "normal")

    and print out the corresponding closure functions:

    latexify(closed_central_eqs, :closure)

    \[\begin{align*} -M{_{30}} =& 0 \\ -M{_{21}} =& 0 \\ -M{_{12}} =& 0 \\ -M{_{31}} =& 3 M{_{11}} M{_{20}} \\ -M{_{22}} =& M{_{02}} M{_{20}} + 2 M{_{11}}^{2} -\end{align*}\]

    Higher order central moments under normal closure take a rather simple form compared to their raw moment equivalents. That can be expected due to the relationship between central moments and cumulants, on which the closure is based.

    Solving Moment Equations

    The closed moment equations can be solved numerically using DifferentialEquations.jl that provides a variety of highly-efficient solvers and analysis tools. In order to do so, first we need to specify the values of all system parameters, the initial condition and the timespan to solve over. Then the ModelingToolkit.ODESystem corresponding to the moment equations can be directly converted into an ODEProblem which can finally be solved. Let's go through the procedure step-by-step for the closed raw moment equations (closed_raw_eqs). Most of what is covered below is closely based on this Catalyst tutorial.

    We start with the parameters. Note that they are ordered as they appear after the end statement in the @reaction_network macro and this ordering can also be checked using the paramsmap function:

    paramsmap(rn)
    Dict{Sym{ModelingToolkit.Parameter{Real}},Int64} with 5 entries:
    -  c₃ => 3
    -  Ω  => 5
    -  c₄ => 4
    -  c₂ => 2
    -  c₁ => 1

    We can now create a vector of parameter values as:

    # parameters [c₁, c₂, c₃, c₄, Ω]
    -p = [0.9, 2, 1, 1, 100]

    Next, we can specify the initial condition. Usually when working with moment equations we consider deterministic initial conditions so that the molecule numbers at initial time take the specified integer values with probability one. We can define the initial molecule numbers as $X(t=0) = X_0$ and $Y(t=0) = Y_0$. Probability one implies that initially the means will be equal to the molecule numbers, i.e., $μ_{10}(t=0) = X_0$ and $μ_{01}(t=0) = Y_0$, whereas all higher order raw moments will be products of the corresponding powers of the means, e.g., $μ_{21} = X_0^2 Y_0$. Note that all central moments would be set to zero in this case. To make life easier we use deterministic_IC function which, given the initial molecule numbers, automatically constructs the variable mapping under deterministic initial conditions:

    # initial molecule numbers [X, Y] (order as in speciesmap(rn))
    -u₀ = [1, 1]
    -u₀map = deterministic_IC(u₀, closed_raw_eqs)

    The next ingredient, the time interval to solve on, can be specified simply as:

    tspan = (0., 100.)

    Now we are able to create the corresponding ODEProblem:

    oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)

    Finally, we have everything we need to solve the raw moment equations which can be done using any ODE solver implemented within DifferentialEquations.jl. We use the default Tsit5() solver and then plot the obtained mean molecule numbers:

    # using only ODE solvers from DifferentialEquations (faster to load)
    -using OrdinaryDiffEq
    -sol = solve(oprob, Tsit5(), saveat=0.1)
    -
    -using Plots
    -plot(sol, idxs=[1,2], lw=2)

    Brusselator means 1

    The obtained moment dynamics show damped oscillations which is the expected averaged behaviour of the Brusselator in a vast swathe of parameter space [1]. However, to establish more clearly how well a second order moment expansion with normal moment closure performs for this system and this specific set of parameters, we can compare the resulting moment trajectories to the true moment estimates obtained using Gillespie's Stochastic Simulation Algorithm (SSA).

    Stochastic Simulation

    To run the SSA for a given reaction network, we build a JumpProcesses (formerly known as DiffEqJump) JumpProblem using Gillespie's Direct method. Note that other SSA variants are also available, see the documentation. Moreover, in order to run many realisations of the jump process, we define a corresponding EnsembleProblem. All of this can be done as follows:

    using JumpProcesses
    -
    -# convert ReactionSystem into JumpSystem
    -jsys = convert(JumpSystem, rn, combinatoric_ratelaws=false)
    -
    -# create a DiscreteProblem encoding that the molecule numbers are integer-valued
    -dprob = DiscreteProblem(jsys, u₀, tspan, p) # same parameters as defined earlier
    -
    -# create a JumpProblem: specify Gillespie's Direct Method as the solver
    -# and SET save_positions to (false, false) as otherwise time of each
    -# reaction occurence would be saved (complicating moment estimates)
    -jprob = JumpProblem(jsys, dprob, Direct(), save_positions=(false, false))
    -
    -# define an EnsembleProblem to simulate multiple trajectories
    -ensembleprob = EnsembleProblem(jprob)
    -
    -# simulate 10000 SSA trajectories
    -@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.1, trajectories=10000)

    Now we use the DifferentialEquations ensemble statistics tools to calculate the SSA mean values and plot them:

    using DiffEqBase.EnsembleAnalysis
    -
    -means_SSA = timeseries_steps_mean(sol_SSA)
    -plot!(means_SSA, lw=2, labels=["SSA μ₁₀(t)" "SSA μ₀₁(t)"], linestyle=:dash,
    -      linecolor=[1 2], background_color_legend=nothing, legend=:bottomright)

    Brusselator SSA 1

    The comparison to the SSA reveals that the second-order moment expansion using normal closure captures the correct qualitative behaviour of the Brusselator and provides reasonably accurate moment estimates given this particular parameter set. Note, however, that moment closure approximations can lead to unphysical results and suffer from numerical instabilities, please see the Common Issues tutorial for more details.

    +Using MomentClosure · MomentClosure.jl

    Using MomentClosure

    This tutorial is an introduction to using MomentClosure to define chemical reaction network models, generate the corresponding moment equations, apply moment closure approximations and finally solve the resulting system of ODEs. To demonstrate this functionality, we will consider a specific case of an oscillatory chemical system known as the Brusselator, characterised by the reactions

    \[\begin{align*} +2X + Y &\stackrel{c_1}{\rightarrow} 3X, \\ +X &\stackrel{c_2}{\rightarrow} Y, \\ +∅ &\underset{c_4}{\stackrel{c_3}{\rightleftharpoons}} X. +\end{align*}\]

    We have chosen this particular model to start with as it has been studied with different moment closures before by Schnoerr et al. (2015) and so it is useful as a reference point. The plots of moment trajectories we obtain in this tutorial fully reproduce some of the figures published in the paper, hence (partially) proving the validity of our implementation.

    The terminology and the notation used throughout is consistent with the Theory section of the docs and we advise giving it a skim-through.

    Model Initialisation

    Catalyst.jl provides a comprehensive interface to modelling chemical reaction networks in Julia and can be used to construct models fully-compatible with MomentClosure. For more details on how to do so we recommend reading Catalyst's tutorial. This way, the Brusselator can be defined as:

    using Catalyst
    +rn = @reaction_network begin
    +  # including system-size parameter Ω
    +  @parameters c₁ c₂ c₃ c₄ Ω
    +  (c₁/Ω^2), 2X + Y → 3X
    +  (c₂), X → Y
    +  (c₃*Ω, c₄), 0 ↔ X
    +end

    The returned rn is an instance of ModelingToolkit.ReactionSystem. The net stoichiometry matrix and an array of the corresponding propensities, if needed, can be extracted directly from the model using Catalyst.netstoichmat and MomentClosure function propensities respectively.

    Note that MomentClosure also supports systems containing geometrically distributed reaction products that can be defined using Catalyst—see this tutorial for more details.

    Generating Moment Equations

    We can now obtain the moment equations. The system follows the law of mass action, i.e., all propensity functions are polynomials in molecule numbers $X(t)$ and $Y(t)$, and so we can generate either raw or central moment equations, as described in the Theory section on moment expansion.

    Raw Moment Equations

    Let's start with the raw moment equations which we choose to generate up to second order ($m=2$):

    using MomentClosure
    +raw_eqs = generate_raw_moment_eqs(rn, 2, combinatoric_ratelaws=false)

    Note that we have set combinatoric_ratelaw=false in order to ignore the factorial scaling factors which Catalyst adds to mass-action reactions. The function generate_raw_moment_eqs returns an instance of RawMomentEquations that contains a ModelingToolkit.ODESystem composed of all the moment equations (accessed by raw_eqs.odes).

    We can use Latexify to look at the generated moment equations:

    using Latexify
    +latexify(raw_eqs)

    \[\begin{align*} +\frac{d\mu_{1 0}}{dt} =& c_3 \Omega + c_1 \Omega^{-2} \mu_{2 1} - c_2 \mu_{1 0} - c_4 \mu_{1 0} - c_1 \Omega^{-2} \mu_{1 1} \\ +\frac{d\mu_{0 1}}{dt} =& c_2 \mu_{1 0} + c_1 \Omega^{-2} \mu_{1 1} - c_1 \Omega^{-2} \mu_{2 1} \\ +\frac{d\mu_{2 0}}{dt} =& c_2 \mu_{1 0} + c_3 \Omega + c_4 \mu_{1 0} + 2 c_3 \Omega \mu_{1 0} + 2 c_1 \Omega^{-2} \mu_{3 1} - 2 c_2 \mu_{2 0} - 2 c_4 \mu_{2 0} - c_1 \Omega^{-2} \mu_{1 1} - c_1 \Omega^{-2} \mu_{2 1} \\ +\frac{d\mu_{1 1}}{dt} =& c_2 \mu_{2 0} + c_3 \Omega \mu_{0 1} + c_1 \Omega^{-2} \mu_{1 1} + c_1 \Omega^{-2} \mu_{2 2} - c_2 \mu_{1 0} - c_2 \mu_{1 1} - c_4 \mu_{1 1} - c_1 \Omega^{-2} \mu_{1 2} - c_1 \Omega^{-2} \mu_{3 1} \\ +\frac{d\mu_{0 2}}{dt} =& c_2 \mu_{1 0} + 2 c_2 \mu_{1 1} + c_1 \Omega^{-2} \mu_{2 1} + 2 c_1 \Omega^{-2} \mu_{1 2} - c_1 \Omega^{-2} \mu_{1 1} - 2 c_1 \Omega^{-2} \mu_{2 2} +\end{align*}\]

    The raw moments are defined as

    \[\mu_{ij}(t) = \langle X(t)^i Y(t)^j \rangle\]

    where $\langle \rangle$ denote the expectation value and we have explicitly included the time-dependence for completeness (made implicit in the formatted moment equations). Note that the ordering of species ($X$ first and $Y$ second) is consistent with the order these variables appear within the Catalyst.@reaction_network macro. The ordering can also be checked using Catalyst.speciesmap function:

    speciesmap(rn)
    Dict{Term{Real},Int64} with 2 entries:
    +  X(t) => 1
    +  Y(t) => 2

    Coming back to the generated moment equations, we observe that they depend on higher-order moments. For example, the ODE for $\mu_{02}$ depends on third order moments $μ_{12}$ and $μ_{21}$ and the fourth order moment $\mu_{22}$. Consider the general case of raw moment equations: if a network involves reactions that are polynomials (in molecule numbers) of at most order $k$, then its $m^{\text{th}}$ order moment equations will depend on moments up to order $m+k-1$. Hence the relationship seen above is expected as the Brusselator involves a trimolecular reaction whose corresponding propensity function is a third order polynomial in $X(t)$ and $Y(t)$. The number denoting the highest order of moments encountered in the generated RawMomentEquations can also be accessed as raw_eqs.q_order (returning 4 in this case).

    Central Moment Equations

    The corresponding central moment equations can also be easily generated:

    central_eqs = generate_central_moment_eqs(rn, 2, combinatoric_ratelaws=false)

    Note that in case of non-polynomial propensity functions the Taylor expansion order $q$ must also be specified, see the P53 system example for more details. Luckily, the Brusselator contains only mass-action reactions and hence $q$ is automatically determined by the highest order (polynomial) propensity. The function generate_central_moment_eqs returns an instance of CentralMomentEquations. As before, we can visualise the central moment equations:

    latexify(central_eqs)

    \[\begin{align*} +\frac{d\mu_{1 0}}{dt} =& c_3 \Omega + c_1 \Omega^{-2} M_{2 1} + c_1 \Omega^{-2} \mu_{1 0}^{2} \mu_{0 1} + c_1 \Omega^{-2} M_{2 0} \mu_{0 1} + 2 c_1 \Omega^{-2} M_{1 1} \mu_{1 0} - c_2 \mu_{1 0} - c_4 \mu_{1 0} - c_1 \Omega^{-2} M_{1 1} - c_1 \Omega^{-2} \mu_{0 1} \mu_{1 0} \\ +\frac{d\mu_{0 1}}{dt} =& c_2 \mu_{1 0} + c_1 \Omega^{-2} M_{1 1} + c_1 \Omega^{-2} \mu_{0 1} \mu_{1 0} - c_1 \Omega^{-2} M_{2 1} - c_1 \Omega^{-2} \mu_{1 0}^{2} \mu_{0 1} - c_1 \Omega^{-2} M_{2 0} \mu_{0 1} - \frac{2}{1} c_1 \Omega^{-2} M_{1 1} \mu_{1 0} \\ +\frac{dM_{2 0}}{dt} =& c_3 \Omega + c_2 \mu_{1 0} + c_4 \mu_{1 0} + 2 c_1 \Omega^{-2} M_{3 1} + c_1 \Omega^{-2} \mu_{1 0}^{2} \mu_{0 1} + 2 c_1 \Omega^{-2} \mu_{1 0}^{2} M_{1 1} + 2 c_1 \Omega^{-2} M_{3 0} \mu_{0 1} + 4 c_1 \Omega^{-2} M_{2 1} \mu_{1 0} + 4 c_1 \Omega^{-2} M_{2 0} \mu_{0 1} \mu_{1 0} - 2 c_2 M_{2 0} - 2 c_4 M_{2 0} - c_1 \Omega^{-2} M_{1 1} - c_1 \Omega^{-2} M_{2 1} - c_1 \Omega^{-2} M_{2 0} \mu_{0 1} - c_1 \Omega^{-2} \mu_{0 1} \mu_{1 0} \\ +\frac{dM_{1 1}}{dt} =& c_2 M_{2 0} + c_1 \Omega^{-2} M_{1 1} + c_1 \Omega^{-2} M_{2 2} + c_1 \Omega^{-2} \mu_{1 0}^{2} M_{0 2} + c_1 \Omega^{-2} M_{2 1} \mu_{0 1} + c_1 \Omega^{-2} \mu_{0 1} \mu_{1 0} + 2 c_1 \Omega^{-2} M_{1 2} \mu_{1 0} + 2 c_1 \Omega^{-2} M_{1 1} \mu_{0 1} \mu_{1 0} - c_2 M_{1 1} - c_4 M_{1 1} - c_2 \mu_{1 0} - c_1 \Omega^{-2} M_{1 2} - c_1 \Omega^{-2} M_{3 1} - c_1 \Omega^{-2} \mu_{1 0}^{2} M_{1 1} - c_1 \Omega^{-2} \mu_{1 0}^{2} \mu_{0 1} - c_1 \Omega^{-2} M_{0 2} \mu_{1 0} - c_1 \Omega^{-2} M_{1 1} \mu_{0 1} - c_1 \Omega^{-2} M_{3 0} \mu_{0 1} - c_1 \Omega^{-2} M_{1 1} \mu_{1 0} - 2 c_1 \Omega^{-2} M_{2 1} \mu_{1 0} - 2 c_1 \Omega^{-2} M_{2 0} \mu_{0 1} \mu_{1 0} \\ +\frac{dM_{0 2}}{dt} =& c_2 \mu_{1 0} + 2 c_2 M_{1 1} + c_1 \Omega^{-2} M_{2 1} + 2 c_1 \Omega^{-2} M_{1 2} + c_1 \Omega^{-2} \mu_{1 0}^{2} \mu_{0 1} + c_1 \Omega^{-2} M_{2 0} \mu_{0 1} + 2 c_1 \Omega^{-2} M_{0 2} \mu_{1 0} + 2 c_1 \Omega^{-2} M_{1 1} \mu_{0 1} + 2 c_1 \Omega^{-2} M_{1 1} \mu_{1 0} - c_1 \Omega^{-2} M_{1 1} - 2 c_1 \Omega^{-2} M_{2 2} - 2 c_1 \Omega^{-2} \mu_{1 0}^{2} M_{0 2} - c_1 \Omega^{-2} \mu_{0 1} \mu_{1 0} - 2 c_1 \Omega^{-2} M_{2 1} \mu_{0 1} - 4 c_1 \Omega^{-2} M_{1 2} \mu_{1 0} - 4 c_1 \Omega^{-2} M_{1 1} \mu_{0 1} \mu_{1 0} +\end{align*}\]

    Unfortunately, central moment equations often take a visually painful form. Note that the first two ODEs, as before, indicate the means, and the central moments are denoted as

    \[M_{ij}(t) = \langle (X(t)-\mu_{10}(t))^i (Y(t)-\mu_{01}(t))^j \rangle.\]

    Applying Moment Closure

    As observed above, the moment equations of the Brusselator are coupled and depend on higher order moments—we have an infinite hierarchy of ODEs in our hands which cannot be solved directly and requires approximate treatment. One way of approaching the problem is to apply moment closure approximations (MAs), in which higher order moments are expressed as functions of lower order moments, thus effectively truncating the hierarchy and enabling a numerical solution. A variety of MAs have been proposed in literature and are implemented in MomentClosure.jl, see the Theory section on MAs for more details.

    Let's apply normal closure to the raw moment equations raw_eqs we have generated earlier using moment_closure function:

    closed_raw_eqs = moment_closure(raw_eqs, "normal")

    The function returns ClosedMomentEquations that consists of both the ModelingToolkit.ODESystem containing all closed moment equations as well as the specific closure functions for each higher order raw moments. We can use Latexify again to look at the closed ODEs:

    latexify(closed_raw_eqs)

    \[\begin{align*} +\frac{d\mu{_{10}}}{dt} =& c{_3} \Omega + c{_1} \mu{_{01}} \mu{_{20}} \Omega^{-2} + 2 c{_1} \mu{_{10}} \mu{_{11}} \Omega^{-2} - c{_2} \mu{_{10}} - c{_4} \mu{_{10}} - c{_1} \mu{_{11}} \Omega^{-2} - 2 c{_1} \mu{_{01}} \Omega^{-2} \mu{_{10}}^{2} \\ +\frac{d\mu{_{01}}}{dt} =& c{_2} \mu{_{10}} + c{_1} \mu{_{11}} \Omega^{-2} + 2 c{_1} \mu{_{01}} \Omega^{-2} \mu{_{10}}^{2} - c{_1} \mu{_{01}} \mu{_{20}} \Omega^{-2} - 2 c{_1} \mu{_{10}} \mu{_{11}} \Omega^{-2} \\ +\frac{d\mu{_{20}}}{dt} =& c{_2} \mu{_{10}} + c{_3} \Omega + c{_4} \mu{_{10}} + 2 c{_3} \Omega \mu{_{10}} + 2 c{_1} \mu{_{01}} \Omega^{-2} \mu{_{10}}^{2} + 6 c{_1} \mu{_{11}} \mu{_{20}} \Omega^{-2} - 2 c{_2} \mu{_{20}} - 2 c{_4} \mu{_{20}} - c{_1} \mu{_{11}} \Omega^{-2} - c{_1} \mu{_{01}} \mu{_{20}} \Omega^{-2} - 4 c{_1} \mu{_{01}} \Omega^{-2} \mu{_{10}}^{3} - 2 c{_1} \mu{_{10}} \mu{_{11}} \Omega^{-2} \\ +\frac{d\mu{_{11}}}{dt} =& c{_2} \mu{_{20}} + c{_1} \mu{_{11}} \Omega^{-2} + c{_3} \Omega \mu{_{01}} + c{_1} \mu{_{02}} \mu{_{20}} \Omega^{-2} + 2 c{_1} \Omega^{-2} \mu{_{11}}^{2} + 2 c{_1} \mu{_{01}} \Omega^{-2} \mu{_{10}}^{3} + 2 c{_1} \mu{_{10}} \Omega^{-2} \mu{_{01}}^{2} - c{_2} \mu{_{10}} - c{_2} \mu{_{11}} - c{_4} \mu{_{11}} - 2 c{_1} \mu{_{01}} \mu{_{11}} \Omega^{-2} - c{_1} \mu{_{02}} \mu{_{10}} \Omega^{-2} - 3 c{_1} \mu{_{11}} \mu{_{20}} \Omega^{-2} - 2 c{_1} \Omega^{-2} \mu{_{01}}^{2} \mu{_{10}}^{2} \\ +\frac{d\mu{_{02}}}{dt} =& c{_2} \mu{_{10}} + 2 c{_2} \mu{_{11}} + c{_1} \mu{_{01}} \mu{_{20}} \Omega^{-2} + 4 c{_1} \mu{_{01}} \mu{_{11}} \Omega^{-2} + 2 c{_1} \mu{_{02}} \mu{_{10}} \Omega^{-2} + 2 c{_1} \mu{_{10}} \mu{_{11}} \Omega^{-2} + 4 c{_1} \Omega^{-2} \mu{_{01}}^{2} \mu{_{10}}^{2} - c{_1} \mu{_{11}} \Omega^{-2} - 4 c{_1} \Omega^{-2} \mu{_{11}}^{2} - 2 c{_1} \mu{_{01}} \Omega^{-2} \mu{_{10}}^{2} - 2 c{_1} \mu{_{02}} \mu{_{20}} \Omega^{-2} - 4 c{_1} \mu{_{10}} \Omega^{-2} \mu{_{01}}^{2} +\end{align*}\]

    The closure functions can also be displayed by adding :closure argument:

    latexify(closed_raw_eqs, :closure)

    \[\begin{align*} +\mu{_{21}} =& \mu{_{01}} \mu{_{20}} + 2 \mu{_{10}} \mu{_{11}} - 2 \mu{_{01}} \mu{_{10}}^{2} \\ +\mu{_{12}} =& \mu{_{02}} \mu{_{10}} + 2 \mu{_{01}} \mu{_{11}} - 2 \mu{_{10}} \mu{_{01}}^{2} \\ +\mu{_{31}} =& \mu{_{01}} \mu{_{30}} + 6 \mu{_{01}} \mu{_{10}}^{3} + 3 \mu{_{10}} \mu{_{21}} + 3 \mu{_{11}} \mu{_{20}} - 6 \mu{_{11}} \mu{_{10}}^{2} - 6 \mu{_{01}} \mu{_{10}} \mu{_{20}} \\ +\mu{_{22}} =& \mu{_{02}} \mu{_{20}} + 2 \mu{_{11}}^{2} + 2 \mu{_{01}} \mu{_{21}} + 2 \mu{_{10}} \mu{_{12}} + 6 \mu{_{01}}^{2} \mu{_{10}}^{2} - 2 \mu{_{02}} \mu{_{10}}^{2} - 2 \mu{_{20}} \mu{_{01}}^{2} - 8 \mu{_{01}} \mu{_{10}} \mu{_{11}} +\end{align*}\]

    Similarly, we can close central moment equations using

    closed_central_eqs = moment_closure(central_eqs, "normal")

    and print out the corresponding closure functions:

    latexify(closed_central_eqs, :closure)

    \[\begin{align*} +M{_{30}} =& 0 \\ +M{_{21}} =& 0 \\ +M{_{12}} =& 0 \\ +M{_{31}} =& 3 M{_{11}} M{_{20}} \\ +M{_{22}} =& M{_{02}} M{_{20}} + 2 M{_{11}}^{2} +\end{align*}\]

    Higher order central moments under normal closure take a rather simple form compared to their raw moment equivalents. That can be expected due to the relationship between central moments and cumulants, on which the closure is based.

    Solving Moment Equations

    The closed moment equations can be solved numerically using DifferentialEquations.jl that provides a variety of highly-efficient solvers and analysis tools. In order to do so, first we need to specify the values of all system parameters, the initial condition and the timespan to solve over. Then the ModelingToolkit.ODESystem corresponding to the moment equations can be directly converted into an ODEProblem which can finally be solved. Let's go through the procedure step-by-step for the closed raw moment equations (closed_raw_eqs). Most of what is covered below is closely based on this Catalyst tutorial.

    We start with the parameters. Note that they are ordered as they appear after the end statement in the @reaction_network macro and this ordering can also be checked using the paramsmap function:

    paramsmap(rn)
    Dict{Sym{ModelingToolkit.Parameter{Real}},Int64} with 5 entries:
    +  c₃ => 3
    +  Ω  => 5
    +  c₄ => 4
    +  c₂ => 2
    +  c₁ => 1

    We can now create a vector of parameter values as:

    # parameters [c₁, c₂, c₃, c₄, Ω]
    +p = [0.9, 2, 1, 1, 100]

    Next, we can specify the initial condition. Usually when working with moment equations we consider deterministic initial conditions so that the molecule numbers at initial time take the specified integer values with probability one. We can define the initial molecule numbers as $X(t=0) = X_0$ and $Y(t=0) = Y_0$. Probability one implies that initially the means will be equal to the molecule numbers, i.e., $μ_{10}(t=0) = X_0$ and $μ_{01}(t=0) = Y_0$, whereas all higher order raw moments will be products of the corresponding powers of the means, e.g., $μ_{21} = X_0^2 Y_0$. Note that all central moments would be set to zero in this case. To make life easier we use deterministic_IC function which, given the initial molecule numbers, automatically constructs the variable mapping under deterministic initial conditions:

    # initial molecule numbers [X, Y] (order as in speciesmap(rn))
    +u₀ = [1, 1]
    +u₀map = deterministic_IC(u₀, closed_raw_eqs)

    The next ingredient, the time interval to solve on, can be specified simply as:

    tspan = (0., 100.)

    Now we are able to create the corresponding ODEProblem:

    oprob = ODEProblem(closed_raw_eqs, u₀map, tspan, p)

    Finally, we have everything we need to solve the raw moment equations which can be done using any ODE solver implemented within DifferentialEquations.jl. We use the default Tsit5() solver and then plot the obtained mean molecule numbers:

    # using only ODE solvers from DifferentialEquations (faster to load)
    +using OrdinaryDiffEq
    +sol = solve(oprob, Tsit5(), saveat=0.1)
    +
    +using Plots
    +plot(sol, idxs=[1,2], lw=2)

    Brusselator means 1

    The obtained moment dynamics show damped oscillations which is the expected averaged behaviour of the Brusselator in a vast swathe of parameter space [1]. However, to establish more clearly how well a second order moment expansion with normal moment closure performs for this system and this specific set of parameters, we can compare the resulting moment trajectories to the true moment estimates obtained using Gillespie's Stochastic Simulation Algorithm (SSA).

    Stochastic Simulation

    To run the SSA for a given reaction network, we build a JumpProcesses (formerly known as DiffEqJump) JumpProblem using Gillespie's Direct method. Note that other SSA variants are also available, see the documentation. Moreover, in order to run many realisations of the jump process, we define a corresponding EnsembleProblem. All of this can be done as follows:

    using JumpProcesses
    +
    +# convert ReactionSystem into JumpSystem
    +jsys = convert(JumpSystem, rn, combinatoric_ratelaws=false)
    +
    +# create a DiscreteProblem encoding that the molecule numbers are integer-valued
    +dprob = DiscreteProblem(jsys, u₀, tspan, p) # same parameters as defined earlier
    +
    +# create a JumpProblem: specify Gillespie's Direct Method as the solver
    +# and SET save_positions to (false, false) as otherwise time of each
    +# reaction occurence would be saved (complicating moment estimates)
    +jprob = JumpProblem(jsys, dprob, Direct(), save_positions=(false, false))
    +
    +# define an EnsembleProblem to simulate multiple trajectories
    +ensembleprob = EnsembleProblem(jprob)
    +
    +# simulate 10000 SSA trajectories
    +@time sol_SSA = solve(ensembleprob, SSAStepper(), saveat=0.1, trajectories=10000)

    Now we use the DifferentialEquations ensemble statistics tools to calculate the SSA mean values and plot them:

    using DiffEqBase.EnsembleAnalysis
    +
    +means_SSA = timeseries_steps_mean(sol_SSA)
    +plot!(means_SSA, lw=2, labels=["SSA μ₁₀(t)" "SSA μ₀₁(t)"], linestyle=:dash,
    +      linecolor=[1 2], background_color_legend=nothing, legend=:bottomright)

    Brusselator SSA 1

    The comparison to the SSA reveals that the second-order moment expansion using normal closure captures the correct qualitative behaviour of the Brusselator and provides reasonably accurate moment estimates given this particular parameter set. Note, however, that moment closure approximations can lead to unphysical results and suffer from numerical instabilities, please see the Common Issues tutorial for more details.

    diff --git a/dev/tutorials/using_momentclosure_SDE/index.html b/dev/tutorials/using_momentclosure_SDE/index.html index 97ab880..54da1a4 100644 --- a/dev/tutorials/using_momentclosure_SDE/index.html +++ b/dev/tutorials/using_momentclosure_SDE/index.html @@ -1,78 +1,78 @@ -Moment Equations from SDEs · MomentClosure.jl

    Moment Equations from SDEs

    In the previous tutorial, we have shown how to generate and close moment equations for chemical reaction networks. Similarly, MomentClosure can be applied to systems of stochastic differential equations (SDEs) and here we demonstrate this functionality by working through a couple of practical examples. Namely, we consider two specific models from a relevant paper by Ghusinga et al. (2017) [1], 1) the Van der Pol oscillator and 2) a swinging pendulum, and apply moment closure approximations (MA) to reproduce some of the published results. For the theory behind the SDE moment expansion see here.

    Model 1

    The deterministic Van der Pol oscillator is described by [1]:

    \[\begin{align*} - \frac{d^2 x}{dt^2} - \epsilon(1-x^2)\frac{dx}{dt} + \omega_n^2 x = A\cos(\omega_g t), -\end{align*}\]

    where $\epsilon$ is the bifurcation parameter, $\omega_n$ the natural frequency, $\omega_g$ the force frequency and $A$ the force amplitude. We formulate a stochastic equivalent of this system by assuming that the force is noisy and taking $x_1 = x$ and $x_2 = \frac{dx}{dt}$, so that

    \[\begin{align*} - dx_1 &= x_2 dt, \\ - dx_2 &= \left( \epsilon(1-x_1^2) x_2 - \omega_n^2 x_1 \right)dt + A\cos(\omega_g t)dt + A dw_t. -\end{align*}\]

    In Julia, systems of SDEs can be conveniently described using ModelingToolkit.jl that provides an SDESystem type. Defining such models is straightforward (as in this example) and in our case is done as follows:

    using ModelingToolkit
    -
    -@variables t, x₁(t), x₂(t)
    -@parameters ϵ, ω_n, ω_g, A
    -
    -drift_eqs = [Differential(t)(x₁) ~ x₂;
    -             Differential(t)(x₂) ~ ϵ*(1-x₁^2)*x₂ - ω_n^2*x₁ + A*cos(ω_g*t)]
    -diff_eqs = [0; A]
    -
    -vdp_model = SDESystem(drift_eqs, diff_eqs, t, [x₁, x₂], [ϵ, ω_n, ω_g, A], name = :VdP)
    -
    -ps = [ϵ => 0.1, ω_n => 120*pi, ω_g => 120*pi, A => 2.5] # parameter values
    -u0 = [0.1, 0.1]   # initial conditions
    -tspan = (0., 0.1) # simulation time limit

    We can now easily extract the raw moment equations up to second order using MomentClosure

    using MomentClosure, Latexify
    -
    -moment_eqs = generate_raw_moment_eqs(vdp_model, 2) 
    -latexify(moment_eqs)

    \[\begin{align*} -\frac{d\mu{_{10}}}{dt} =& \mu{_{01}} \\ -\frac{d\mu{_{01}}}{dt} =& A \cos\left( t \omega_{g} \right) + \epsilon \mu{_{01}} - \epsilon \mu{_{21}} - \omega_{n}^{2} \mu{_{10}} \\ -\frac{d\mu{_{20}}}{dt} =& 2 \mu{_{11}} \\ -\frac{d\mu{_{11}}}{dt} =& \epsilon \mu{_{11}} + A \mu{_{10}} \cos\left( t \omega_{g} \right) + \mu{_{02}} - \epsilon \mu{_{31}} - \omega_{n}^{2} \mu{_{20}} \\ -\frac{d\mu{_{02}}}{dt} =& A^{2} + 2 \epsilon \mu{_{02}} + 2 A \mu{_{01}} \cos\left( t \omega_{g} \right) - 2 \omega_{n}^{2} \mu{_{11}} - 2 \epsilon \mu{_{22}} -\end{align*}\]

    The obtained moment equations are equivalent to the published ones (except for a single term in $\mu_{11}$ equation as there is a typo in the paper), giving some confidence that everything works as intended!

    Note that the moment equations are not closed as there are two fourth order moments involved, $\mu_{31}$ and $\mu_{22}$, and hence we need to resort to MAs. We proceed to apply the derivative matching approximation and solve the system of ODEs as follows:

    using DifferentialEquations
    -
    -closed_eqs = moment_closure(moment_eqs, "derivative matching")
    -
    -u0map = deterministic_IC(u0, closed_eqs)
    -oprob = ODEProblem(closed_eqs, u0map, tspan, ps)
    -
    -sol_MA = solve(oprob, Tsit5(), saveat=0.0001)

    Finally, we can also use DifferentialEquations to solve the SDEs for many trajectories and compare the ensemble statistics to the derivative matching approximation (getting a great match):

    using DifferentialEquations.EnsembleAnalysis, Plots
    -
    -prob_SDE = SDEProblem(vdp_model, u0, tspan, ps)
    -@time sol_SDE = solve(EnsembleProblem(prob_SDE), SRIW1(), saveat=0.0001, trajectories=100)
    -means_SDE = timeseries_steps_mean(sol_SDE)
    -
    -plot(sol_MA.t, sol_MA[1, :], lw=2, label="MA", ylabel="⟨x₁⟩", xlabel="time")
    -plot!(sol_MA.t, means_SDE[1, :], lw=2, label="SDE", linecolor=:red,
    -      linestyle=:dash, background_color_legend=nothing, legend=:topright, grid=false)

    Model 1 SDE

    Model 2

    We next consider a simple pendulum, deterministically described as [1]

    \[\begin{align*} - \frac{d^2\theta}{dt^2} + \frac{k}{m}\frac{d\theta}{dt} + \frac{g}{l} \sin{\theta} = 0, -\end{align*}\]

    where $\theta$ is the angular displacement, $m$ the mass of the pendulum, $g$ the gravitational acceleration constant, $l$ the pendulum length and $k$ the friction constant. The stochasticity is modelled as a white noise term arising due to pendulum randomly interacting with air molecules (assumed to be inversely proportional to $m$). Letting $x_1 = \theta$ and $x_2 = \frac{d\theta}{dt}$ we write down the SDE as:

    \[\begin{align*} - dx_1 &= x_2 dt, \\ - dx_2 &= \left( -\frac{k}{m}x_2 - \frac{g}{l}\sin{x_1} \right)dt + \frac{1}{m}dw_t. -\end{align*}\]

    Using ModelingToolkit again we can define the model as

    @variables t, x₁(t), x₂(t)
    -@parameters k, l, m, g
    -
    -drift_eqs = [Differential(t)(x₁) ~ x₂;
    -             Differential(t)(x₂) ~ -k/m*x₂ - g/l*sin(x₁)]
    -diff_eqs = [0; 1/m]
    -
    -pendulum_model = SDESystem(drift_eqs, diff_eqs, t, [x₁, x₂], [k, l, m, g], name = :pendulum)
    -ps = [k => 10, m => 10, l => 10, g => 10]
    -u0 = [3, 3]
    -tspan = (0., 15.)

    As the drift term is non-polynomial, we can no longer write down the raw moment equations in a straightforward manner. Nevertheless, we can expand the expressions up to a certain Taylor expansion order $q$ and generate the corresponding time-evolution equations for the means and higher order central moments—this situation is identical to moment expansion for chemical reaction networks with non-polynomial propensities. Hence we can obtain the equations for the means and variances with $q=3$:

    moment_eqs = generate_central_moment_eqs(pendulum_model, 2, 3) 
    -latexify(moment_eqs) # the output here is maybe not the most visually pleasing

    \[\begin{align*} -\frac{d\mu{_{10}}}{dt} =& \mu{_{01}} \\ -\frac{d\mu{_{01}}}{dt} =& \frac{\left( - k \right) \mu{_{01}}}{m} + \frac{\left( - g \right) \sin\left( \mu{_{10}} \right)}{l} + \frac{\frac{1}{6} g M{_{30}} \cos\left( \mu{_{10}} \right)}{l} + \frac{\frac{1}{2} g M{_{20}} \sin\left( \mu{_{10}} \right)}{l} \\ -\frac{dM{_{20}}}{dt} =& 2 M{_{11}} \\ -\frac{dM{_{11}}}{dt} =& \frac{\left( - k \right) M{_{11}}}{m} + \frac{\left( - g \right) M{_{20}} \cos\left( \mu{_{10}} \right)}{l} + \frac{\frac{1}{2} g M{_{30}} \sin\left( \mu{_{10}} \right)}{l} + M{_{02}} \\ -\frac{dM{_{02}}}{dt} =& \frac{\frac{1}{1}}{m^{2}} + \frac{-2 k M{_{02}}}{m} + \frac{g M{_{21}} \sin\left( \mu{_{10}} \right)}{l} + \frac{-2 g M{_{11}} \cos\left( \mu{_{10}} \right)}{l} -\end{align*}\]

    We can now approximate the moment equations using gamma closure, solve the ODEs numerically and compare the predictions to true SDE solution, finding good agreement:

    closed_eqs = moment_closure(moment_eqs, "gamma")
    -
    -u0map = deterministic_IC(u0, closed_eqs)
    -oprob = ODEProblem(closed_eqs, u0map, tspan, ps)
    -sol_MA = solve(oprob, Tsit5(), saveat=0.01)
    -
    -prob_SDE = SDEProblem(pendulum_model, u0, tspan, ps)
    -sol_SDE = solve(EnsembleProblem(prob_SDE), SRIW1(), saveat=0.01, trajectories=100)
    -means_SDE = timeseries_steps_mean(sol_SDE)
    -
    -plot(sol_MA.t, sin.(sol_MA[1, :]), lw=2, label="MA", ylabel="sin(⟨x₁⟩)", xlabel="time")
    -plot!(sol_MA.t, sin.(means_SDE[1, :]), lw=2, label="SDE", linecolor=:red,
    -    linestyle=:dash, background_color_legend=nothing, legend=:topright, grid=false)

    Model 2 SDE

    References

    [1]: K. R. Ghusinga, M. Soltani, A. Lamperski, S. V. Dhople, and A. Singh, "Approximate moment dynamics for polynomial and trigonometric stochastic systems", IEEE 56th Annual Conference on Decision and Control (2017). https://doi.org/10.1109/CDC.2017.8263922

    +Moment Equations from SDEs · MomentClosure.jl

    Moment Equations from SDEs

    In the previous tutorial, we have shown how to generate and close moment equations for chemical reaction networks. Similarly, MomentClosure can be applied to systems of stochastic differential equations (SDEs) and here we demonstrate this functionality by working through a couple of practical examples. Namely, we consider two specific models from a relevant paper by Ghusinga et al. (2017) [1], 1) the Van der Pol oscillator and 2) a swinging pendulum, and apply moment closure approximations (MA) to reproduce some of the published results. For the theory behind the SDE moment expansion see here.

    Model 1

    The deterministic Van der Pol oscillator is described by [1]:

    \[\begin{align*} + \frac{d^2 x}{dt^2} - \epsilon(1-x^2)\frac{dx}{dt} + \omega_n^2 x = A\cos(\omega_g t), +\end{align*}\]

    where $\epsilon$ is the bifurcation parameter, $\omega_n$ the natural frequency, $\omega_g$ the force frequency and $A$ the force amplitude. We formulate a stochastic equivalent of this system by assuming that the force is noisy and taking $x_1 = x$ and $x_2 = \frac{dx}{dt}$, so that

    \[\begin{align*} + dx_1 &= x_2 dt, \\ + dx_2 &= \left( \epsilon(1-x_1^2) x_2 - \omega_n^2 x_1 \right)dt + A\cos(\omega_g t)dt + A dw_t. +\end{align*}\]

    In Julia, systems of SDEs can be conveniently described using ModelingToolkit.jl that provides an SDESystem type. Defining such models is straightforward (as in this example) and in our case is done as follows:

    using ModelingToolkit
    +
    +@variables t, x₁(t), x₂(t)
    +@parameters ϵ, ω_n, ω_g, A
    +
    +drift_eqs = [Differential(t)(x₁) ~ x₂;
    +             Differential(t)(x₂) ~ ϵ*(1-x₁^2)*x₂ - ω_n^2*x₁ + A*cos(ω_g*t)]
    +diff_eqs = [0; A]
    +
    +vdp_model = SDESystem(drift_eqs, diff_eqs, t, [x₁, x₂], [ϵ, ω_n, ω_g, A], name = :VdP)
    +
    +ps = [ϵ => 0.1, ω_n => 120*pi, ω_g => 120*pi, A => 2.5] # parameter values
    +u0 = [0.1, 0.1]   # initial conditions
    +tspan = (0., 0.1) # simulation time limit

    We can now easily extract the raw moment equations up to second order using MomentClosure

    using MomentClosure, Latexify
    +
    +moment_eqs = generate_raw_moment_eqs(vdp_model, 2) 
    +latexify(moment_eqs)

    \[\begin{align*} +\frac{d\mu{_{10}}}{dt} =& \mu{_{01}} \\ +\frac{d\mu{_{01}}}{dt} =& A \cos\left( t \omega_{g} \right) + \epsilon \mu{_{01}} - \epsilon \mu{_{21}} - \omega_{n}^{2} \mu{_{10}} \\ +\frac{d\mu{_{20}}}{dt} =& 2 \mu{_{11}} \\ +\frac{d\mu{_{11}}}{dt} =& \epsilon \mu{_{11}} + A \mu{_{10}} \cos\left( t \omega_{g} \right) + \mu{_{02}} - \epsilon \mu{_{31}} - \omega_{n}^{2} \mu{_{20}} \\ +\frac{d\mu{_{02}}}{dt} =& A^{2} + 2 \epsilon \mu{_{02}} + 2 A \mu{_{01}} \cos\left( t \omega_{g} \right) - 2 \omega_{n}^{2} \mu{_{11}} - 2 \epsilon \mu{_{22}} +\end{align*}\]

    The obtained moment equations are equivalent to the published ones (except for a single term in $\mu_{11}$ equation as there is a typo in the paper), giving some confidence that everything works as intended!

    Note that the moment equations are not closed as there are two fourth order moments involved, $\mu_{31}$ and $\mu_{22}$, and hence we need to resort to MAs. We proceed to apply the derivative matching approximation and solve the system of ODEs as follows:

    using DifferentialEquations
    +
    +closed_eqs = moment_closure(moment_eqs, "derivative matching")
    +
    +u0map = deterministic_IC(u0, closed_eqs)
    +oprob = ODEProblem(closed_eqs, u0map, tspan, ps)
    +
    +sol_MA = solve(oprob, Tsit5(), saveat=0.0001)

    Finally, we can also use DifferentialEquations to solve the SDEs for many trajectories and compare the ensemble statistics to the derivative matching approximation (getting a great match):

    using DifferentialEquations.EnsembleAnalysis, Plots
    +
    +prob_SDE = SDEProblem(vdp_model, u0, tspan, ps)
    +@time sol_SDE = solve(EnsembleProblem(prob_SDE), SRIW1(), saveat=0.0001, trajectories=100)
    +means_SDE = timeseries_steps_mean(sol_SDE)
    +
    +plot(sol_MA.t, sol_MA[1, :], lw=2, label="MA", ylabel="⟨x₁⟩", xlabel="time")
    +plot!(sol_MA.t, means_SDE[1, :], lw=2, label="SDE", linecolor=:red,
    +      linestyle=:dash, background_color_legend=nothing, legend=:topright, grid=false)

    Model 1 SDE

    Model 2

    We next consider a simple pendulum, deterministically described as [1]

    \[\begin{align*} + \frac{d^2\theta}{dt^2} + \frac{k}{m}\frac{d\theta}{dt} + \frac{g}{l} \sin{\theta} = 0, +\end{align*}\]

    where $\theta$ is the angular displacement, $m$ the mass of the pendulum, $g$ the gravitational acceleration constant, $l$ the pendulum length and $k$ the friction constant. The stochasticity is modelled as a white noise term arising due to pendulum randomly interacting with air molecules (assumed to be inversely proportional to $m$). Letting $x_1 = \theta$ and $x_2 = \frac{d\theta}{dt}$ we write down the SDE as:

    \[\begin{align*} + dx_1 &= x_2 dt, \\ + dx_2 &= \left( -\frac{k}{m}x_2 - \frac{g}{l}\sin{x_1} \right)dt + \frac{1}{m}dw_t. +\end{align*}\]

    Using ModelingToolkit again we can define the model as

    @variables t, x₁(t), x₂(t)
    +@parameters k, l, m, g
    +
    +drift_eqs = [Differential(t)(x₁) ~ x₂;
    +             Differential(t)(x₂) ~ -k/m*x₂ - g/l*sin(x₁)]
    +diff_eqs = [0; 1/m]
    +
    +pendulum_model = SDESystem(drift_eqs, diff_eqs, t, [x₁, x₂], [k, l, m, g], name = :pendulum)
    +ps = [k => 10, m => 10, l => 10, g => 10]
    +u0 = [3, 3]
    +tspan = (0., 15.)

    As the drift term is non-polynomial, we can no longer write down the raw moment equations in a straightforward manner. Nevertheless, we can expand the expressions up to a certain Taylor expansion order $q$ and generate the corresponding time-evolution equations for the means and higher order central moments—this situation is identical to moment expansion for chemical reaction networks with non-polynomial propensities. Hence we can obtain the equations for the means and variances with $q=3$:

    moment_eqs = generate_central_moment_eqs(pendulum_model, 2, 3) 
    +latexify(moment_eqs) # the output here is maybe not the most visually pleasing

    \[\begin{align*} +\frac{d\mu{_{10}}}{dt} =& \mu{_{01}} \\ +\frac{d\mu{_{01}}}{dt} =& \frac{\left( - k \right) \mu{_{01}}}{m} + \frac{\left( - g \right) \sin\left( \mu{_{10}} \right)}{l} + \frac{\frac{1}{6} g M{_{30}} \cos\left( \mu{_{10}} \right)}{l} + \frac{\frac{1}{2} g M{_{20}} \sin\left( \mu{_{10}} \right)}{l} \\ +\frac{dM{_{20}}}{dt} =& 2 M{_{11}} \\ +\frac{dM{_{11}}}{dt} =& \frac{\left( - k \right) M{_{11}}}{m} + \frac{\left( - g \right) M{_{20}} \cos\left( \mu{_{10}} \right)}{l} + \frac{\frac{1}{2} g M{_{30}} \sin\left( \mu{_{10}} \right)}{l} + M{_{02}} \\ +\frac{dM{_{02}}}{dt} =& \frac{\frac{1}{1}}{m^{2}} + \frac{-2 k M{_{02}}}{m} + \frac{g M{_{21}} \sin\left( \mu{_{10}} \right)}{l} + \frac{-2 g M{_{11}} \cos\left( \mu{_{10}} \right)}{l} +\end{align*}\]

    We can now approximate the moment equations using gamma closure, solve the ODEs numerically and compare the predictions to true SDE solution, finding good agreement:

    closed_eqs = moment_closure(moment_eqs, "gamma")
    +
    +u0map = deterministic_IC(u0, closed_eqs)
    +oprob = ODEProblem(closed_eqs, u0map, tspan, ps)
    +sol_MA = solve(oprob, Tsit5(), saveat=0.01)
    +
    +prob_SDE = SDEProblem(pendulum_model, u0, tspan, ps)
    +sol_SDE = solve(EnsembleProblem(prob_SDE), SRIW1(), saveat=0.01, trajectories=100)
    +means_SDE = timeseries_steps_mean(sol_SDE)
    +
    +plot(sol_MA.t, sin.(sol_MA[1, :]), lw=2, label="MA", ylabel="sin(⟨x₁⟩)", xlabel="time")
    +plot!(sol_MA.t, sin.(means_SDE[1, :]), lw=2, label="SDE", linecolor=:red,
    +    linestyle=:dash, background_color_legend=nothing, legend=:topright, grid=false)

    Model 2 SDE

    References

    [1]: K. R. Ghusinga, M. Soltani, A. Lamperski, S. V. Dhople, and A. Singh, "Approximate moment dynamics for polynomial and trigonometric stochastic systems", IEEE 56th Annual Conference on Decision and Control (2017). https://doi.org/10.1109/CDC.2017.8263922