From 442f4058f9433c53219cdf48589ff672b678e0ad Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Fri, 5 Apr 2024 04:16:40 +0000 Subject: [PATCH] build based on 13a044f --- dev/.documenter-siteinfo.json | 2 +- dev/API/CalibrateEmulateSample/index.html | 2 +- dev/API/Emulators/index.html | 32 +- dev/API/GaussianProcess/index.html | 10 +- dev/API/MarkovChainMonteCarlo/index.html | 16 +- dev/API/RandomFeatures/index.html | 66 +- dev/API/Utilities/index.html | 4 +- dev/GaussianProcessEmulator/index.html | 2 +- dev/assets/documenter.js | 923 ++++++++---------- dev/assets/themes/documenter-dark.css | 2 +- dev/calibrate/index.html | 2 +- dev/contributing/index.html | 2 +- dev/emulate/index.html | 2 +- dev/examples/Cloudy_example/index.html | 2 +- dev/examples/edmf_example/index.html | 2 +- .../emulators/ishigami_3d_1d/index.html | 2 +- .../lorenz_integrator_3d_3d/index.html | 2 +- .../emulators/regression_2d_2d/index.html | 2 +- dev/examples/lorenz_example/index.html | 2 +- dev/examples/sinusoid_example/index.html | 2 +- dev/glossary/index.html | 2 +- dev/index.html | 2 +- dev/installation_instructions/index.html | 2 +- dev/objects.inv | Bin 4557 -> 0 bytes dev/random_feature_emulator/index.html | 2 +- dev/sample/index.html | 2 +- dev/search_index.js | 2 +- 27 files changed, 470 insertions(+), 621 deletions(-) delete mode 100644 dev/objects.inv diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index e75fe32e..987ee050 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.10.2","generation_timestamp":"2024-04-05T02:57:14","documenter_version":"1.3.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.10.2","generation_timestamp":"2024-04-05T04:16:32","documenter_version":"1.2.1"}} \ No newline at end of file diff --git a/dev/API/CalibrateEmulateSample/index.html b/dev/API/CalibrateEmulateSample/index.html index eb7ec951..b05ce89a 100644 --- a/dev/API/CalibrateEmulateSample/index.html +++ b/dev/API/CalibrateEmulateSample/index.html @@ -1,2 +1,2 @@ -- · CalibrateEmulateSample.jl
+- · CalibrateEmulateSample.jl
diff --git a/dev/API/Emulators/index.html b/dev/API/Emulators/index.html index 228d00b1..8ffa053c 100644 --- a/dev/API/Emulators/index.html +++ b/dev/API/Emulators/index.html @@ -1,51 +1,61 @@ -General Interface · CalibrateEmulateSample.jl

Emulators

CalibrateEmulateSample.Emulators.EmulatorType
struct Emulator{FT<:AbstractFloat}

Structure used to represent a general emulator, independently of the algorithm used.

Fields

  • machine_learning_tool::CalibrateEmulateSample.Emulators.MachineLearningTool: Machine learning tool, defined as a struct of type MachineLearningTool.

  • training_pairs::EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT} where FT<:AbstractFloat: Normalized, standardized, transformed pairs given the Booleans normalize_inputs, standardize_outputs, retained_svd_frac.

  • input_mean::AbstractVector{FT} where FT<:AbstractFloat: Mean of input; length input_dim.

  • normalize_inputs::Bool: If normalizing: whether to fit models on normalized inputs ((inputs - input_mean) * sqrt_inv_input_cov).

  • normalization::Union{Nothing, LinearAlgebra.UniformScaling{FT}, AbstractMatrix{FT}} where FT<:AbstractFloat: (Linear) normalization transformation; size input_dim × input_dim.

  • standardize_outputs::Bool: Whether to fit models on normalized outputs: outputs / standardize_outputs_factor.

  • standardize_outputs_factors::Union{Nothing, AbstractVector{FT}} where FT<:AbstractFloat: If standardizing: Standardization factors (characteristic values of the problem).

  • decomposition::Union{Nothing, LinearAlgebra.SVD}: The singular value decomposition of obs_noise_cov, such that obs_noise_cov = decomposition.U * Diagonal(decomposition.S) * decomposition.Vt. NB: the SVD may be reduced in dimensions.

  • retained_svd_frac::AbstractFloat: Fraction of singular values kept in decomposition. A value of 1 implies full SVD spectrum information.

source
CalibrateEmulateSample.Emulators.optimize_hyperparameters!Method
optimize_hyperparameters!(
+General Interface · CalibrateEmulateSample.jl

Emulators

CalibrateEmulateSample.Emulators.EmulatorType
struct Emulator{FT<:AbstractFloat}

Structure used to represent a general emulator, independently of the algorithm used.

Fields

  • machine_learning_tool::CalibrateEmulateSample.Emulators.MachineLearningTool: Machine learning tool, defined as a struct of type MachineLearningTool.

  • training_pairs::EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT} where FT<:AbstractFloat: Normalized, standardized, transformed pairs given the Booleans normalize_inputs, standardize_outputs, retained_svd_frac.

  • input_mean::AbstractVector{FT} where FT<:AbstractFloat: Mean of input; length input_dim.

  • normalize_inputs::Bool: If normalizing: whether to fit models on normalized inputs ((inputs - input_mean) * sqrt_inv_input_cov).

  • normalization::Union{Nothing, LinearAlgebra.UniformScaling{FT}, AbstractMatrix{FT}} where FT<:AbstractFloat: (Linear) normalization transformation; size input_dim × input_dim.

  • standardize_outputs::Bool: Whether to fit models on normalized outputs: outputs / standardize_outputs_factor.

  • standardize_outputs_factors::Union{Nothing, AbstractVector{FT}} where FT<:AbstractFloat: If standardizing: Standardization factors (characteristic values of the problem).

  • decomposition::Union{Nothing, LinearAlgebra.SVD}: The singular value decomposition of obs_noise_cov, such that obs_noise_cov = decomposition.U * Diagonal(decomposition.S) * decomposition.Vt. NB: the SVD may be reduced in dimensions.

  • retained_svd_frac::AbstractFloat: Fraction of singular values kept in decomposition. A value of 1 implies full SVD spectrum information.

source
CalibrateEmulateSample.Emulators.EmulatorMethod
Emulator(
+    machine_learning_tool::CalibrateEmulateSample.Emulators.MachineLearningTool,
+    input_output_pairs::EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT<:AbstractFloat};
+    obs_noise_cov,
+    normalize_inputs,
+    standardize_outputs,
+    standardize_outputs_factors,
+    decorrelate,
+    retained_svd_frac
+) -> CalibrateEmulateSample.Emulators.Emulator{FT} where Float64<:FT<:AbstractFloat
+

Positional Arguments

  • machine_learning_tool ::MachineLearningTool,
  • input_output_pairs ::PairedDataContainer

Keyword Arguments

  • obs_noise_cov: A matrix/uniform scaling to provide the observational noise covariance of the data - used for data processing (default nothing),
  • normalize_inputs: Normalize the inputs to be unit Gaussian, in the smallest full-rank space of the data (default true),
  • standardize_outputs: Standardize outputs with by dividing by a vector of provided factors (default false),
  • standardize_outputs_factors: If standardizing, the provided dim_output-length vector of factors,
  • decorrelate: Apply (truncated) SVD to the outputs. Predictions are returned in the decorrelated space, (default true)
  • retained_svd_frac: The cumulative sum of singular values retained after output SVD truncation (default 1.0 - no truncation)
source
GaussianProcesses.predictFunction
predict(
     gp::CalibrateEmulateSample.Emulators.GaussianProcess{CalibrateEmulateSample.Emulators.GPJL},
     new_inputs::AbstractArray{FT<:AbstractFloat, 2}
 ) -> Tuple{Any, Any}
-

Predict means and covariances in decorrelated output space using Gaussian process models.

source
predict(
+

Predict means and covariances in decorrelated output space using Gaussian process models.

source
predict(
     srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface,
     new_inputs::AbstractMatrix;
     multithread
 ) -> Tuple{Any, Any}
-

Prediction of data observation (not latent function) at new inputs (passed in as columns in a matrix). That is, we add the observational noise into predictions.

source
predict(
+

Prediction of data observation (not latent function) at new inputs (passed in as columns in a matrix). That is, we add the observational noise into predictions.

source
predict(
     vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface,
     new_inputs::AbstractMatrix
 ) -> Tuple{Any, Any}
-

Prediction of data observation (not latent function) at new inputs (passed in as columns in a matrix). That is, we add the observational noise into predictions.

source
predict(
+

Prediction of data observation (not latent function) at new inputs (passed in as columns in a matrix). That is, we add the observational noise into predictions.

source
predict(
     emulator::CalibrateEmulateSample.Emulators.Emulator{FT<:AbstractFloat},
     new_inputs::AbstractArray{FT<:AbstractFloat, 2};
     transform_to_real,
     vector_rf_unstandardize,
     mlt_kwargs...
 ) -> Tuple{Any, Any}
-

Makes a prediction using the emulator on new inputs (each new inputs given as data columns). Default is to predict in the decorrelated space.

source
CalibrateEmulateSample.Emulators.standardizeFunction
standardize(
     outputs::AbstractVecOrMat,
     output_covs::Union{AbstractVector{<:AbstractMatrix}, AbstractVector{<:LinearAlgebra.UniformScaling}},
     factors::AbstractVector
 ) -> Tuple{Any, Union{AbstractVector{<:AbstractMatrix}, AbstractVector{<:LinearAlgebra.UniformScaling}}}
-

Standardize with a vector of factors (size equal to output dimension).

source
CalibrateEmulateSample.Emulators.reverse_standardizeFunction
reverse_standardize(
     emulator::CalibrateEmulateSample.Emulators.Emulator{FT<:AbstractFloat},
     outputs::AbstractVecOrMat,
     output_covs::AbstractVecOrMat
 ) -> Tuple{Any, Any}
-

Reverse a previous standardization with the stored vector of factors (size equal to output dimension). output_cov is a Vector of covariance matrices, such as is returned by svd_reverse_transform_mean_cov.

source
CalibrateEmulateSample.Emulators.svd_transformFunction
svd_transform(
     data::AbstractArray{FT<:AbstractFloat, 2},
     obs_noise_cov::Union{Nothing, AbstractArray{FT<:AbstractFloat, 2}};
     retained_svd_frac
 ) -> Tuple{Any, Any}
-

Apply a singular value decomposition (SVD) to the data

  • data - GP training data/targets; size output_dim × N_samples
  • obs_noise_cov - covariance of observational noise
  • truncate_svd - Project onto this fraction of the largest principal components. Defaults to 1.0 (no truncation).

Returns the transformed data and the decomposition, which is a matrix factorization of type LinearAlgebra.SVD.

Note: If F::SVD is the factorization object, U, S, V and Vt can be obtained via F.U, F.S, F.V and F.Vt, such that A = U * Diagonal(S) * Vt. The singular values in S are sorted in descending order.

source
CalibrateEmulateSample.Emulators.svd_reverse_transform_mean_covFunction
svd_reverse_transform_mean_cov(
+

Apply a singular value decomposition (SVD) to the data

  • data - GP training data/targets; size output_dim × N_samples
  • obs_noise_cov - covariance of observational noise
  • truncate_svd - Project onto this fraction of the largest principal components. Defaults to 1.0 (no truncation).

Returns the transformed data and the decomposition, which is a matrix factorization of type LinearAlgebra.SVD.

Note: If F::SVD is the factorization object, U, S, V and Vt can be obtained via F.U, F.S, F.V and F.Vt, such that A = U * Diagonal(S) * Vt. The singular values in S are sorted in descending order.

source
CalibrateEmulateSample.Emulators.svd_reverse_transform_mean_covFunction
svd_reverse_transform_mean_cov(
     μ::AbstractArray{FT<:AbstractFloat, 2},
     σ2::AbstractVector,
     decomposition::LinearAlgebra.SVD
 ) -> Tuple{Any, Any}
-

Transform the mean and covariance back to the original (correlated) coordinate system

  • μ - predicted mean; size output_dim × N_predicted_points.
  • σ2 - predicted variance; size output_dim × N_predicted_points. - predicted covariance; size N_predicted_points array of size output_dim × output_dim.
  • decomposition - SVD decomposition of obs_noise_cov.

Returns the transformed mean (size output_dim × N_predicted_points) and variance. Note that transforming the variance back to the original coordinate system results in non-zero off-diagonal elements, so instead of just returning the elements on the main diagonal (i.e., the variances), we return the full covariance at each point, as a vector of length N_predicted_points, where each element is a matrix of size output_dim × output_dim.

source
+

Transform the mean and covariance back to the original (correlated) coordinate system

  • μ - predicted mean; size output_dim × N_predicted_points.
  • σ2 - predicted variance; size output_dim × N_predicted_points. - predicted covariance; size N_predicted_points array of size output_dim × output_dim.
  • decomposition - SVD decomposition of obs_noise_cov.

Returns the transformed mean (size output_dim × N_predicted_points) and variance. Note that transforming the variance back to the original coordinate system results in non-zero off-diagonal elements, so instead of just returning the elements on the main diagonal (i.e., the variances), we return the full covariance at each point, as a vector of length N_predicted_points, where each element is a matrix of size output_dim × output_dim.

source
diff --git a/dev/API/GaussianProcess/index.html b/dev/API/GaussianProcess/index.html index 0ddbf164..dc297e72 100644 --- a/dev/API/GaussianProcess/index.html +++ b/dev/API/GaussianProcess/index.html @@ -1,22 +1,22 @@ -Gaussian Process · CalibrateEmulateSample.jl

GaussianProcess

CalibrateEmulateSample.Emulators.GaussianProcessType
struct GaussianProcess{GPPackage, FT} <: CalibrateEmulateSample.Emulators.MachineLearningTool

Structure holding training input and the fitted Gaussian process regression models.

Fields

  • models::Vector{Union{Nothing, PyCall.PyObject, GaussianProcesses.GPE}}: The Gaussian Process (GP) Regression model(s) that are fitted to the given input-data pairs.

  • kernel::Union{Nothing, var"#s17", var"#s18"} where {var"#s17"<:GaussianProcesses.Kernel, var"#s18"<:PyCall.PyObject}: Kernel object.

  • noise_learn::Bool: Learn the noise with the White Noise kernel explicitly?

  • alg_reg_noise::Any: Additional observational or regularization noise in used in GP algorithms

  • prediction_type::CalibrateEmulateSample.Emulators.PredictionType: Prediction type (y to predict the data, f to predict the latent function).

source
CalibrateEmulateSample.Emulators.GaussianProcessMethod
GaussianProcess(
+Gaussian Process · CalibrateEmulateSample.jl

GaussianProcess

CalibrateEmulateSample.Emulators.GaussianProcessType
struct GaussianProcess{GPPackage, FT} <: CalibrateEmulateSample.Emulators.MachineLearningTool

Structure holding training input and the fitted Gaussian process regression models.

Fields

  • models::Vector{Union{Nothing, PyCall.PyObject, GaussianProcesses.GPE}}: The Gaussian Process (GP) Regression model(s) that are fitted to the given input-data pairs.

  • kernel::Union{Nothing, var"#s17", var"#s18"} where {var"#s17"<:GaussianProcesses.Kernel, var"#s18"<:PyCall.PyObject}: Kernel object.

  • noise_learn::Bool: Learn the noise with the White Noise kernel explicitly?

  • alg_reg_noise::Any: Additional observational or regularization noise in used in GP algorithms

  • prediction_type::CalibrateEmulateSample.Emulators.PredictionType: Prediction type (y to predict the data, f to predict the latent function).

source
CalibrateEmulateSample.Emulators.GaussianProcessMethod
GaussianProcess(
     package::AbstractFloat;
     kernel,
     noise_learn,
     alg_reg_noise,
     prediction_type
 )
-
  • package - GaussianProcessPackage object.
  • kernel - GaussianProcesses kernel object. Default is a Squared Exponential kernel.
  • noise_learn - Boolean to additionally learn white noise in decorrelated space. Default is true.
  • alg_reg_noise - Float to fix the (small) regularization parameter of algorithms when noise_learn = true
  • prediction_type - PredictionType object. Default predicts data, not latent function (FType()).
source
CalibrateEmulateSample.Emulators.build_models!Method
build_models!(
+
  • package - GaussianProcessPackage object.
  • kernel - GaussianProcesses kernel object. Default is a Squared Exponential kernel.
  • noise_learn - Boolean to additionally learn white noise in decorrelated space. Default is true.
  • alg_reg_noise - Float to fix the (small) regularization parameter of algorithms when noise_learn = true
  • prediction_type - PredictionType object. Default predicts data, not latent function (FType()).
source
CalibrateEmulateSample.Emulators.build_models!Method
build_models!(
     gp::CalibrateEmulateSample.Emulators.GaussianProcess{CalibrateEmulateSample.Emulators.GPJL},
     input_output_pairs::EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT<:AbstractFloat}
 )
-

Method to build Gaussian process models based on the package.

source
CalibrateEmulateSample.Emulators.optimize_hyperparameters!Method
optimize_hyperparameters!(
     gp::CalibrateEmulateSample.Emulators.GaussianProcess{CalibrateEmulateSample.Emulators.GPJL},
     args...;
     kwargs...
 )
-

Optimize Gaussian process hyperparameters using in-build package method.

Warning: if one uses GPJL() and wishes to modify positional arguments. The first positional argument must be the Optim method (default LBGFS()).

source
GaussianProcesses.predictMethod
predict(
+

Optimize Gaussian process hyperparameters using in-build package method.

Warning: if one uses GPJL() and wishes to modify positional arguments. The first positional argument must be the Optim method (default LBGFS()).

source
GaussianProcesses.predictMethod
predict(
     gp::CalibrateEmulateSample.Emulators.GaussianProcess{CalibrateEmulateSample.Emulators.GPJL},
     new_inputs::AbstractArray{FT<:AbstractFloat, 2}
 ) -> Tuple{Any, Any}
-

Predict means and covariances in decorrelated output space using Gaussian process models.

source
+

Predict means and covariances in decorrelated output space using Gaussian process models.

source
diff --git a/dev/API/MarkovChainMonteCarlo/index.html b/dev/API/MarkovChainMonteCarlo/index.html index 2c21e621..553c1c14 100644 --- a/dev/API/MarkovChainMonteCarlo/index.html +++ b/dev/API/MarkovChainMonteCarlo/index.html @@ -1,5 +1,5 @@ -MarkovChainMonteCarlo · CalibrateEmulateSample.jl

MarkovChainMonteCarlo

Top-level class and methods

CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCWrapperType
struct MCMCWrapper

Top-level class holding all configuration information needed for MCMC sampling: the prior, emulated likelihood and sampling algorithm (DensityModel and Sampler, respectively, in AbstractMCMC's terminology).

Fields

  • prior::EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution: ParameterDistribution object describing the prior distribution on parameter values.

  • log_posterior_map::AbstractMCMC.AbstractModel: AdvancedMH.DensityModel object, used to evaluate the posterior density being sampled from.

  • mh_proposal_sampler::AbstractMCMC.AbstractSampler: Object describing a MCMC sampling algorithm and its settings.

  • sample_kwargs::NamedTuple: NamedTuple of other arguments to be passed to AbstractMCMC.sample().

source
CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCWrapperMethod
MCMCWrapper(
+MarkovChainMonteCarlo · CalibrateEmulateSample.jl

MarkovChainMonteCarlo

Top-level class and methods

CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCWrapperType
struct MCMCWrapper

Top-level class holding all configuration information needed for MCMC sampling: the prior, emulated likelihood and sampling algorithm (DensityModel and Sampler, respectively, in AbstractMCMC's terminology).

Fields

  • prior::EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution: ParameterDistribution object describing the prior distribution on parameter values.

  • log_posterior_map::AbstractMCMC.AbstractModel: AdvancedMH.DensityModel object, used to evaluate the posterior density being sampled from.

  • mh_proposal_sampler::AbstractMCMC.AbstractSampler: Object describing a MCMC sampling algorithm and its settings.

  • sample_kwargs::NamedTuple: NamedTuple of other arguments to be passed to AbstractMCMC.sample().

source
CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCWrapperMethod
MCMCWrapper(
     mcmc_alg::CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCProtocol,
     obs_sample::AbstractArray{FT<:AbstractFloat, 1},
     prior::EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution,
@@ -8,11 +8,11 @@
     burnin,
     kwargs...
 )
-

Constructor for MCMCWrapper which performs the same standardization (SVD decorrelation) that was applied in the Emulator. It creates and wraps an instance of EmulatorPosteriorModel, for sampling from the Emulator, and MetropolisHastingsSampler, for generating the MC proposals.

  • mcmc_alg: MCMCProtocol describing the MCMC sampling algorithm to use. Currently implemented algorithms are:

    • RWMHSampling: Metropolis-Hastings sampling from a vanilla random walk with fixed stepsize.
    • pCNMHSampling: Metropolis-Hastings sampling using the preconditioned Crank-Nicholson algorithm, which has a well-behaved small-stepsize limit.
  • obs_sample: A single sample from the observations. Can, e.g., be picked from an Observation struct using get_obs_sample.

  • prior: ParameterDistribution object containing the parameters' prior distributions.

  • em: Emulator to sample from.

  • stepsize: MCMC step size, applied as a scaling to the prior covariance.

  • init_params: Starting parameter values for MCMC sampling.

  • burnin: Initial number of MCMC steps to discard from output (pre-convergence).

source
StatsBase.sampleFunction

sample([rng,] mcmc::MCMCWrapper, args...; kwargs...)

Extends the sample methods of AbstractMCMC (which extends StatsBase) to sample from the emulated posterior, using the MCMC sampling algorithm and Emulator configured in MCMCWrapper. Returns a MCMCChains.Chains object containing the samples.

Supported methods are:

  • sample([rng, ]mcmc, N; kwargs...)

    Return a MCMCChains.Chains object containing N samples from the emulated posterior.

  • sample([rng, ]mcmc, isdone; kwargs...)

    Sample from the model with the Markov chain Monte Carlo sampler until a convergence criterion isdone returns true, and return the samples. The function isdone has the signature

        isdone(rng, model, sampler, samples, state, iteration; kwargs...)

    where state and iteration are the current state and iteration of the sampler, respectively. It should return true when sampling should end, and false otherwise.

  • sample([rng, ]mcmc, parallel_type, N, nchains; kwargs...)

    Sample nchains Monte Carlo Markov chains in parallel according to parallel_type, which may be MCMCThreads() or MCMCDistributed() for thread and parallel sampling, respectively.

source
CalibrateEmulateSample.MarkovChainMonteCarlo.get_posteriorFunction
get_posterior(
+

Constructor for MCMCWrapper which performs the same standardization (SVD decorrelation) that was applied in the Emulator. It creates and wraps an instance of EmulatorPosteriorModel, for sampling from the Emulator, and MetropolisHastingsSampler, for generating the MC proposals.

  • mcmc_alg: MCMCProtocol describing the MCMC sampling algorithm to use. Currently implemented algorithms are:

    • RWMHSampling: Metropolis-Hastings sampling from a vanilla random walk with fixed stepsize.
    • pCNMHSampling: Metropolis-Hastings sampling using the preconditioned Crank-Nicholson algorithm, which has a well-behaved small-stepsize limit.
  • obs_sample: A single sample from the observations. Can, e.g., be picked from an Observation struct using get_obs_sample.

  • prior: ParameterDistribution object containing the parameters' prior distributions.

  • em: Emulator to sample from.

  • stepsize: MCMC step size, applied as a scaling to the prior covariance.

  • init_params: Starting parameter values for MCMC sampling.

  • burnin: Initial number of MCMC steps to discard from output (pre-convergence).

source
StatsBase.sampleFunction

sample([rng,] mcmc::MCMCWrapper, args...; kwargs...)

Extends the sample methods of AbstractMCMC (which extends StatsBase) to sample from the emulated posterior, using the MCMC sampling algorithm and Emulator configured in MCMCWrapper. Returns a MCMCChains.Chains object containing the samples.

Supported methods are:

  • sample([rng, ]mcmc, N; kwargs...)

    Return a MCMCChains.Chains object containing N samples from the emulated posterior.

  • sample([rng, ]mcmc, isdone; kwargs...)

    Sample from the model with the Markov chain Monte Carlo sampler until a convergence criterion isdone returns true, and return the samples. The function isdone has the signature

        isdone(rng, model, sampler, samples, state, iteration; kwargs...)

    where state and iteration are the current state and iteration of the sampler, respectively. It should return true when sampling should end, and false otherwise.

  • sample([rng, ]mcmc, parallel_type, N, nchains; kwargs...)

    Sample nchains Monte Carlo Markov chains in parallel according to parallel_type, which may be MCMCThreads() or MCMCDistributed() for thread and parallel sampling, respectively.

source
CalibrateEmulateSample.MarkovChainMonteCarlo.get_posteriorFunction
get_posterior(
     mcmc::CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCWrapper,
     chain::MCMCChains.Chains
 ) -> EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution
-

Returns a ParameterDistribution object corresponding to the empirical distribution of the samples in chain.

Note

This method does not currently support combining samples from multiple Chains.

source
CalibrateEmulateSample.MarkovChainMonteCarlo.optimize_stepsizeFunction
optimize_stepsize(
     rng::Random.AbstractRNG,
     mcmc::CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCWrapper;
     init_stepsize,
@@ -20,18 +20,18 @@
     max_iter,
     sample_kwargs...
 ) -> Float64
-

Uses a heuristic to return a stepsize for the mh_proposal_sampler element of MCMCWrapper which yields fast convergence of the Markov chain.

The criterion used is that Metropolis-Hastings proposals should be accepted between 15% and 35% of the time.

source

See AbstractMCMC sampling API for background on our use of Turing.jl's AbstractMCMC API for MCMC sampling.

Sampler algorithms

CalibrateEmulateSample.MarkovChainMonteCarlo.pCNMHSamplingType
struct pCNMHSampling <: CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCProtocol

MCMCProtocol which uses Metropolis-Hastings sampling that generates proposals for new parameters according to the preconditioned Crank-Nicholson (pCN) algorithm, which is usable for MCMC in the stepsize → 0 limit, unlike the vanilla random walk. Steps are based on the covariance of prior.

source

See AbstractMCMC sampling API for background on our use of Turing.jl's AbstractMCMC API for MCMC sampling.

Sampler algorithms

CalibrateEmulateSample.MarkovChainMonteCarlo.pCNMHSamplingType
struct pCNMHSampling <: CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCProtocol

MCMCProtocol which uses Metropolis-Hastings sampling that generates proposals for new parameters according to the preconditioned Crank-Nicholson (pCN) algorithm, which is usable for MCMC in the stepsize → 0 limit, unlike the vanilla random walk. Steps are based on the covariance of prior.

source
CalibrateEmulateSample.MarkovChainMonteCarlo.MetropolisHastingsSamplerFunction
MetropolisHastingsSampler(
     _::CalibrateEmulateSample.MarkovChainMonteCarlo.RWMHSampling,
     prior::EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution
 ) -> CalibrateEmulateSample.MarkovChainMonteCarlo.RWMetropolisHastings{D} where D<:(AdvancedMH.RandomWalkProposal{false})
-

Constructor for all Sampler objects, with one method for each supported MCMC algorithm.

Warning

Both currently implemented Samplers use a Gaussian approximation to the prior: specifically, new Metropolis-Hastings proposals are a scaled combination of the old parameter values and a random shift distributed as a Gaussian with the same covariance as the prior.

This suffices for our current use case, in which our priors are Gaussian (possibly in a transformed space) and we assume enough fidelity in the Emulator that inference isn't prior-dominated.

source

Emulated posterior (Model)

CalibrateEmulateSample.MarkovChainMonteCarlo.EmulatorPosteriorModelFunction
EmulatorPosteriorModel(
+

Constructor for all Sampler objects, with one method for each supported MCMC algorithm.

Warning

Both currently implemented Samplers use a Gaussian approximation to the prior: specifically, new Metropolis-Hastings proposals are a scaled combination of the old parameter values and a random shift distributed as a Gaussian with the same covariance as the prior.

This suffices for our current use case, in which our priors are Gaussian (possibly in a transformed space) and we assume enough fidelity in the Emulator that inference isn't prior-dominated.

source

Emulated posterior (Model)

CalibrateEmulateSample.MarkovChainMonteCarlo.EmulatorPosteriorModelFunction
EmulatorPosteriorModel(
     prior::EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution,
     em::CalibrateEmulateSample.Emulators.Emulator{FT<:AbstractFloat},
     obs_sample::AbstractArray{FT<:AbstractFloat, 1}
 ) -> AdvancedMH.DensityModel{F} where F<:(CalibrateEmulateSample.MarkovChainMonteCarlo.var"#1#2"{EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution{PDType, CType, ST}, CalibrateEmulateSample.Emulators.Emulator{FT}, <:AbstractVector{FT1}} where {PDType<:EnsembleKalmanProcesses.ParameterDistributions.ParameterDistributionType, CType<:EnsembleKalmanProcesses.ParameterDistributions.ConstraintType, ST<:AbstractString, FT<:AbstractFloat, FT1<:AbstractFloat})
-

Factory which constructs AdvancedMH.DensityModel objects given a prior on the model parameters (prior) and an Emulator of the log-likelihood of the data given parameters. Together these yield the log posterior density we're attempting to sample from with the MCMC, which is the role of the DensityModel class in the AbstractMCMC interface.

source

Internals - MCMC State

CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCStateType
struct MCMCState{T, L<:Real} <: AdvancedMH.AbstractTransition

Extends the AdvancedMH.Transition (which encodes the current state of the MC during sampling) with a boolean flag to record whether this state is new (arising from accepting a Metropolis-Hastings proposal) or old (from rejecting a proposal).

Fields

  • params::Any: Sampled value of the parameters at the current state of the MCMC chain.

  • log_density::Real: Log probability of params, as computed by the model using the prior.

  • accepted::Bool: Whether this state resulted from accepting a new MH proposal.

source

Internals - Other

CalibrateEmulateSample.MarkovChainMonteCarlo.to_decorrelatedFunction
to_decorrelated(
+

Factory which constructs AdvancedMH.DensityModel objects given a prior on the model parameters (prior) and an Emulator of the log-likelihood of the data given parameters. Together these yield the log posterior density we're attempting to sample from with the MCMC, which is the role of the DensityModel class in the AbstractMCMC interface.

source

Internals - MCMC State

CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCStateType
struct MCMCState{T, L<:Real} <: AdvancedMH.AbstractTransition

Extends the AdvancedMH.Transition (which encodes the current state of the MC during sampling) with a boolean flag to record whether this state is new (arising from accepting a Metropolis-Hastings proposal) or old (from rejecting a proposal).

Fields

  • params::Any: Sampled value of the parameters at the current state of the MCMC chain.

  • log_density::Real: Log probability of params, as computed by the model using the prior.

  • accepted::Bool: Whether this state resulted from accepting a new MH proposal.

source

Internals - Other

+

Transform samples from the original (correlated) coordinate system to the SVD-decorrelated coordinate system used by Emulator. Used in the constructor for MCMCWrapper.

source
diff --git a/dev/API/RandomFeatures/index.html b/dev/API/RandomFeatures/index.html index 125c3f8a..9ed407a8 100644 --- a/dev/API/RandomFeatures/index.html +++ b/dev/API/RandomFeatures/index.html @@ -1,18 +1,18 @@ -Random Features · CalibrateEmulateSample.jl

RandomFeatures

Kernel and Covariance structure

CalibrateEmulateSample.Emulators.LowRankFactorType
struct LowRankFactor{FT<:AbstractFloat} <: CalibrateEmulateSample.Emulators.CovarianceStructureType

builds a covariance structure that deviates from the identity with a low-rank perturbation. This perturbation is diagonalized in the low-rank space

source
CalibrateEmulateSample.Emulators.SeparableKernelType
struct SeparableKernel{CST1<:CalibrateEmulateSample.Emulators.CovarianceStructureType, CST2<:CalibrateEmulateSample.Emulators.CovarianceStructureType} <: CalibrateEmulateSample.Emulators.KernelStructureType

Builds a separable kernel, i.e. one that accounts for input and output covariance structure separately

source
CalibrateEmulateSample.Emulators.NonseparableKernelType
struct NonseparableKernel{CST<:CalibrateEmulateSample.Emulators.CovarianceStructureType} <: CalibrateEmulateSample.Emulators.KernelStructureType

Builds a nonseparable kernel, i.e. one that accounts for a joint input and output covariance structure

source
CalibrateEmulateSample.Emulators.calculate_n_hyperparametersFunction
calculate_n_hyperparameters(
+Random Features · CalibrateEmulateSample.jl

RandomFeatures

Kernel and Covariance structure

CalibrateEmulateSample.Emulators.LowRankFactorType
struct LowRankFactor{FT<:AbstractFloat} <: CalibrateEmulateSample.Emulators.CovarianceStructureType

builds a covariance structure that deviates from the identity with a low-rank perturbation. This perturbation is diagonalized in the low-rank space

source
CalibrateEmulateSample.Emulators.SeparableKernelType
struct SeparableKernel{CST1<:CalibrateEmulateSample.Emulators.CovarianceStructureType, CST2<:CalibrateEmulateSample.Emulators.CovarianceStructureType} <: CalibrateEmulateSample.Emulators.KernelStructureType

Builds a separable kernel, i.e. one that accounts for input and output covariance structure separately

source
CalibrateEmulateSample.Emulators.NonseparableKernelType
struct NonseparableKernel{CST<:CalibrateEmulateSample.Emulators.CovarianceStructureType} <: CalibrateEmulateSample.Emulators.KernelStructureType

Builds a nonseparable kernel, i.e. one that accounts for a joint input and output covariance structure

source

Scalar interface

CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterfaceType
struct ScalarRandomFeatureInterface{S<:AbstractString, RNG<:Random.AbstractRNG, KST<:CalibrateEmulateSample.Emulators.KernelStructureType} <: CalibrateEmulateSample.Emulators.RandomFeatureInterface

Structure holding the Scalar Random Feature models.

Fields

  • rfms::Vector{RandomFeatures.Methods.RandomFeatureMethod}: vector of RandomFeatureMethods, contains the feature structure, batch-sizes and regularization

  • fitted_features::Vector{RandomFeatures.Methods.Fit}: vector of Fits, containing the matrix decomposition and coefficients of RF when fitted to data

  • batch_sizes::Union{Nothing, Dict{S, Int64}} where S<:AbstractString: batch sizes

  • n_features::Union{Nothing, Int64}: n_features

  • input_dim::Int64: input dimension

  • rng::Random.AbstractRNG: choice of random number generator

  • kernel_structure::CalibrateEmulateSample.Emulators.KernelStructureType: Kernel structure type (e.g. Separable or Nonseparable)

  • feature_decomposition::AbstractString: Random Feature decomposition, choose from "svd" or "cholesky" (default)

  • optimizer_options::Dict{S} where S<:AbstractString: dictionary of options for hyperparameter optimizer

source

Scalar interface

CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterfaceType
struct ScalarRandomFeatureInterface{S<:AbstractString, RNG<:Random.AbstractRNG, KST<:CalibrateEmulateSample.Emulators.KernelStructureType} <: CalibrateEmulateSample.Emulators.RandomFeatureInterface

Structure holding the Scalar Random Feature models.

Fields

  • rfms::Vector{RandomFeatures.Methods.RandomFeatureMethod}: vector of RandomFeatureMethods, contains the feature structure, batch-sizes and regularization

  • fitted_features::Vector{RandomFeatures.Methods.Fit}: vector of Fits, containing the matrix decomposition and coefficients of RF when fitted to data

  • batch_sizes::Union{Nothing, Dict{S, Int64}} where S<:AbstractString: batch sizes

  • n_features::Union{Nothing, Int64}: n_features

  • input_dim::Int64: input dimension

  • rng::Random.AbstractRNG: choice of random number generator

  • kernel_structure::CalibrateEmulateSample.Emulators.KernelStructureType: Kernel structure type (e.g. Separable or Nonseparable)

  • feature_decomposition::AbstractString: Random Feature decomposition, choose from "svd" or "cholesky" (default)

  • optimizer_options::Dict{S} where S<:AbstractString: dictionary of options for hyperparameter optimizer

source
CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterfaceMethod
ScalarRandomFeatureInterface(
     n_features::Int64,
     input_dim::Int64;
     kernel_structure,
@@ -21,16 +21,16 @@
     feature_decomposition,
     optimizer_options
 ) -> CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface{String, Random._GLOBAL_RNG, CalibrateEmulateSample.Emulators.SeparableKernel{CST1, CalibrateEmulateSample.Emulators.OneDimFactor}} where CST1<:CalibrateEmulateSample.Emulators.CovarianceStructureType
-

Constructs a ScalarRandomFeatureInterface <: MachineLearningTool interface for the RandomFeatures.jl package for multi-input and single- (or decorrelated-)output emulators.

  • n_features - the number of random features
  • input_dim - the dimension of the input space
  • kernel_structure - - a prescribed form of kernel structure
  • batch_sizes = nothing - Dictionary of batch sizes passed RandomFeatures.jl object (see definition there)
  • rng = Random.GLOBAL_RNG - random number generator
  • feature_decomposition = "cholesky" - choice of how to store decompositions of random features, cholesky or svd available
  • optimizer_options = nothing - Dict of options to pass into EKI optimization of hyperparameters (defaults created in ScalarRandomFeatureInterface constructor):
    • "prior": the prior for the hyperparameter optimization
    • "priorinscale": use this to tune the input prior scale
    • "n_ensemble": number of ensemble members
    • "n_iteration": number of eki iterations
    • "covsamplemultiplier": increase for more samples to estimate covariance matrix in optimization (default 10.0, minimum 0.0)
    • "scheduler": Learning rate Scheduler (a.k.a. EKP timestepper) Default: DataMisfitController
    • "tikhonov": tikhonov regularization parameter if >0
    • "inflation": additive inflation ∈ [0,1] with 0 being no inflation
    • "train_fraction": e.g. 0.8 (default) means 80:20 train - test split
    • "nfeaturesopt": fix the number of features for optimization (default n_features, as used for prediction)
    • "multithread": how to multithread. "ensemble" (default) threads across ensemble members "tullio" threads random feature matrix algebra
    • "accelerator": use EKP accelerators (default is no acceleration)
    • "verbose" => false, verbose optimizer statements
source
CalibrateEmulateSample.Emulators.build_models!Method
build_models!(
+

Constructs a ScalarRandomFeatureInterface <: MachineLearningTool interface for the RandomFeatures.jl package for multi-input and single- (or decorrelated-)output emulators.

  • n_features - the number of random features
  • input_dim - the dimension of the input space
  • kernel_structure - - a prescribed form of kernel structure
  • batch_sizes = nothing - Dictionary of batch sizes passed RandomFeatures.jl object (see definition there)
  • rng = Random.GLOBAL_RNG - random number generator
  • feature_decomposition = "cholesky" - choice of how to store decompositions of random features, cholesky or svd available
  • optimizer_options = nothing - Dict of options to pass into EKI optimization of hyperparameters (defaults created in ScalarRandomFeatureInterface constructor):
    • "prior": the prior for the hyperparameter optimization
    • "priorinscale": use this to tune the input prior scale
    • "n_ensemble": number of ensemble members
    • "n_iteration": number of eki iterations
    • "covsamplemultiplier": increase for more samples to estimate covariance matrix in optimization (default 10.0, minimum 0.0)
    • "scheduler": Learning rate Scheduler (a.k.a. EKP timestepper) Default: DataMisfitController
    • "tikhonov": tikhonov regularization parameter if >0
    • "inflation": additive inflation ∈ [0,1] with 0 being no inflation
    • "train_fraction": e.g. 0.8 (default) means 80:20 train - test split
    • "nfeaturesopt": fix the number of features for optimization (default n_features, as used for prediction)
    • "multithread": how to multithread. "ensemble" (default) threads across ensemble members "tullio" threads random feature matrix algebra
    • "accelerator": use EKP accelerators (default is no acceleration)
    • "verbose" => false, verbose optimizer statements
source
CalibrateEmulateSample.Emulators.build_models!Method
build_models!(
     srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface,
     input_output_pairs::EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT<:AbstractFloat}
 )
-

Builds the random feature method from hyperparameters. We use cosine activation functions and a Multivariate Normal distribution (from Distributions.jl) with mean M=0, and input covariance U built with the CovarianceStructureType.

source
GaussianProcesses.predictMethod
predict(
+

Builds the random feature method from hyperparameters. We use cosine activation functions and a Multivariate Normal distribution (from Distributions.jl) with mean M=0, and input covariance U built with the CovarianceStructureType.

source
GaussianProcesses.predictMethod
predict(
     srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface,
     new_inputs::AbstractMatrix;
     multithread
 ) -> Tuple{Any, Any}
-

Prediction of data observation (not latent function) at new inputs (passed in as columns in a matrix). That is, we add the observational noise into predictions.

source

Vector Interface

CalibrateEmulateSample.Emulators.VectorRandomFeatureInterfaceType
struct VectorRandomFeatureInterface{S<:AbstractString, RNG<:Random.AbstractRNG, KST<:CalibrateEmulateSample.Emulators.KernelStructureType} <: CalibrateEmulateSample.Emulators.RandomFeatureInterface

Structure holding the Vector Random Feature models.

Fields

  • rfms::Vector{RandomFeatures.Methods.RandomFeatureMethod}: A vector of RandomFeatureMethods, contains the feature structure, batch-sizes and regularization

  • fitted_features::Vector{RandomFeatures.Methods.Fit}: vector of Fits, containing the matrix decomposition and coefficients of RF when fitted to data

  • batch_sizes::Union{Nothing, Dict{S, Int64}} where S<:AbstractString: batch sizes

  • n_features::Union{Nothing, Int64}: number of features

  • input_dim::Int64: input dimension

  • output_dim::Int64: output_dimension

  • rng::Random.AbstractRNG: rng

  • regularization::Vector{Union{LinearAlgebra.Diagonal, LinearAlgebra.UniformScaling, Matrix}}: regularization

  • kernel_structure::CalibrateEmulateSample.Emulators.KernelStructureType: Kernel structure type (e.g. Separable or Nonseparable)

  • feature_decomposition::AbstractString: Random Feature decomposition, choose from "svd" or "cholesky" (default)

  • optimizer_options::Dict: dictionary of options for hyperparameter optimizer

source

Vector Interface

CalibrateEmulateSample.Emulators.VectorRandomFeatureInterfaceType
struct VectorRandomFeatureInterface{S<:AbstractString, RNG<:Random.AbstractRNG, KST<:CalibrateEmulateSample.Emulators.KernelStructureType} <: CalibrateEmulateSample.Emulators.RandomFeatureInterface

Structure holding the Vector Random Feature models.

Fields

  • rfms::Vector{RandomFeatures.Methods.RandomFeatureMethod}: A vector of RandomFeatureMethods, contains the feature structure, batch-sizes and regularization

  • fitted_features::Vector{RandomFeatures.Methods.Fit}: vector of Fits, containing the matrix decomposition and coefficients of RF when fitted to data

  • batch_sizes::Union{Nothing, Dict{S, Int64}} where S<:AbstractString: batch sizes

  • n_features::Union{Nothing, Int64}: number of features

  • input_dim::Int64: input dimension

  • output_dim::Int64: output_dimension

  • rng::Random.AbstractRNG: rng

  • regularization::Vector{Union{LinearAlgebra.Diagonal, LinearAlgebra.UniformScaling, Matrix}}: regularization

  • kernel_structure::CalibrateEmulateSample.Emulators.KernelStructureType: Kernel structure type (e.g. Separable or Nonseparable)

  • feature_decomposition::AbstractString: Random Feature decomposition, choose from "svd" or "cholesky" (default)

  • optimizer_options::Dict: dictionary of options for hyperparameter optimizer

source
CalibrateEmulateSample.Emulators.VectorRandomFeatureInterfaceMethod
VectorRandomFeatureInterface(
     n_features::Int64,
     input_dim::Int64,
     output_dim::Int64;
@@ -40,81 +40,81 @@
     feature_decomposition,
     optimizer_options
 ) -> CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface{String, Random._GLOBAL_RNG, CalibrateEmulateSample.Emulators.SeparableKernel{CST1, CST2}} where {CST1<:CalibrateEmulateSample.Emulators.CovarianceStructureType, CST2<:CalibrateEmulateSample.Emulators.CovarianceStructureType}
-

Constructs a VectorRandomFeatureInterface <: MachineLearningTool interface for the RandomFeatures.jl package for multi-input and multi-output emulators.

  • n_features - the number of random features
  • input_dim - the dimension of the input space
  • output_dim - the dimension of the output space
  • kernel_structure - - a prescribed form of kernel structure
  • batch_sizes = nothing - Dictionary of batch sizes passed RandomFeatures.jl object (see definition there)
  • rng = Random.GLOBAL_RNG - random number generator
  • feature_decomposition = "cholesky" - choice of how to store decompositions of random features, cholesky or svd available
  • optimizer_options = nothing - Dict of options to pass into EKI optimization of hyperparameters (defaults created in VectorRandomFeatureInterface constructor):
    • "prior": the prior for the hyperparameter optimization
    • "priorinscale"/"prioroutscale": use these to tune the input/output prior scale.
    • "n_ensemble": number of ensemble members
    • "n_iteration": number of eki iterations
    • "scheduler": Learning rate Scheduler (a.k.a. EKP timestepper) Default: DataMisfitController
    • "covsamplemultiplier": increase for more samples to estimate covariance matrix in optimization (default 10.0, minimum 0.0)
    • "tikhonov": tikhonov regularization parameter if > 0
    • "inflation": additive inflation ∈ [0,1] with 0 being no inflation
    • "train_fraction": e.g. 0.8 (default) means 80:20 train - test split
    • "nfeaturesopt": fix the number of features for optimization (default n_features, as used for prediction)
    • "multithread": how to multithread. "ensemble" (default) threads across ensemble members "tullio" threads random feature matrix algebra
    • "accelerator": use EKP accelerators (default is no acceleration)
    • "verbose" => false, verbose optimizer statements to check convergence, priors and optimal parameters.
source
CalibrateEmulateSample.Emulators.build_models!Method
build_models!(
+

Constructs a VectorRandomFeatureInterface <: MachineLearningTool interface for the RandomFeatures.jl package for multi-input and multi-output emulators.

  • n_features - the number of random features
  • input_dim - the dimension of the input space
  • output_dim - the dimension of the output space
  • kernel_structure - - a prescribed form of kernel structure
  • batch_sizes = nothing - Dictionary of batch sizes passed RandomFeatures.jl object (see definition there)
  • rng = Random.GLOBAL_RNG - random number generator
  • feature_decomposition = "cholesky" - choice of how to store decompositions of random features, cholesky or svd available
  • optimizer_options = nothing - Dict of options to pass into EKI optimization of hyperparameters (defaults created in VectorRandomFeatureInterface constructor):
    • "prior": the prior for the hyperparameter optimization
    • "priorinscale"/"prioroutscale": use these to tune the input/output prior scale.
    • "n_ensemble": number of ensemble members
    • "n_iteration": number of eki iterations
    • "scheduler": Learning rate Scheduler (a.k.a. EKP timestepper) Default: DataMisfitController
    • "covsamplemultiplier": increase for more samples to estimate covariance matrix in optimization (default 10.0, minimum 0.0)
    • "tikhonov": tikhonov regularization parameter if > 0
    • "inflation": additive inflation ∈ [0,1] with 0 being no inflation
    • "train_fraction": e.g. 0.8 (default) means 80:20 train - test split
    • "nfeaturesopt": fix the number of features for optimization (default n_features, as used for prediction)
    • "multithread": how to multithread. "ensemble" (default) threads across ensemble members "tullio" threads random feature matrix algebra
    • "accelerator": use EKP accelerators (default is no acceleration)
    • "verbose" => false, verbose optimizer statements to check convergence, priors and optimal parameters.
source
CalibrateEmulateSample.Emulators.build_models!Method
build_models!(
     vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface,
     input_output_pairs::EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT<:AbstractFloat};
     regularization_matrix
-) -> Vector{Union{LinearAlgebra.Diagonal, LinearAlgebra.UniformScaling, Matrix}}
-

Build Vector Random Feature model for the input-output pairs subject to regularization, and optimizes the hyperparameters with EKP.

source
GaussianProcesses.predictMethod
predict(
+) -> Union{Nothing, Vector{Union{LinearAlgebra.Diagonal, LinearAlgebra.UniformScaling, Matrix}}}
+

Build Vector Random Feature model for the input-output pairs subject to regularization, and optimizes the hyperparameters with EKP.

source
GaussianProcesses.predictMethod
predict(
     vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface,
     new_inputs::AbstractMatrix
 ) -> Tuple{Any, Any}
-

Prediction of data observation (not latent function) at new inputs (passed in as columns in a matrix). That is, we add the observational noise into predictions.

source

Other utilities

Other utilities

CalibrateEmulateSample.Emulators.get_rfmsFunction
get_rfms(
     srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface
 ) -> Vector{RandomFeatures.Methods.RandomFeatureMethod}
-

gets the rfms field

source
get_rfms(
+

gets the rfms field

source
get_rfms(
     vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface
 ) -> Vector{RandomFeatures.Methods.RandomFeatureMethod}
-

Gets the rfms field

source
CalibrateEmulateSample.Emulators.get_fitted_featuresFunction
get_fitted_features(
     srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface
 ) -> Vector{RandomFeatures.Methods.Fit}
-

gets the fitted_features field

source
get_fitted_features(
+

gets the fitted_features field

source
get_fitted_features(
     vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface
 ) -> Vector{RandomFeatures.Methods.Fit}
-

Gets the fitted_features field

source
CalibrateEmulateSample.Emulators.get_batch_sizesFunction
get_batch_sizes(
     srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface
 ) -> Union{Nothing, Dict{S, Int64}} where S<:AbstractString
-

gets batch_sizes the field

source
get_batch_sizes(
+

gets batch_sizes the field

source
get_batch_sizes(
     vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface
 ) -> Union{Nothing, Dict{S, Int64}} where S<:AbstractString
-

Gets the batch_sizes field

source
CalibrateEmulateSample.Emulators.get_n_featuresFunction
get_n_features(
     srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface
 ) -> Union{Nothing, Int64}
-

gets the n_features field

source
get_n_features(
+

gets the n_features field

source
get_n_features(
     vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface
 ) -> Union{Nothing, Int64}
-

Gets the n_features field

source
CalibrateEmulateSample.Emulators.get_input_dimFunction
get_input_dim(
     srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface
 ) -> Int64
-

gets the input_dim field

source
get_input_dim(
+

gets the input_dim field

source
get_input_dim(
     vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface
 ) -> Int64
-

Gets the input_dim field

source
CalibrateEmulateSample.Emulators.get_rngFunction
get_rng(
     srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface
 ) -> Random.AbstractRNG
-

gets the rng field

source
get_rng(
+

gets the rng field

source
get_rng(
     vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface
 ) -> Random.AbstractRNG
-

Gets the rng field

source
CalibrateEmulateSample.Emulators.get_kernel_structureFunction
get_kernel_structure(
     srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface
 ) -> CalibrateEmulateSample.Emulators.KernelStructureType
-

Gets the kernel_structure field

source
get_kernel_structure(
+

Gets the kernel_structure field

source
get_kernel_structure(
     vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface
 ) -> CalibrateEmulateSample.Emulators.KernelStructureType
-

Gets the kernel_structure field

source
CalibrateEmulateSample.Emulators.get_feature_decompositionFunction
get_feature_decomposition(
     srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface
 ) -> AbstractString
-

gets the feature_decomposition field

source
get_feature_decomposition(
+

gets the feature_decomposition field

source
get_feature_decomposition(
     vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface
 ) -> AbstractString
-

Gets the feature_decomposition field

source
CalibrateEmulateSample.Emulators.get_optimizer_optionsFunction
get_optimizer_options(
     srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface
 ) -> Dict{S} where S<:AbstractString
-

gets the optimizer_options field

source
get_optimizer_options(
+

gets the optimizer_options field

source
get_optimizer_options(
     vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface
 ) -> Dict
-

Gets the optimizer_options field

source
CalibrateEmulateSample.Emulators.shrinkage_covFunction
shrinkage_cov(sample_mat::AbstractMatrix) -> Any
-

Calculate the empirical covariance, additionally applying a shrinkage operator (here the Ledoit Wolf 2004 shrinkage operation). Known to have better stability properties than Monte-Carlo for low sample sizes

source
+

Empty method, as optimization takes place within the build_models stage

source
CalibrateEmulateSample.Emulators.shrinkage_covFunction
shrinkage_cov(sample_mat::AbstractMatrix) -> Any
+

Calculate the empirical covariance, additionally applying a shrinkage operator (here the Ledoit Wolf 2004 shrinkage operation). Known to have better stability properties than Monte-Carlo for low sample sizes

source
diff --git a/dev/API/Utilities/index.html b/dev/API/Utilities/index.html index d0b781a6..4b4ccc2c 100644 --- a/dev/API/Utilities/index.html +++ b/dev/API/Utilities/index.html @@ -4,8 +4,8 @@ obs::EnsembleKalmanProcesses.Observations.Observation; rng_seed ) -> Any -

Return a random sample from the observations, for use in the MCMC.

source
CalibrateEmulateSample.Utilities.get_training_pointsMethod
get_training_points(
+

Return a random sample from the observations, for use in the MCMC.

  • rng - optional RNG object used to pick random sample; defaults to Random.GLOBAL_RNG.
  • obs - Observation struct with the observations (extract will pick one of the sample observations to train).
  • rng_seed - optional kwarg; if provided, used to re-seed rng before sampling.
source
CalibrateEmulateSample.Utilities.get_training_pointsMethod
get_training_points(
     ekp::EnsembleKalmanProcesses.EnsembleKalmanProcess{FT, IT, P},
     train_iterations::Union{AbstractVector{IT}, IT} where IT
 ) -> EnsembleKalmanProcesses.DataContainers.PairedDataContainer
-

Extract the training points needed to train the Gaussian process regression.

  • ekp - EnsembleKalmanProcess holding the parameters and the data that were produced during the Ensemble Kalman (EK) process.
  • train_iterations - Number (or indices) EK layers/iterations to train on.
source
+

Extract the training points needed to train the Gaussian process regression.

source diff --git a/dev/GaussianProcessEmulator/index.html b/dev/GaussianProcessEmulator/index.html index d4b6808e..84185fa7 100644 --- a/dev/GaussianProcessEmulator/index.html +++ b/dev/GaussianProcessEmulator/index.html @@ -25,4 +25,4 @@ noise_learn = true )

When noise_learn is true, an additional white noise kernel is added to the kernel. This white noise is present across all parameter values, including the training data. The scale parameters of the white noise kernel are learned in optimize_hyperparameters!(emulator).

You may not need to learn the noise if you already have a good estimate of the noise from your training data, and if the Gaussian process kernel is well specified. When noise_learn is false, a small additional regularization is added for stability. The default value is 1e-3 but this can be chosen through the optional argument alg_reg_noise:

gauss_proc = GaussianProcess(
     gppackage;
     noise_learn = false,
-    alg_reg_noise = 1e-3 )
+ alg_reg_noise = 1e-3 ) diff --git a/dev/assets/documenter.js b/dev/assets/documenter.js index c6562b55..f5311607 100644 --- a/dev/assets/documenter.js +++ b/dev/assets/documenter.js @@ -4,6 +4,7 @@ requirejs.config({ '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.13.2/jquery-ui.min', + 'minisearch': 'https://cdn.jsdelivr.net/npm/minisearch@6.1.0/dist/umd/index.min', 'katex-auto-render': 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.8/contrib/auto-render.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', @@ -102,10 +103,9 @@ $(document).on("click", ".docstring header", function () { }); }); -$(document).on("click", ".docs-article-toggle-button", function (event) { +$(document).on("click", ".docs-article-toggle-button", function () { let articleToggleTitle = "Expand docstring"; let navArticleToggleTitle = "Expand all docstrings"; - let animationSpeed = event.noToggleAnimation ? 0 : 400; debounce(() => { if (isExpanded) { @@ -116,7 +116,7 @@ $(document).on("click", ".docs-article-toggle-button", function (event) { isExpanded = false; - $(".docstring section").slideUp(animationSpeed); + $(".docstring section").slideUp(); } else { $(this).removeClass("fa-chevron-down").addClass("fa-chevron-up"); $(".docstring-article-toggle-button") @@ -127,7 +127,7 @@ $(document).on("click", ".docs-article-toggle-button", function (event) { articleToggleTitle = "Collapse docstring"; navArticleToggleTitle = "Collapse all docstrings"; - $(".docstring section").slideDown(animationSpeed); + $(".docstring section").slideDown(); } $(this).prop("title", navArticleToggleTitle); @@ -224,465 +224,224 @@ $(document).ready(function () { }) //////////////////////////////////////////////////////////////////////////////// -require(['jquery'], function($) { - -$(document).ready(function () { - let meta = $("div[data-docstringscollapsed]").data(); - - if (meta?.docstringscollapsed) { - $("#documenter-article-toggle-button").trigger({ - type: "click", - noToggleAnimation: true, - }); - } -}); - -}) -//////////////////////////////////////////////////////////////////////////////// -require(['jquery'], function($) { - -/* -To get an in-depth about the thought process you can refer: https://hetarth02.hashnode.dev/series/gsoc - -PSEUDOCODE: - -Searching happens automatically as the user types or adjusts the selected filters. -To preserve responsiveness, as much as possible of the slow parts of the search are done -in a web worker. Searching and result generation are done in the worker, and filtering and -DOM updates are done in the main thread. The filters are in the main thread as they should -be very quick to apply. This lets filters be changed without re-searching with minisearch -(which is possible even if filtering is on the worker thread) and also lets filters be -changed _while_ the worker is searching and without message passing (neither of which are -possible if filtering is on the worker thread) - -SEARCH WORKER: - -Import minisearch - -Build index - -On message from main thread - run search - find the first 200 unique results from each category, and compute their divs for display - note that this is necessary and sufficient information for the main thread to find the - first 200 unique results from any given filter set - post results to main thread - -MAIN: - -Launch worker - -Declare nonconstant globals (worker_is_running, last_search_text, unfiltered_results) +require(['jquery', 'minisearch'], function($, minisearch) { -On text update - if worker is not running, launch_search() +// 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 -launch_search - set worker_is_running to true, set last_search_text to the search text - post the search query to worker +let results = []; +let timer = undefined; -on message from worker - if last_search_text is not the same as the text in the search field, - the latest search result is not reflective of the latest search query, so update again - launch_search() - otherwise - set worker_is_running to false - - regardless, display the new search results to the user - save the unfiltered_results as a global - update_search() - -on filter click - adjust the filter selection - update_search() - -update_search - apply search filters by looping through the unfiltered_results and finding the first 200 - unique results that match the filters - - Update the DOM -*/ - -/////// SEARCH WORKER /////// - -function worker_function(documenterSearchIndex, documenterBaseURL, filters) { - importScripts( - "https://cdn.jsdelivr.net/npm/minisearch@6.1.0/dist/umd/index.min.js" - ); +let data = documenterSearchIndex["docs"].map((x, key) => { + x["id"] = key; // minisearch requires a unique for each object + return x; +}); - let data = documenterSearchIndex.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@!]+$/, ""); + } - // 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 results + 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) { - // 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@!]+$/, ""); - - word = word.toLowerCase(); } 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: { - prefix: true, - boost: { title: 100 }, - fuzzy: 2, - }, - }); - - index.addAll(data); - - /** - * Used to map characters to HTML entities. - * Refer: https://github.com/lodash/lodash/blob/main/src/escape.ts - */ - const htmlEscapes = { - "&": "&", - "<": "<", - ">": ">", - '"': """, - "'": "'", - }; - - /** - * Used to match HTML entities and HTML characters. - * Refer: https://github.com/lodash/lodash/blob/main/src/escape.ts - */ - const reUnescapedHtml = /[&<>"']/g; - const reHasUnescapedHtml = RegExp(reUnescapedHtml.source); - - /** - * Escape function from lodash - * Refer: https://github.com/lodash/lodash/blob/main/src/escape.ts - */ - function escape(string) { - return string && reHasUnescapedHtml.test(string) - ? string.replace(reUnescapedHtml, (chr) => htmlEscapes[chr]) - : string || ""; - } - - /** - * 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(`${querystring}`, "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 - - text = text.length ? escape(text) : ""; - - let display_result = text.length - ? "..." + - text.replace( - new RegExp(`${escape(querystring)}`, "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 = ` - -
-
${escape(result.title)}
-
${result.category}
-
-

- ${display_result} -

-
- ${display_link} -
-
- ${search_divider} - `; - - return result_div; - } - - self.onmessage = function (e) { - let query = e.data; - let results = index.search(query, { - filter: (result) => { - // Only return relevant results - return result.score >= 1; - }, - }); - - // Pre-filter to deduplicate and limit to 200 per category to the extent - // possible without knowing what the filters are. - let filtered_results = []; - let counts = {}; - for (let filter of filters) { - counts[filter] = 0; - } - let present = {}; - - for (let result of results) { - cat = result.category; - cnt = counts[cat]; - if (cnt < 200) { - id = cat + "---" + result.location; - if (present[id]) { - continue; - } - present[id] = true; - filtered_results.push({ - location: result.location, - category: cat, - div: make_search_result(result, query), - }); - } - } - - postMessage(filtered_results); - }; -} - -// `worker = Threads.@spawn worker_function(documenterSearchIndex)`, but in JavaScript! -const filters = [ - ...new Set(documenterSearchIndex["docs"].map((x) => x.category)), -]; -const worker_str = - "(" + - worker_function.toString() + - ")(" + - JSON.stringify(documenterSearchIndex["docs"]) + - "," + - JSON.stringify(documenterBaseURL) + - "," + - JSON.stringify(filters) + - ")"; -const worker_blob = new Blob([worker_str], { type: "text/javascript" }); -const worker = new Worker(URL.createObjectURL(worker_blob)); - -/////// SEARCH MAIN /////// - -// Whether the worker is currently handling a search. This is a boolean -// as the worker only ever handles 1 or 0 searches at a time. -var worker_is_running = false; - -// The last search text that was sent to the worker. This is used to determine -// if the worker should be launched again when it reports back results. -var last_search_text = ""; - -// The results of the last search. This, in combination with the state of the filters -// in the DOM, is used compute the results to display on calls to update_search. -var unfiltered_results = []; - -// Which filter is currently selected -var selected_filter = ""; - -$(document).on("input", ".documenter-search-input", function (event) { - if (!worker_is_running) { - launch_search(); - } + }, }); -function launch_search() { - worker_is_running = true; - last_search_text = $(".documenter-search-input").val(); - worker.postMessage(last_search_text); -} +index.addAll(data); -worker.onmessage = function (e) { - if (last_search_text !== $(".documenter-search-input").val()) { - launch_search(); - } else { - worker_is_running = false; - } +let filters = [...new Set(data.map((x) => x.category))]; +var modal_filters = make_modal_body_filters(filters); +var filter_results = []; - unfiltered_results = e.data; - update_search(); -}; +$(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")) { - selected_filter = ""; + $(this).removeClass("search-filter-selected"); } else { - selected_filter = $(this).text().toLowerCase(); + $(this).addClass("search-filter-selected"); } - // This updates search results and toggles classes for UI: - update_search(); + // 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() { +function update_search(selected_filters = []) { + let initial_search_body = ` +
Type something to get started!
+ `; + let querystring = $(".documenter-search-input").val(); if (querystring.trim()) { - if (selected_filter == "") { - results = unfiltered_results; - } else { - results = unfiltered_results.filter((result) => { - return selected_filter == result.category.toLowerCase(); - }); - } + 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 modal_filters = make_modal_body_filters(); let search_divider = `
`; if (results.length) { @@ -690,23 +449,19 @@ function update_search() { let count = 0; let search_results = ""; - for (var i = 0, n = results.length; i < n && count < 200; ++i) { - let result = results[i]; - if (result.location && !links.includes(result.location)) { - search_results += result.div; - count++; + 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); } - } + }); - if (count == 1) { - count_str = "1 result"; - } else if (count == 200) { - count_str = "200+ results"; - } else { - count_str = count + " results"; - } - let result_count = `
${count_str}
`; + let result_count = `
${count} result(s)
`; search_result_container = `
@@ -735,37 +490,125 @@ function update_search() { $(".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(` -
Type something to get started!
- `); + $(".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() { - let str = filters - .map((val) => { - if (selected_filter == val.toLowerCase()) { - return `${val}`; - } else { - return `${val}`; - } - }) - .join(""); +function make_modal_body_filters(filters, selected_filters = []) { + let str = ``; + + filters.forEach((val) => { + if (selected_filters.includes(val)) { + str += `${val}`; + } else { + str += `${val}`; + } + }); - return ` + 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); } }) @@ -792,107 +635,103 @@ $(document).ready(function () { //////////////////////////////////////////////////////////////////////////////// require(['jquery'], function($) { -$(document).ready(function () { - let search_modal_header = ` - - `; + + ` +); - let initial_search_body = ` -
Type something to get started!
- `; +document.querySelector(".docs-search-query").addEventListener("click", () => { + openModal(); +}); - let search_modal_footer = ` - - `; +document.querySelector(".close-search-modal").addEventListener("click", () => { + closeModal(); +}); - $(document.body).append( - ` - - ` - ); +$(document).on("click", ".search-result-link", function () { + closeModal(); +}); - document.querySelector(".docs-search-query").addEventListener("click", () => { +document.addEventListener("keydown", (event) => { + if ((event.ctrlKey || event.metaKey) && event.key === "/") { openModal(); - }); - - document - .querySelector(".close-search-modal") - .addEventListener("click", () => { - closeModal(); - }); - - $(document).on("click", ".search-result-link", function () { + } else if (event.key === "Escape") { 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"); + return false; +}); - searchModal.classList.add("is-active"); - document.querySelector(".documenter-search-input").focus(); - } +// Functions to open and close a modal +function openModal() { + let searchModal = document.querySelector("#search-modal"); - function closeModal() { - let searchModal = document.querySelector("#search-modal"); - let initial_search_body = ` -
Type something to get started!
- `; + searchModal.classList.add("is-active"); + document.querySelector(".documenter-search-input").focus(); +} - searchModal.classList.remove("is-active"); - document.querySelector(".documenter-search-input").blur(); +function closeModal() { + let searchModal = document.querySelector("#search-modal"); + let initial_search_body = ` +
Type something to get started!
+ `; - if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) { - $(".search-modal-card-body").addClass("is-justify-content-center"); - } + searchModal.classList.remove("is-active"); + document.querySelector(".documenter-search-input").blur(); - $(".documenter-search-input").val(""); - $(".search-modal-card-body").html(initial_search_body); + if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) { + $(".search-modal-card-body").addClass("is-justify-content-center"); } - document - .querySelector("#search-modal .modal-background") - .addEventListener("click", () => { - closeModal(); - }); -}); + $(".documenter-search-input").val(""); + $(".search-modal-card-body").html(initial_search_body); +} + +document + .querySelector("#search-modal .modal-background") + .addEventListener("click", () => { + closeModal(); + }); }) //////////////////////////////////////////////////////////////////////////////// diff --git a/dev/assets/themes/documenter-dark.css b/dev/assets/themes/documenter-dark.css index 53889fb9..9f5449f4 100644 --- a/dev/assets/themes/documenter-dark.css +++ b/dev/assets/themes/documenter-dark.css @@ -4,4 +4,4 @@ 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 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;overflow:auto}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;overflow-x:hidden}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}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 .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 !important;background-color:#f1f5f9 !important}html.theme--documenter-dark .search-result-title{color:whitesmoke}html.theme--documenter-dark .search-result-highlight{background-color:greenyellow;color:black}html.theme--documenter-dark .search-divider{border-bottom:1px solid #5e6d6f50}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 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;overflow:auto}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;overflow-x:hidden}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}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 .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 !important;background-color:#f1f5f9 !important}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:whitesmoke;background-color:#33415580;border-radius:0.6rem}html.theme--documenter-dark .search-result-title{color:whitesmoke}html.theme--documenter-dark .search-result-highlight{background-color:greenyellow;color:black}html.theme--documenter-dark .search-divider{border-bottom:1px solid #5e6d6f50}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} diff --git a/dev/calibrate/index.html b/dev/calibrate/index.html index 2015ffaf..462acacf 100644 --- a/dev/calibrate/index.html +++ b/dev/calibrate/index.html @@ -1,2 +1,2 @@ -Calibrate · CalibrateEmulateSample.jl

The Calibrate stage

Calibration of the computer model entails finding an optimal parameter $\theta^*$ that maximizes the posterior probability

\[\rho(\theta\vert y, \Gamma_y) = \dfrac{e^{-\mathcal{L}(\theta; y)}}{Z(y\vert\Gamma_y)}\rho_{\mathrm{prior}}(\theta), \qquad \mathcal{L}(\theta, y) = \langle \mathcal{G}(\theta) - y \, , \, \Gamma_y^{-1} \left ( \mathcal{G}(\theta) - y \right ) \rangle,\]

where $\mathcal{L}$ is the loss or negative log-likelihood, $Z(y\vert\Gamma)$ is a normalizing constant, $y$ represents the data, $\Gamma_y$ is the noise covariance matrix and $\rho_{\mathrm{prior}}(\theta)$ is the prior density. Calibration is performed using ensemble Kalman processes, which generate input-output pairs $\{\theta, \mathcal{G}(\theta)\}$ in high density from the prior initial guess to the found optimal parameter $\theta^*$. These input-output pairs are then used as the data to train an emulator of the forward model $\mathcal{G}$.

Ensemble Kalman Processes

Calibration can be performed using different ensemble Kalman processes: ensemble Kalman inversion (Iglesias et al, 2013), ensemble Kalman sampler (Garbuno-Inigo et al, 2020), and unscented Kalman inversion (Huang et al, 2022). All algorithms are implemented in EnsembleKalmanProcesses.jl. Documentation of each algorithm is available in the EnsembleKalmanProcesses docs.

Typical construction of the EnsembleKalmanProcess

Documentation on how to construct an EnsembleKalmanProcess from the computer model and the data can be found in the EnsembleKalmanProcesses docs.

Julia-free forward model

One draw of our approach is that it does not require the forward map to be written in Julia. To aid construction of such a workflow, EnsembleKalmanProcesses.jl provides a documented example of a BASH workflow for the sinusoid problem, with source code here. The forward map interacts with the calibration tools (EKP) only though TOML file reading an writing, and thus can be written in any language; for example, to be used with slurm HPC scripts, with source code here.

+Calibrate · CalibrateEmulateSample.jl

The Calibrate stage

Calibration of the computer model entails finding an optimal parameter $\theta^*$ that maximizes the posterior probability

\[\rho(\theta\vert y, \Gamma_y) = \dfrac{e^{-\mathcal{L}(\theta; y)}}{Z(y\vert\Gamma_y)}\rho_{\mathrm{prior}}(\theta), \qquad \mathcal{L}(\theta, y) = \langle \mathcal{G}(\theta) - y \, , \, \Gamma_y^{-1} \left ( \mathcal{G}(\theta) - y \right ) \rangle,\]

where $\mathcal{L}$ is the loss or negative log-likelihood, $Z(y\vert\Gamma)$ is a normalizing constant, $y$ represents the data, $\Gamma_y$ is the noise covariance matrix and $\rho_{\mathrm{prior}}(\theta)$ is the prior density. Calibration is performed using ensemble Kalman processes, which generate input-output pairs $\{\theta, \mathcal{G}(\theta)\}$ in high density from the prior initial guess to the found optimal parameter $\theta^*$. These input-output pairs are then used as the data to train an emulator of the forward model $\mathcal{G}$.

Ensemble Kalman Processes

Calibration can be performed using different ensemble Kalman processes: ensemble Kalman inversion (Iglesias et al, 2013), ensemble Kalman sampler (Garbuno-Inigo et al, 2020), and unscented Kalman inversion (Huang et al, 2022). All algorithms are implemented in EnsembleKalmanProcesses.jl. Documentation of each algorithm is available in the EnsembleKalmanProcesses docs.

Typical construction of the EnsembleKalmanProcess

Documentation on how to construct an EnsembleKalmanProcess from the computer model and the data can be found in the EnsembleKalmanProcesses docs.

Julia-free forward model

One draw of our approach is that it does not require the forward map to be written in Julia. To aid construction of such a workflow, EnsembleKalmanProcesses.jl provides a documented example of a BASH workflow for the sinusoid problem, with source code here. The forward map interacts with the calibration tools (EKP) only though TOML file reading an writing, and thus can be written in any language; for example, to be used with slurm HPC scripts, with source code here.

diff --git a/dev/contributing/index.html b/dev/contributing/index.html index ed5f26e5..5d4a0d3e 100644 --- a/dev/contributing/index.html +++ b/dev/contributing/index.html @@ -30,4 +30,4 @@ # s, squash = use commit, but meld into previous commit # # If you remove a line here THAT COMMIT WILL BE LOST. - # However, if you remove everything, the rebase will be aborted.

Then in the next screen that appears, we can just delete all messages that we do not want to show in the commit. After this is done and we are back to the console, we have to force push. We need to force push because we rewrote the local commit history.

$ git push -u origin <name_of_local_branch> --force

You can find more information about squashing here.

Unit testing

Currently a number of checks are run per commit for a given PR.

Unit tests are run against every new commit for a given PR, the status of the unit-tests are not checked during the merge process but act as a sanity check for developers and reviewers. Depending on the content changed in the PR, some CI checks that are not necessary will be skipped. For example doc only changes do not require the unit tests to be run.

The merge process

We ensure that all unit tests across several environments, Documentation builds, and integration tests (managed by Buildkite), pass before merging any PR into main. The integration tests currently run some of our example cases in examples/.

+ # However, if you remove everything, the rebase will be aborted.

Then in the next screen that appears, we can just delete all messages that we do not want to show in the commit. After this is done and we are back to the console, we have to force push. We need to force push because we rewrote the local commit history.

$ git push -u origin <name_of_local_branch> --force

You can find more information about squashing here.

Unit testing

Currently a number of checks are run per commit for a given PR.

Unit tests are run against every new commit for a given PR, the status of the unit-tests are not checked during the merge process but act as a sanity check for developers and reviewers. Depending on the content changed in the PR, some CI checks that are not necessary will be skipped. For example doc only changes do not require the unit tests to be run.

The merge process

We ensure that all unit tests across several environments, Documentation builds, and integration tests (managed by Buildkite), pass before merging any PR into main. The integration tests currently run some of our example cases in examples/.

diff --git a/dev/emulate/index.html b/dev/emulate/index.html index 41a9ffff..48e2951f 100644 --- a/dev/emulate/index.html +++ b/dev/emulate/index.html @@ -10,4 +10,4 @@ retained_svd_frac = 0.95, )

The optional arguments above relate to the data processing.

Emulator Training

The emulator is trained when we combine the machine learning tool and the data into the Emulator above. For any machine learning tool, hyperparameters are optimized.

optimize_hyperparameters!(emulator)

For some machine learning packages however, this may be completed during construction automatically, and for others this will not. If automatic construction took place, the optimize_hyperparameters! line does not perform any new task, so may be safely called. In the Lorenz example, this line learns the hyperparameters of the Gaussian process, which depend on the choice of kernel, and the choice of GP package. Predictions at new inputs can then be made using

y, cov = Emulator.predict(emulator, new_inputs)

This returns both a mean value and a covariance.

Data processing

Some effects of the following are outlined in a practical setting in the results and appendices of Howland, Dunbar, Schneider, (2022).

Diagonalization and output dimension reduction

This arises from the optional arguments

We always use singular value decomposition to diagonalize the output space, requiring output covariance Γy. Why? If we need to train a $\mathbb{R}^{10} \to \mathbb{R}^{100}$ emulator, diagonalization allows us to instead train 100 $\mathbb{R}^{10} \to \mathbb{R}^{1}$ emulators (far cheaper).

Performance is increased further by throwing away less informative output dimensions, if 95% of the information (i.e., variance) is in the first 40 diagonalized output dimensions then setting retained_svd_frac=0.95 will train only 40 emulators.

Note

Diagonalization is an approximation. It is however a good approximation when the observational covariance varies slowly in the parameter space.

Warn

Severe approximation errors can occur if obs_noise_cov is not provided.

Normalization and standardization

This arises from the optional arguments

We normalize the input data in a standard way by centering, and scaling with the empirical covariance

To help with poor conditioning of the covariance matrix, users can also standardize each output dimension with by a multiplicative factor given by the elements of factor_vector.

Modular interface

Developers may contribute new tools by performing the following

  1. Create MyMLToolName.jl, and include "MyMLToolName.jl" in Emulators.jl
  2. Create a struct MyMLTool <: MachineLearningTool, containing any arguments or optimizer options
  3. Create the following three methods to build, train, and predict with your tool (use GaussianProcess.jl as a guide)
build_models!(mlt::MyMLTool, iopairs::PairedDataContainer) -> Nothing
 optimize_hyperparameters!(mlt::MyMLTool, args...; kwargs...) -> Nothing
-function predict(mlt::MyMLTool, new_inputs::Matrix; kwargs...) -> Matrix, Union{Matrix, Array{,3}
on dimensions of the predict inputs and outputs

The predict method takes as input, an input_dim-by-N_new matrix. It return both a predicted mean and a predicted (co)variance at new inputs. (i) for scalar-output methods relying on diagonalization, return output_dim-by-N_new matrices for mean and variance, (ii) For vector-output methods, return output_dim-by-N_new for mean and output_dim-by-output_dim-by-N_new for covariances.

Please get in touch with our development team when contributing new statistical emulators, to help us ensure the smoothest interface with any new tools.

+function predict(mlt::MyMLTool, new_inputs::Matrix; kwargs...) -> Matrix, Union{Matrix, Array{,3}
on dimensions of the predict inputs and outputs

The predict method takes as input, an input_dim-by-N_new matrix. It return both a predicted mean and a predicted (co)variance at new inputs. (i) for scalar-output methods relying on diagonalization, return output_dim-by-N_new matrices for mean and variance, (ii) For vector-output methods, return output_dim-by-N_new for mean and output_dim-by-output_dim-by-N_new for covariances.

Please get in touch with our development team when contributing new statistical emulators, to help us ensure the smoothest interface with any new tools.

diff --git a/dev/examples/Cloudy_example/index.html b/dev/examples/Cloudy_example/index.html index cf56a762..98724f6e 100644 --- a/dev/examples/Cloudy_example/index.html +++ b/dev/examples/Cloudy_example/index.html @@ -242,4 +242,4 @@ # Setting title and labels ax.title = param_names[idx] ax.xlabel = "Value" - ax.ylabel = "Density"

This is what the marginal distributions of the three parameters look like, for the case of the GP emulator, and in the constrained/physical space:

posterior_N0_gpjl

posterior_theta_gpjl

posterior_k_gpjl

Here, the posterior distributions are shown as orange histograms, the prior distribution are shown as grey histograms (though with the exception of the parmaeter k, they are barely visible), and the true parameter values are marked as vertical purple lines.

Appendix: What Does Cloudy Do?

For the purpose of Bayesian parameter learning, the forward model can be treated as a black box that processes input parameters to yield specific outputs. However, for those who wish to learn more about the inner workings of Cloudy, we refer to his paper and offer a brief outline below:

The mathematical starting point of Cloudy is the stochastic collection equation (SCE; sometimes also called Smoluchowski equation after Marian Smoluchowski), which describes the time rate of change of $f = f(m, t)$, the mass distribution function of liquid water droplets, due to the process of collision and coalescence. The distribution function $f$ depends on droplet mass $m$ and time $t$ and is defined such that $f(m) \text{ d}m$ denotes the number of droplets with masses in the interval $[m, m + dm]$ per unit volume.

The stochastic collection equation is an integro-differential equation that can be written as

\[ \frac{\partial f(m, t)}{\partial t} = \frac{1}{2} \int_{m'=0}^{\infty} f(m', t) f(m-m', t) \mathcal{C}(m', m-m')\text{d}m' - f(m, t) \int_{m'=0}^\infty f(m', t)\mathcal{C}(m, m') \text{d}m', \]

where $\mathcal{C}(m', m'')$ is the collision-coalescence kernel, which encapsulates the physics of droplet-droplet interactions – it describes the rate at which two drops of masses $m'$ and $m''$ come into contact and coalesce into a drop of mass $m' + m''$. The first term on the right-hand side of the SCE describes the rate of increase of the number of drops having a mass $m$ due to collision and coalescence of drops of masses $m'$ and $m-m'$ (where the factor $\frac{1}{2}$ avoids double counting), while the second term describes the rate of reduction of drops of mass $m$ due to collision and coalescence of drops having a mass $m$ with other drops.

We can rewrite the SCE in terms of the moments $M_k$ of $f$, which are the prognostic variables in Cloudy. They are defined by

\[ M_k = \int_0^\infty m^k f(m, t) \text{d}m\]

The time rate of change of the k-th moment of $f$ is obtained by multiplying the SCE by $m^k$ and integrating over the entire range of droplet masses (from $m=0$ to $\infty$), which yields

\[ \frac{\partial M_k(t)}{\partial t} = \frac{1}{2}\int_0^\infty \left((m+m')^k - m^k - {m'}^k\right) \mathcal{C}(m, m')f(m, t)f(m', t) \, \text{d}m\, \text{d}m' ~~~~~~~~ (1)\]

In this example, the kernel is set to be constant – $\mathcal{C}(m', m'') = B = \text{const}$ – and the cloud droplet mass distribution is assumed to be a $\text{Gamma}(k_t, \theta_t)$ distribution, scaled by a factor $N_{0,t}$ which denotes the droplet number concentration:

\[f(m, t) = \frac{N_{0,t}}{\Gamma(k_t)\theta_t^k} m^{k_t-1} \exp{(-m/\theta_t)}\]

The parameter vector $\phi_t= [N_{0,t}, k_t, \theta_t]$ changes over time (as indicated by the subscript $t$), as the shape of the distribution evolves. In fact, there is a priori no reason to assume that the distribution would retain its Gamma shape over time, but this is a common assumption that is made in order to solve the closure problem (without this assumption, one would have to keep track of infinitely many moments of the mass distribution in order to uniquely identify the distribution $f$ at each time step, which is obviously not practicable).

For Gamma mass distribution functions, specifying the first three moments ($M_0$, $M_1$, and $M_2$) is sufficient to uniquely determine the parameter vector $\phi_t$, hence Cloudy solves equation (1) for $k = 0, 1, 2$. This mapping of the parameters of the initial cloud droplet mass distribution to the (zeroth-, first-, and second-order) moments of the distribution at a specified end time is done by DynamicalModel.jl.

+ ax.ylabel = "Density"

This is what the marginal distributions of the three parameters look like, for the case of the GP emulator, and in the constrained/physical space:

posterior_N0_gpjl

posterior_theta_gpjl

posterior_k_gpjl

Here, the posterior distributions are shown as orange histograms, the prior distribution are shown as grey histograms (though with the exception of the parmaeter k, they are barely visible), and the true parameter values are marked as vertical purple lines.

Appendix: What Does Cloudy Do?

For the purpose of Bayesian parameter learning, the forward model can be treated as a black box that processes input parameters to yield specific outputs. However, for those who wish to learn more about the inner workings of Cloudy, we refer to his paper and offer a brief outline below:

The mathematical starting point of Cloudy is the stochastic collection equation (SCE; sometimes also called Smoluchowski equation after Marian Smoluchowski), which describes the time rate of change of $f = f(m, t)$, the mass distribution function of liquid water droplets, due to the process of collision and coalescence. The distribution function $f$ depends on droplet mass $m$ and time $t$ and is defined such that $f(m) \text{ d}m$ denotes the number of droplets with masses in the interval $[m, m + dm]$ per unit volume.

The stochastic collection equation is an integro-differential equation that can be written as

\[ \frac{\partial f(m, t)}{\partial t} = \frac{1}{2} \int_{m'=0}^{\infty} f(m', t) f(m-m', t) \mathcal{C}(m', m-m')\text{d}m' - f(m, t) \int_{m'=0}^\infty f(m', t)\mathcal{C}(m, m') \text{d}m', \]

where $\mathcal{C}(m', m'')$ is the collision-coalescence kernel, which encapsulates the physics of droplet-droplet interactions – it describes the rate at which two drops of masses $m'$ and $m''$ come into contact and coalesce into a drop of mass $m' + m''$. The first term on the right-hand side of the SCE describes the rate of increase of the number of drops having a mass $m$ due to collision and coalescence of drops of masses $m'$ and $m-m'$ (where the factor $\frac{1}{2}$ avoids double counting), while the second term describes the rate of reduction of drops of mass $m$ due to collision and coalescence of drops having a mass $m$ with other drops.

We can rewrite the SCE in terms of the moments $M_k$ of $f$, which are the prognostic variables in Cloudy. They are defined by

\[ M_k = \int_0^\infty m^k f(m, t) \text{d}m\]

The time rate of change of the k-th moment of $f$ is obtained by multiplying the SCE by $m^k$ and integrating over the entire range of droplet masses (from $m=0$ to $\infty$), which yields

\[ \frac{\partial M_k(t)}{\partial t} = \frac{1}{2}\int_0^\infty \left((m+m')^k - m^k - {m'}^k\right) \mathcal{C}(m, m')f(m, t)f(m', t) \, \text{d}m\, \text{d}m' ~~~~~~~~ (1)\]

In this example, the kernel is set to be constant – $\mathcal{C}(m', m'') = B = \text{const}$ – and the cloud droplet mass distribution is assumed to be a $\text{Gamma}(k_t, \theta_t)$ distribution, scaled by a factor $N_{0,t}$ which denotes the droplet number concentration:

\[f(m, t) = \frac{N_{0,t}}{\Gamma(k_t)\theta_t^k} m^{k_t-1} \exp{(-m/\theta_t)}\]

The parameter vector $\phi_t= [N_{0,t}, k_t, \theta_t]$ changes over time (as indicated by the subscript $t$), as the shape of the distribution evolves. In fact, there is a priori no reason to assume that the distribution would retain its Gamma shape over time, but this is a common assumption that is made in order to solve the closure problem (without this assumption, one would have to keep track of infinitely many moments of the mass distribution in order to uniquely identify the distribution $f$ at each time step, which is obviously not practicable).

For Gamma mass distribution functions, specifying the first three moments ($M_0$, $M_1$, and $M_2$) is sufficient to uniquely determine the parameter vector $\phi_t$, hence Cloudy solves equation (1) for $k = 0, 1, 2$. This mapping of the parameters of the initial cloud droplet mass distribution to the (zeroth-, first-, and second-order) moments of the distribution at a specified end time is done by DynamicalModel.jl.

diff --git a/dev/examples/edmf_example/index.html b/dev/examples/edmf_example/index.html index abaaa74f..ec3e13bb 100644 --- a/dev/examples/edmf_example/index.html +++ b/dev/examples/edmf_example/index.html @@ -7,4 +7,4 @@ using CalibrateEmulateSample.ParameterDistribution posterior = load(posterior_filepath)["posterior"] posterior_samples = vcat([get_distribution(posterior)[name] for name in get_name(posterior)]...) # samples are columns

To transform these samples into physical parameter space use the following:

transformed_posterior_samples =
-mapslices(x -> transform_unconstrained_to_constrained(posterior, x), posterior_samples, dims = 1)
Computational vs Physical space

The computational $\theta$-space are the parameters on which the algorithms act. Statistics (e.g. mean/covariance) are most meaningful when taken in this space. The physical $\phi$-space is a (nonlinear) transformation of the computational space to apply parameter constraints. To pass parameter values back into the forward model, one must transform them. Full details and examples can be found here

+mapslices(x -> transform_unconstrained_to_constrained(posterior, x), posterior_samples, dims = 1)
Computational vs Physical space

The computational $\theta$-space are the parameters on which the algorithms act. Statistics (e.g. mean/covariance) are most meaningful when taken in this space. The physical $\phi$-space is a (nonlinear) transformation of the computational space to apply parameter constraints. To pass parameter values back into the forward model, one must transform them. Full details and examples can be found here

diff --git a/dev/examples/emulators/ishigami_3d_1d/index.html b/dev/examples/emulators/ishigami_3d_1d/index.html index 09d6eb21..f2a88869 100644 --- a/dev/examples/emulators/ishigami_3d_1d/index.html +++ b/dev/examples/emulators/ishigami_3d_1d/index.html @@ -90,4 +90,4 @@ (std) firstorder: [0.05909336956162543, 0.11484966121124164, 0.012908533302492602] (mean) totalorder: [0.5670345355855254, 0.4716028261179354, 0.24108222433317] (std) totalorder: [0.10619345801872732, 0.1041023777237331, 0.07200225781785778] - + diff --git a/dev/examples/emulators/lorenz_integrator_3d_3d/index.html b/dev/examples/emulators/lorenz_integrator_3d_3d/index.html index eafcbd34..c7001856 100644 --- a/dev/examples/emulators/lorenz_integrator_3d_3d/index.html +++ b/dev/examples/emulators/lorenz_integrator_3d_3d/index.html @@ -79,4 +79,4 @@ u_test_tmp[:, i + 1] = rf_mean end

The other trajectories are similar. We then produce the following plots. In all figures, the results from evolving the state with the true integrator is orange, and with the emulated integrators are blue.

Gaussian Process Emulator (Sci-kit learn: GP)

For one example fit

Random Feature Emulator (RF-nosvd-nonsep)

For one example fit

-

and here are CDFs over 20 randomized trials of the random feature hyperparameter optimization

+

and here are CDFs over 20 randomized trials of the random feature hyperparameter optimization

diff --git a/dev/examples/emulators/regression_2d_2d/index.html b/dev/examples/emulators/regression_2d_2d/index.html index 56429aa8..76bf25cd 100644 --- a/dev/examples/emulators/regression_2d_2d/index.html +++ b/dev/examples/emulators/regression_2d_2d/index.html @@ -66,4 +66,4 @@ inputs = permutedims(hcat(X1[:], X2[:]), (2, 1))

We predict using the emulators at the new inputs, and transform_to_real inverts the data processing back to physical values

em_mean, em_cov = predict(emulator, inputs, transform_to_real = true)

We then plot the predicted mean and pointwise variances, and calculate the errors from the three highlighted cases:

Gaussian Process Emulator (Sci-kit learn: gp-skljl)

L^2 error of mean and latent truth:0.0008042391077774167

Random Feature Emulator (rf-scalar)

L^2 error of mean and latent truth:0.0012253119679379056

Random Feature Emulator (vector: rf-nosvd-nonsep)

L^2 error of mean and latent truth:0.0011094292509180393
- + diff --git a/dev/examples/lorenz_example/index.html b/dev/examples/lorenz_example/index.html index 4878ae66..23604597 100644 --- a/dev/examples/lorenz_example/index.html +++ b/dev/examples/lorenz_example/index.html @@ -114,4 +114,4 @@ println("True parameters: ") println(params_true) println("\nEKI results:") -println(get_ϕ_mean_final(priors, ekiobj))

The parameters and forward model outputs will be saved in parameter_storage.jld2 and data_storage.jld2, respectively. The data will be saved in the directory output. A scatter plot animation of the ensemble convergence to the true parameters is saved in the directory output. These points represent the training points that are used for the emulator.

Emulate-sample

The L96 parameter estimation can be run using julia --project emulate_sample.jl

The output will provide the estimated posterior distribution over the parameters. The emulate-sample code will run for several choices in the machine learning model that is used for the emulation stage, inclding Gaussian Process regression and RF, and using singular value data decorrelation or not.

The sampling results from two emulators are shown below. We can see that the posterior is relatively insensitive to the choice of the machine learning emulation tool in this L96 example.

L96 CES example case: GP regression emulator (case="GP")

L96 CES example case: RF scalar emulator (case="RF-scalar")

+println(get_ϕ_mean_final(priors, ekiobj))

The parameters and forward model outputs will be saved in parameter_storage.jld2 and data_storage.jld2, respectively. The data will be saved in the directory output. A scatter plot animation of the ensemble convergence to the true parameters is saved in the directory output. These points represent the training points that are used for the emulator.

Emulate-sample

The L96 parameter estimation can be run using julia --project emulate_sample.jl

The output will provide the estimated posterior distribution over the parameters. The emulate-sample code will run for several choices in the machine learning model that is used for the emulation stage, inclding Gaussian Process regression and RF, and using singular value data decorrelation or not.

The sampling results from two emulators are shown below. We can see that the posterior is relatively insensitive to the choice of the machine learning emulation tool in this L96 example.

L96 CES example case: GP regression emulator (case="GP")

L96 CES example case: RF scalar emulator (case="RF-scalar")

diff --git a/dev/examples/sinusoid_example/index.html b/dev/examples/sinusoid_example/index.html index 26c0debf..5b6a29c2 100644 --- a/dev/examples/sinusoid_example/index.html +++ b/dev/examples/sinusoid_example/index.html @@ -101,4 +101,4 @@ println("Vertical shift mean: ", mean(constrained_posterior["vert_shift"]), ", std: ", std(constrained_posterior["vert_shift"]))

This gives:

parametersmeanstd
amplitude3.03820.2880
vert_shift6.37740.4586

This is in agreement with the true $\theta=(3.0, 7.0)$ and with the observational covariance matrix we provided $\Gamma=0.2 * I$ (i.e., a standard deviation of approx. $0.45$). CalibrateEmulateSample.jl has built-in plotting recipes to help us visualize the prior and posterior distributions. Note that these are the marginal distributions.

# We can quickly plot priors and posterior using built-in capabilities
 p = plot(prior, fill = :lightgray)
 plot!(posterior, fill = :darkblue, alpha = 0.5)
-

GP_posterior

The MCMC has learned the posterior distribution which is much narrower than the prior. For multidimensional problems, the posterior is typically multidimensional, and marginal distribution plots do not show how parameters co-vary. We plot a 2D histogram of $\theta_1$ vs. $\theta_2$ below, with the marginal distributions on each axis.

GP_2d_posterior

Sample with Random Features

We can repeat the sampling method using the random features emulator instead of the Gaussian process and we find similar results:

parametersmeanstd
amplitude3.32100.7216
vert_shift6.39860.5098

RF_2d_posterior

It is reassuring to see that our uncertainty quantification methods are robust to the different emulator choices here. This is because our particular GP and RF emulators showed similar accuracy during validation. However, this result is highly sensitive to the choices of GP kernel and RF kernel structure. If you find very different posterior distributions for different emulators, it is likely that the kernel choices need be refined. The kernel choices must be flexible enough to accurately capture the relationships between the inputs and outputs. We recommend trying a variety of different emulator configurations and carefully considering emulator validation on samples that the emulator has not been trained on.

+

GP_posterior

The MCMC has learned the posterior distribution which is much narrower than the prior. For multidimensional problems, the posterior is typically multidimensional, and marginal distribution plots do not show how parameters co-vary. We plot a 2D histogram of $\theta_1$ vs. $\theta_2$ below, with the marginal distributions on each axis.

GP_2d_posterior

Sample with Random Features

We can repeat the sampling method using the random features emulator instead of the Gaussian process and we find similar results:

parametersmeanstd
amplitude3.32100.7216
vert_shift6.39860.5098

RF_2d_posterior

It is reassuring to see that our uncertainty quantification methods are robust to the different emulator choices here. This is because our particular GP and RF emulators showed similar accuracy during validation. However, this result is highly sensitive to the choices of GP kernel and RF kernel structure. If you find very different posterior distributions for different emulators, it is likely that the kernel choices need be refined. The kernel choices must be flexible enough to accurately capture the relationships between the inputs and outputs. We recommend trying a variety of different emulator configurations and carefully considering emulator validation on samples that the emulator has not been trained on.

diff --git a/dev/glossary/index.html b/dev/glossary/index.html index e3fb9244..f16aa3ec 100644 --- a/dev/glossary/index.html +++ b/dev/glossary/index.html @@ -1,2 +1,2 @@ -Glossary · CalibrateEmulateSample.jl

Glossary

The following list includes the names and symbols of recurring concepts in CalibrateEmulateSample.jl. Some of these variables do not appear in the codebase, which relies on array programming for performance. Contributions to the codebase require following this notational convention. Similarly, if you find inconsistencies in the documentation or codebase, please report an issue on GitHub.

NameSymbol (Theory/Docs)Symbol (Code)
Parameter vector, Parameters (unconstrained space)$\theta$θ
Parameter vector size, Number of parameters$p$N_par
Ensemble size$J$N_ens
Ensemble particles, members$\theta^{(j)}$
Number of iterations$N_{\rm it}$N_iter
Observation vector, Observations, Data vector$y$y
Observation vector size, Data vector size$d$N_obs
Observational noise$\eta$obs_noise
Observational noise covariance$\Gamma_y$obs_noise_cov
Hilbert space inner product$\langle \phi , \Gamma^{-1} \psi \rangle$
Forward map$\mathcal{G}$G
Dynamical model$\Psi$Ψ
Transform map (constrained to unconstrained)$\mathcal{T}$T
Observation map$\mathcal{H}$H
Prior covariance (unconstrained space)$\Gamma_{\theta}$prior_cov
Prior mean (unconstrained space)$m_\theta$prior_mean
+Glossary · CalibrateEmulateSample.jl

Glossary

The following list includes the names and symbols of recurring concepts in CalibrateEmulateSample.jl. Some of these variables do not appear in the codebase, which relies on array programming for performance. Contributions to the codebase require following this notational convention. Similarly, if you find inconsistencies in the documentation or codebase, please report an issue on GitHub.

NameSymbol (Theory/Docs)Symbol (Code)
Parameter vector, Parameters (unconstrained space)$\theta$θ
Parameter vector size, Number of parameters$p$N_par
Ensemble size$J$N_ens
Ensemble particles, members$\theta^{(j)}$
Number of iterations$N_{\rm it}$N_iter
Observation vector, Observations, Data vector$y$y
Observation vector size, Data vector size$d$N_obs
Observational noise$\eta$obs_noise
Observational noise covariance$\Gamma_y$obs_noise_cov
Hilbert space inner product$\langle \phi , \Gamma^{-1} \psi \rangle$
Forward map$\mathcal{G}$G
Dynamical model$\Psi$Ψ
Transform map (constrained to unconstrained)$\mathcal{T}$T
Observation map$\mathcal{H}$H
Prior covariance (unconstrained space)$\Gamma_{\theta}$prior_cov
Prior mean (unconstrained space)$m_\theta$prior_mean
diff --git a/dev/index.html b/dev/index.html index 303d7176..41225243 100644 --- a/dev/index.html +++ b/dev/index.html @@ -1,2 +1,2 @@ -Home · CalibrateEmulateSample.jl

CalibrateEmulateSample.jl

CalibrateEmulateSample.jl solves parameter estimation problems using accelerated (and approximate) Bayesian inversion.

The framework can be applied currently to learn:

  • the joint distribution for a moderate numbers of parameters (<40),
  • it is not inherently restricted to unimodal distributions.

It can be used with computer models that:

  • can be noisy or chaotic,
  • are non-differentiable,
  • can only be treated as black-box (interfaced only with parameter files).

The computer model is supplied by the user, as a parameter-to-data map $\mathcal{G}(\theta): \mathbb{R}^p \rightarrow \mathbb{R}^d$. For example, $\mathcal{G}$ could be a map from any given parameter configuration $\theta$ to a collection of statistics of a dynamical system trajectory. $\mathcal{G}$ is referred to as the forward model in the Bayesian inverse problem setting.

The data produced by the forward model are compared to observations $y$, which are assumed to be corrupted by additive noise $\eta$, such that

\[y = \mathcal{G}(\theta) + \eta,\]

where the noise $\eta$ is drawn from a $d$-dimensional Gaussian with distribution $\mathcal{N}(0, \Gamma_y)$.

The inverse problem

Given an observation $y$, the computer model $\mathcal{G}$, the observational noise $\Gamma_y$, and some broad prior information on $\theta$, we return the joint distribution of a data-informed distribution for "$\theta$ given $y$".

As the name suggests, CalibrateEmulateSample.jl breaks this problem into a sequence of three steps: calibration, emulation, and sampling. A comprehensive treatment of the calibrate-emulate-sample approach to Bayesian inverse problems can be found in Cleary et al. (2020).

The three steps of the algorithm: see our walkthrough of the Sinusoid Example

Learn the vertical shift and amplitude of the signal given the noisy observation

The calibrate step of the algorithm consists of an application of Ensemble Kalman Processes, which generates input-output pairs $\{\theta, \mathcal{G}(\theta)\}$ in high density around an optimal parameter $\theta^*$. Here, $\theta$ are amplitude and vertical shift pairs, and $\mathcal{G}(\theta)$ are the resulting signal mean and range. This $\theta^*$ will be near a mode of the posterior distribution (Note: This is the only time we interface with the forward model $\mathcal{G}$).

calibrate with EKP to generate data pairs...

The emulate step takes these pairs $\{\theta, \mathcal{G}(\theta)\}$ and trains a statistical surrogate model (e.g., a Gaussian process), emulating the forward map $\mathcal{G}$.

emulate the map statistically from EKP pairs...

The sample step uses this surrogate in place of $\mathcal{G}$ in a sampling method (Markov chain Monte Carlo) to sample the posterior distribution of $\theta$.

sample the emulated map with MCMC...

Code Components

CalibrateEmulateSample.jl contains the following modules:

ModulePurpose
CalibrateEmulateSample.jlA wrapper for the pipeline
Emulator.jlModular template for the emulators
GaussianProcess.jlA Gaussian process emulator
Scalar/VectorRandomFeatureInterface.jlA Scalar/Vector-output Random Feature emulator
MarkovChainMonteCarlo.jlModular template for Markov Chain Monte Carlo samplers
Utilities.jlHelper functions

Authors

CalibrateEmulateSample.jl is being developed by the Climate Modeling Alliance.

+Home · CalibrateEmulateSample.jl

CalibrateEmulateSample.jl

CalibrateEmulateSample.jl solves parameter estimation problems using accelerated (and approximate) Bayesian inversion.

The framework can be applied currently to learn:

  • the joint distribution for a moderate numbers of parameters (<40),
  • it is not inherently restricted to unimodal distributions.

It can be used with computer models that:

  • can be noisy or chaotic,
  • are non-differentiable,
  • can only be treated as black-box (interfaced only with parameter files).

The computer model is supplied by the user, as a parameter-to-data map $\mathcal{G}(\theta): \mathbb{R}^p \rightarrow \mathbb{R}^d$. For example, $\mathcal{G}$ could be a map from any given parameter configuration $\theta$ to a collection of statistics of a dynamical system trajectory. $\mathcal{G}$ is referred to as the forward model in the Bayesian inverse problem setting.

The data produced by the forward model are compared to observations $y$, which are assumed to be corrupted by additive noise $\eta$, such that

\[y = \mathcal{G}(\theta) + \eta,\]

where the noise $\eta$ is drawn from a $d$-dimensional Gaussian with distribution $\mathcal{N}(0, \Gamma_y)$.

The inverse problem

Given an observation $y$, the computer model $\mathcal{G}$, the observational noise $\Gamma_y$, and some broad prior information on $\theta$, we return the joint distribution of a data-informed distribution for "$\theta$ given $y$".

As the name suggests, CalibrateEmulateSample.jl breaks this problem into a sequence of three steps: calibration, emulation, and sampling. A comprehensive treatment of the calibrate-emulate-sample approach to Bayesian inverse problems can be found in Cleary et al. (2020).

The three steps of the algorithm: see our walkthrough of the Sinusoid Example

Learn the vertical shift and amplitude of the signal given the noisy observation

The calibrate step of the algorithm consists of an application of Ensemble Kalman Processes, which generates input-output pairs $\{\theta, \mathcal{G}(\theta)\}$ in high density around an optimal parameter $\theta^*$. Here, $\theta$ are amplitude and vertical shift pairs, and $\mathcal{G}(\theta)$ are the resulting signal mean and range. This $\theta^*$ will be near a mode of the posterior distribution (Note: This is the only time we interface with the forward model $\mathcal{G}$).

calibrate with EKP to generate data pairs...

The emulate step takes these pairs $\{\theta, \mathcal{G}(\theta)\}$ and trains a statistical surrogate model (e.g., a Gaussian process), emulating the forward map $\mathcal{G}$.

emulate the map statistically from EKP pairs...

The sample step uses this surrogate in place of $\mathcal{G}$ in a sampling method (Markov chain Monte Carlo) to sample the posterior distribution of $\theta$.

sample the emulated map with MCMC...

Code Components

CalibrateEmulateSample.jl contains the following modules:

ModulePurpose
CalibrateEmulateSample.jlA wrapper for the pipeline
Emulator.jlModular template for the emulators
GaussianProcess.jlA Gaussian process emulator
Scalar/VectorRandomFeatureInterface.jlA Scalar/Vector-output Random Feature emulator
MarkovChainMonteCarlo.jlModular template for Markov Chain Monte Carlo samplers
Utilities.jlHelper functions

Authors

CalibrateEmulateSample.jl is being developed by the Climate Modeling Alliance.

diff --git a/dev/installation_instructions/index.html b/dev/installation_instructions/index.html index 0937c3d9..ed881eb6 100644 --- a/dev/installation_instructions/index.html +++ b/dev/installation_instructions/index.html @@ -8,4 +8,4 @@ > PYTHON="" julia --project -e 'using Conda; Conda.add("scikit-learn=1.1.1")'

See the PyCall.jl documentation for more information about how to configure the local Julia / Conda / Python environment.

To test that the package is working:

> julia --project -e 'using Pkg; Pkg.test()'

Building the documentation locally

You need to first build the top-level project before building the documentation:

cd CalibrateEmulateSample.jl
 julia --project -e 'using Pkg; Pkg.instantiate()'

Then you can build the project documentation under the docs/ sub-project:

julia --project=docs/ -e 'using Pkg; Pkg.instantiate()'
-julia --project=docs/ docs/make.jl

The locally rendered HTML documentation can be viewed at docs/build/index.html. Occasional figures may only be viewable in the online documentation due to the fancy-url package.

+julia --project=docs/ docs/make.jl

The locally rendered HTML documentation can be viewed at docs/build/index.html. Occasional figures may only be viewable in the online documentation due to the fancy-url package.

diff --git a/dev/objects.inv b/dev/objects.inv deleted file mode 100644 index 3a2e74df6ed443af76478de0d05717ce81354adb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4557 zcmV;;5i;&0AX9K?X>NERX>N99Zgg*Qc_4OWa&u{KZXhxWBOp+6Z)#;@bUGkIVQgt) za$$63MQwF#VRU6vVQp}1WiD!L3L_v^WpZMd? zav*PJAarPHb0B7EY-J#6b0A}HZE$jBb8}^6Aa!$TZf78RY-wUH3V595Tw8D3I2L}_ zui#D_pasID<4!u$po`tsY0^yN)`-*T!_KZDTePi47QMP8^%VW@dw3N^QL=2SGX)kX z8e8J|cu1c6VG_mx`Ha#mI1T6&;U5utLzl!0<23W5$j?F=kJ*?B15s9ay3e}Hj9;_R|%0po1 z_;&|a%N&k_Ch2iP<_Sqtc4)l-{<(Rq9e#|i^%F#AXz6E*$>jP!J(N-7OS+^qTcBAU z^MiLWA~!UQGXP|d#!mzIw}GD;DkgK{2@@=NHqV}-`w+PBVgr$S`s5lvG+S(`)DGrq_CllO9Xd8}A2nWfSTARsYG;8d7+Br|_X zIHk3Ao8Efu*b+8MEKRM<#wfq7ZUh@M@RM75*I)QyJOGnN`hF5o8^}567&#wv)DKx0 zfdE!n(l3sY{^*^NI}*_qUei3m^87eq(M|+N|xs-Cp{BvtEUu-WWDlyGJ}r=n`L*9L>?E$YM?EI@=zBflLgtQYm@`W(kJy$j%f*n-vLjiOxVLm$*l0cUMZ z0w-=+v|^ts40+di9E0(|APM-j;0LrZz(bm5D`8PpJXq!13cO%fBpd=bB;i2Y0#t_c zWE9FK*4|SvNk(qnst;*l)&dUI!g<`yfE7qj@eQ0SGYl2ok`C{I9((ZgWodK)f{e%9 z#Oj$bFf+FewGJ1g?d%&t1&sFIfu6vlKllRq3BdC>@RLA3t2H$xO1{|^rH(kTbdiRD zrqdALh8d2CpTziLxLHDNV_Of-%#a1oWYc!ohIGo|h!01=4Y%yj!nQUVioMsCU6*UMjb%w>Ut1Pj(|AI`FpK7K*+|tL zk;{^gWCqA`0y`YLT&`%6!O>4|{W<7L%C~<>14z!=i-ABv1q$D3iK66em4qPUJS1T! zxx2IpARcV6b2DV_%+GvWYgr4mX5)}yGMR~?t1MiCkR)UF2@Fpuj9UqB>$8M)n=r0| zYQ=E|uJ>}aB5@FYKE)pweumE|oQBv0`23HSyQDyvadp5PJUvHx9>fM9Hb5oNFpt-# z0T^5gM;enjvrY$=#onXhz4sfL!h#Q_*Mq|VQ9i}Li=_C=_17=Gldt&qjGB*5o_uY& zjRO6k*Dv9-)g7Gl1>nKYudWY%K7${<6Zpwqz-*4!Cr{uflKi3)zeNszVrKLwPfAYQ zEJ?HxSkq&x+QeHP*r!{VMpxEW3cKvQjZ=My!8c?i%_@puCpK&(k|VvV=g)Be^++uh z3~maic`?LAMFbP=;@I0CE`~qUxi;HGy3pBK*5HGe<0E=K=H7bD!vO*U1YOtS{DC_| z1wGQ4I_K~2oI&r3`ho32ly_-;pbW%z7Rrwlp}@*@P>m*9`)x^Dw#!{uWy>ZrizhM# zW|%3cz_Oy~%znu+NRIJ_2?;`xwLuz2T1#<3$I>^_6gG{_xaPD~+*BLcHwI9piG&nx zh@nPi40Xzbs1ZnlpWsl{S=uB;f(B_CZ$zV9$EGyTR(V#pX0wXQpd=+fTtVqwlPO&; z!Nfzt54t`J=ea9lYVceJ0xBWsoYG;1is}=$Kec&VGQ%m~fX(Mxslqm;Y8tmONh@ae z2H?o-DnpZ!LXfIcVUfp0wAOYsE#je(Q;Q6a0eNQo0AJeehpn8Rk>ELI7X z!f8fUZK_qJ;YPViJV*SwXLRIbQ5!#dDsp(U6kh}@yN5RqcWD1z#tvJSVRgx`(O>aap zoUgViRgnzktNQGqb-qy>#H*SbFG1;J55iO$bXNG0hIWSvl`OUKvXmB@61cL+M%7BS z24-L*qfjP$FeXg!0&=CKj*o@_UbP1lBv(BSi7ZI(EcE9zE|gN)n9P^ zO$diX01Y_uni~)|349ktN~f)CFj|~c)F_paWJ0?lZ{fd{KL6!7K z@{cBn>Tp)5=H+S7Bm>0b>#o}&%o&H+mk<%8DO0Xnt@K*uB}V}}^;!sRW4bC%Nw?UlM$o+Lu}}%QHiI&Kt`&hRR-9w&^@D)7 zko^eXFG83qrlD>28bSz#g9;qPaS+Gx&S`Qhd^Om+7%amECE??_K~>|y3NSwBVb)B^ zhanhNS4L@H*mIXUyxp6NmHStI>OH>1!K zD+Jvk{1l+Bi1VZ-)GSRRc`71FBdjdNl-zxWDV`9f94U?NAP9neXcsm;6pl7b5vNCj z9x-~aPm2`rr+z`UZ-jLIW|tbpCJb6oC+b*|ul)Q!-gQ*5jX(X*+TYMBG6ozLYzQBu_5wnn1 zU<%jHB$yY=nEB!r-H(aCf}9o8$tTFU>f}lhi{ck!g_pu5F%rbyhkEx@ToV>ygecuT zf3{&isJ~dkg&z+R*18!x)D|Q3^!x)0O0$xpAHfK(ZPOho)I>bPj=AjAM~Dx zkL~toPO@<_Tc(bUaosiE%&RKa$ci+;X6zcn9+2;hYee0l_7@bC@^*dh^P+JFh*$I; z=x+A~bOvEZ%+!LT$>@~Y%Wp^nH}X7TA^Mn?jKF++h~f0V2pK-V`Fe<2+7l}#XhAUi z^$OsfootdGvD<^JHwY^N1wI=3VM2n^L&o0MuaGUW5bXTs#i{C0o<|fSEnDR(_qVp% z7-qNl)_|HRbvwUdWlOGZtxcN6MJp26C_T~c+oc&6|9VgO#=%c``m_&`O?mrT2+rO< zXg8UuTGQ>1wiEZX$62;B%=Vqcvd%j%ByMF;u0Iam=!mX6gTnlY=t_)(aJipXaWk&w z8mjh>xMftGY2RgpaVM+jP-mI~f$t@5YvOT>m}C}a83|Oz-&uHKt!&JGsck%qgv;n! zQU@f1oQy_c`o`yXe^XUj?Lt`Hb7piLkSR?PB0B5cs>R+CtUgtx)d<7?96?o|S_);l zNWz$1^Bqs=U034xJ|<`3^4mm=tNy!hXW=Wqbny+;N1rlp(YTYhhJ{!z65^zlxFTH& za|i9C+@_555Dj!VI(TvVNMD%qvn2fdc%yCJz^oB?4z`aw8&hcxHK+uJ0}&S<^nNKX zg;l;<3Q63#^=?{77a3d=z9Y5oF2mnEu`9#hI@#A1%JN=ySpjKr4D9Y~`pQqqk^JSq zZ|4n}7#7!ry7h(Kq|VJox#7&zJrov z@w-3#SB7>^6$?mE@hN`;X579bx0f~7O#l%{Oj3DEx}-sug$4=eBXvC2?=I@q;=S>Q zAj~gX5iUUyxWTL_fYF=SiE%^pFRP+oT|~1y*Da(Xy_ZsY#iDkoDXP{_&F*hDWt+>D zhe)kkD7XNvTl!GR*_nB%)BX6c?hht75)LH-Un<7%P>BVZ6GviF<0JOl>1J_hZ#*~e zzJMv8KzWKTPC_7UlXI2jSa4J|#4^Syq@1167G;FWANlDh5@p6;wU@LL7%zz**QAHr znsnZm5qVn|{Hn{t-E}+Oge38k>4N>5T1TCau4AjFIQ9Q6wrVWPeJ8QiM%%e}6{CIz z@f(4y@!J&_{)`@4IX&OEFV?;e@mDm!tWrcrVpk6AGI@Ov^2RXE($aYj^>MmGq&gLH zJ_kY;c^o2!DrT|bBtFTdai9jt-T|z0oyPeNE63X|P}yn^1cdVO{AV$*;;0h47>ryx z1)v7Dz2}kl{>H1Cy20MHO@BHiEAa3vs{f12n$2GFJ1%Q(c4?iLHDmeL%DT8m#JgPb zLMv<8ELT+gLAI`9zRKng#osCEq&{F#)w#X5!*%glf4UeBZ|8+o<6mE#?!2Hw^!CMR zRn){?A$U1lzc?MP0X{k!uHW-(iicI_*u~WX=dLt6P2jHjtn!3!k;~4B7hI@!-aj$b rTY*xyk8%)j%ZFL}Dc-tMxc1rF#LuRSF>Cd7)-u@Y?%)3atuj2dhbx^M diff --git a/dev/random_feature_emulator/index.html b/dev/random_feature_emulator/index.html index f9153660..8d421948 100644 --- a/dev/random_feature_emulator/index.html +++ b/dev/random_feature_emulator/index.html @@ -99,4 +99,4 @@ build_default_prior(input_dim, output_dim, vector_general_kernel) # builds a 2-entry distribution # 781875-dim unbounded distribution 'full_cholesky' -# 1-dim positive distribution `sigma`

See the API for more details.

+# 1-dim positive distribution `sigma`

See the API for more details.

diff --git a/dev/sample/index.html b/dev/sample/index.html index ad44768e..1883e798 100644 --- a/dev/sample/index.html +++ b/dev/sample/index.html @@ -24,4 +24,4 @@ # chain = sample(rng, mcmc, 100_000; stepsize = new_step) display(chain) # diagnostics -plot(chain) # plots samples over iteration and PDFs for each parameter

Internals: Transitions

Implementing MCMC involves defining states and transitions of a Markov process (whose stationary distribution is what we seek to sample from). AbstractMCMC's terminology is a bit confusing for the MH case; states of the chain are described by Transition objects, which contain the current sample (and other information like its log-probability).

AdvancedMH defines an AbstractTransition base class for use with its methods; we implement our own child class, MCMCState, in order to record statistics on the MH acceptance ratio.

Internals: Markov steps

Markov transitions of the chain are defined by overloading AbstractMCMC's step method, which takes the Sampler and current Transition and implements the Sampler's logic to returns an updated Transition representing the chain's new state (actually, a pair of Transitions, for cases where the Sampler doesn't obey detailed balance; this isn't relevant for us).

For example, in Metropolis-Hastings sampling this is where we draw a proposal sample and accept or reject it according to the MH criterion. AdvancedMH implements this here; we re-implement this method because 1) we need to record whether a proposal was accepted or rejected, and 2) our calls to propose() are stepsize-dependent.

+plot(chain) # plots samples over iteration and PDFs for each parameter

Internals: Transitions

Implementing MCMC involves defining states and transitions of a Markov process (whose stationary distribution is what we seek to sample from). AbstractMCMC's terminology is a bit confusing for the MH case; states of the chain are described by Transition objects, which contain the current sample (and other information like its log-probability).

AdvancedMH defines an AbstractTransition base class for use with its methods; we implement our own child class, MCMCState, in order to record statistics on the MH acceptance ratio.

Internals: Markov steps

Markov transitions of the chain are defined by overloading AbstractMCMC's step method, which takes the Sampler and current Transition and implements the Sampler's logic to returns an updated Transition representing the chain's new state (actually, a pair of Transitions, for cases where the Sampler doesn't obey detailed balance; this isn't relevant for us).

For example, in Metropolis-Hastings sampling this is where we draw a proposal sample and accept or reject it according to the MH criterion. AdvancedMH implements this here; we re-implement this method because 1) we need to record whether a proposal was accepted or rejected, and 2) our calls to propose() are stepsize-dependent.

diff --git a/dev/search_index.js b/dev/search_index.js index 2d62789d..8595f012 100644 --- a/dev/search_index.js +++ b/dev/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"examples/emulators/ishigami_3d_1d/#Global-Sensitiviy-Analysis-for-an-emulated-Ishigami-function","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"","category":"section"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"info: How do I run this code?\nThe full code is found in the examples/Emulator/ directory of the github repository","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"In this example, we assess directly the performance of our machine learning emulators. The task is to learn a function for use in a global sensitivity analysis. In particular, we learn the Ishigami function","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"f(x a b) = (1 + bx_3^4)sin(x_1) + a sin(x_2) forall xin -pipi^3","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"with a=7 b=01. In this example, global sensitivity analysis refers to calculation of two Sobol indices. The first index collects proportions V_i (a.k.a firstorder) of the variance of f attributable to the input x_i, and the second index collects proportions TV_i (a.k.a totalorder) of the residual variance having removed contributions attributable to inputs x_j forall jneq i. The Ishigami function has an analytic formula for these Sobol indices, it is also known that one can obtain numerical approximation through quasi-Monto-Carlo methods by evaluating the Ishigami function on a special quasi-random Sobol sequence.","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"To emulate the Ishigami function, the data consists of 300 pairs xf(x)+eta where eta sim N(0Sigma) is additive noise, and the x are sampled from the Sobol sequence. The emulators are validated by evaluating the posterior mean function on the full 16000 points of the Sobol sequence and the Sobol indices are estimated. We rerun the experiment for many repeats of the random feature hyperparameter optimization and present the statistics of these indices, as well as plotting a realization of the emulator.","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"We use the package GlobalSensitivityAnalysis.jl for many of the GSA tools.","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/#Walkthrough-of-the-code","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Walkthrough of the code","text":"","category":"section"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"We first load some standard packages","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"using Distributions\nusing DataStructures # for `OrderedDict`\nusing Random\nusing LinearAlgebra\nusing CairoMakie, ColorSchemes ","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"and the packages for providing the Ishigami function, Sobol sequence, and evaluation of the indices","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"using GlobalSensitivityAnalysis # for `SobolData`\nconst GSA = GlobalSensitivityAnalysis","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"then the CES packages for the emulators","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"using CalibrateEmulateSample.Emulators # for `SKLJL`, `GaussianProcess`, `SeparableKernel`, `LowRankFactor`, `OneDimFactor`, `ScalarRandomFeatureInterface`, `Emulator`\nusing CalibrateEmulateSample.DataContainers # for `PairedDataContainer`\nusing CalibrateEmulateSample.EnsembleKalmanProcesses # for `DataMisfitController`","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"We set up the sampling procedure, evaluate the true ishigami function on these points, and calculate the sobol indices","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"n_data_gen = 2000 \n\ndata = SobolData(\n params = OrderedDict(:x1 => Uniform(-π, π), :x2 => Uniform(-π, π), :x3 => Uniform(-π, π)),\n N = n_data_gen,\n)\n\n# To perform global analysis,\n# one must generate samples using Sobol sequence (i.e. creates more than N points)\nsamples = GSA.sample(data)\nn_data = size(samples, 1) # [n_samples x 3]\n# run model (example)\ny = GSA.ishigami(samples)\n# perform Sobol Analysis\nresult = analyze(data, y)","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"Next we create the noisy training data from the sequence samples","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"n_train_pts = 300\nind = shuffle!(rng, Vector(1:n_data))[1:n_train_pts]\n# now subsample the samples data\nn_tp = length(ind)\ninput = zeros(3, n_tp)\noutput = zeros(1, n_tp)\nΓ = 1e-2\nnoise = rand(rng, Normal(0, Γ), n_tp)\nfor i in 1:n_tp\n input[:, i] = samples[ind[i], :]\n output[i] = y[ind[i]] + noise[i]\nend\niopairs = PairedDataContainer(input, output)","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"We have a few cases for the user to investigate","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"cases = [\n \"Prior\", # Scalar random feature emulator with no hyperparameter learning\n \"GP\", # Trained Sci-kit learn Gaussian process emulator\n \"RF-scalar\", # Trained scalar random feature emulator\n]","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"Each case sets up a different machine learning configuration in the Emulator object.","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"For the random feature case, RF-scalar, we use a rank-3 kernel in the input space, and 500 features for prediction, though for efficiency we use only 200 when learning the hyperparameters. The relevant code snippets are","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"nugget = Float64(1e-12)\noverrides = Dict(\n \"scheduler\" => DataMisfitController(terminate_at = 1e4),\n \"n_features_opt\" => 200,\n)\n\nkernel_structure = SeparableKernel(LowRankFactor(3, nugget), OneDimFactor())\nn_features = 500\nmlt = ScalarRandomFeatureInterface(\n n_features,\n 3,\n rng = rng,\n kernel_structure = kernel_structure,\n optimizer_options = overrides,\n)","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"For the gaussian process case GP we use the sci-kit learn package, a default squared exponential kernel with lengthscale learnt in each input dimensions. We do not learn an additional white kernel for the noise.","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"gppackage = Emulators.SKLJL()\npred_type = Emulators.YType()\nmlt = GaussianProcess(\n gppackage;\n prediction_type = pred_type,\n noise_learn = false,\n)","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"We finish by building the emulator object","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"emulator = Emulator(mlt, iopairs; obs_noise_cov = Γ * I, decorrelate = decorrelate)\noptimize_hyperparameters!(emulator) # (only needed for some Emulator packages)","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/#Results-and-plots","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Results and plots","text":"","category":"section"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"We validate the emulator by evaluating it on the entire Sobol sequence, and calculating the Sobol indices (presenting mean and std if using multiple repeats.","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"# predict on all Sobol points with emulator (example) \ny_pred, y_var = predict(emulator, samples', transform_to_real = true)\n\n# obtain emulated Sobol indices\nresult_pred = analyze(data, y_pred')","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/#Gaussian-Process-Emulator-(sci-kit-learn-GP)","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Gaussian Process Emulator (sci-kit learn GP)","text":"","category":"section"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"Here is the plot for one emulation","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"and the outputted table of Sobol indices","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"True Sobol Indices\n******************\n firstorder: [0.31390519114781146, 0.44241114479004084, 0.0]\n totalorder: [0.5575888552099592, 0.44241114479004084, 0.24368366406214775]\n \nSampled truth Sobol Indices (# points 16000)\n***************************\n firstorder: [0.31261591941512257, 0.441887746224135, -0.005810964687365922]\n totalorder: [0.5623611180844434, 0.44201284296404386, 0.24465876318633062]\n \nSampled Emulated Sobol Indices (# obs 300, noise var 0.01)\n***************************************************************\n firstorder: [0.3094638183079643, 0.4518400892052567, -0.007351344957260407]\n totalorder: [0.5502469909342245, 0.4587734278791574, 0.23542404141319245]","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/#Random-feature-emulator-(Separable-Low-rank-kernel-RF-scalar)","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Random feature emulator (Separable Low-rank kernel RF-scalar)","text":"","category":"section"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"Here is the plot for one emulation","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"Table for 20 repeats of the algorithm","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"True Sobol Indices\n******************\n firstorder: [0.31390519114781146, 0.44241114479004084, 0.0]\n totalorder: [0.5575888552099592, 0.44241114479004084, 0.24368366406214775]\n \nSampled truth Sobol Indices (# points 16000)\n***************************\n firstorder: [0.31261591941512257, 0.441887746224135, -0.005810964687365922]\n totalorder: [0.5623611180844434, 0.44201284296404386, 0.24465876318633062]\n \nSampled Emulated Sobol Indices (# obs 300, noise var 0.01)\n***************************************************************\n(mean) firstorder: [0.33605548545490044, 0.41116050093679196, -0.0012213648484969539]\n(std) firstorder: [0.05909336956162543, 0.11484966121124164, 0.012908533302492602]\n(mean) totalorder: [0.5670345355855254, 0.4716028261179354, 0.24108222433317]\n(std) totalorder: [0.10619345801872732, 0.1041023777237331, 0.07200225781785778]\n","category":"page"},{"location":"examples/sinusoid_example/#Sinusoid-Example","page":"Simple example walkthrough","title":"Sinusoid Example","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"info: How do I run this code?\nThe full code is found in the examples/ directory of the github repository","category":"page"},{"location":"examples/sinusoid_example/#Background","page":"Simple example walkthrough","title":"Background","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"This example demonstrates how to use CalibrateEmulateSample.jl for a simple model that generates noisy observables of a signal. The sinusoid signal is defined by two parameters: its shift along the vertical axis and its amplitude. We make noisy observations of the signal and we can calculate the mean of the signal, which is informative about its shift along the axis, and the range of the signal, which is informative about the amplitude. Although our sinusoid function is simple and quick to evaluate, we shall pretend it is non-differentiable and expensive to evaluate, as a case study for carrying out uncertainty quantification on more complex systems. Additionally, we will work in a \"perfect model\" setting for this example, meaning we will generate pseudo-observations for our model and pretend that these are noisy observations of our system.","category":"page"},{"location":"examples/sinusoid_example/#Model","page":"Simple example walkthrough","title":"Model","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We have a model of a sinusoidal signal that is a function of parameters theta=(Av), where A is the amplitude of the signal and v is vertical shift of the signal:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"f(A v) = A sin(phi + t) + v forall t in 02pi","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Here, phi is the random phase of each signal. The goal is to estimate not just the point estimates of the parameters theta=(Av), but entire probability distributions of them, given some noisy observations. We will use the range and mean of a signal as our observable: ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"G(theta) = big textrangebig(f(theta)big) textmeanbig(f(theta)big) big ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"This highlights the role of choosing a good observable, in particular our choice of G is independent of the random phase shift phi and is in fact deterministic. This allows us to write out an expression for the noisy observation, y_obs:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"y_obs = G(theta) + gamma qquad gamma sim mathcalN(0 Gamma)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"where Gamma is the observational covariance matrix. We will assume the noise to be independent for each observable, giving us a diagonal covariance matrix.","category":"page"},{"location":"examples/sinusoid_example/#Walkthrough-of-code","page":"Simple example walkthrough","title":"Walkthrough of code","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"You can find the full scripts to reproduce this tutorial in examples/Sinusoid/. The code is split into four sections:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Model set up in sinusoid_setup.jl\nCalibrate in calibrate.jl\nEmulate in emulate.jl\nSample in sample.jl","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"You do not need to explicitly run sinusoid_setup.jl as it is called from calibrate.jl. However, this file contains the functions for the model and for generating pseudo-observations. You will need to run steps 2-4 in order as each one relies on output saved from the previous steps.","category":"page"},{"location":"examples/sinusoid_example/#Set-up","page":"Simple example walkthrough","title":"Set up","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"First, we load the packages we need for setting up the model:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"using LinearAlgebra, Random\nusing Plots\nusing JLD2\nusing Statistics, Distributions\n","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We define a model that generates a sinusoid given parameters theta=(Av) (amplitude and vertical shift). We will estimate these parameters from data. The model adds a random phase shift upon evaluation.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"# Define x-axis\ndt = 0.01\ntrange = 0:dt:(2 * pi + dt)\n\nfunction model(amplitude, vert_shift)\n # Set phi, the random phase\n phi = 2 * pi * rand()\n return amplitude * sin.(trange .+ phi) .+ vert_shift\nend\n","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We will define a \"true\" amplitude and vertical shift to generate some pseudo-observations. Let theta=(30 70).","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"amplitude_true = 3.0\nvert_shift_true = 7.0\n# Our input parameters are 2d and our outputs are 2d\ntheta_true = [amplitude_true, vert_shift_true]\ndim_params = 2\n# Generate the \"true\" signal for these parameters\nsignal_true = model(amplitude_true, vert_shift_true)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We will observe properties of the signal that inform us about the amplitude and vertical position. These properties will be the range (the difference between the maximum and the minimum), which is informative about the amplitude of the sinusoid, and the mean, which is informative about the vertical shift. ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"y1_true = maximum(signal_true) - minimum(signal_true)\ny2_true = mean(signal_true)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"However, our observations are typically not noise-free, so we add some white noise to our observables. We call this y_obs. The user can choose the observational covariance matrix, Gamma. We will assume the noise is independent (a diagonal covariance matrix Gamma=02 * I). ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"dim_output = 2\nΓ = 0.2 * I\nwhite_noise = MvNormal(zeros(dim_output), Γ)\ny_obs = [y1_true, y2_true] .+ rand(white_noise)\nprintln(\"Observations:\", y_obs)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"This gives y_obs=(615 642). We can plot the true signal in black, the true observables in red and the noisy observables in blue. (Image: signal)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"It will be helpful for us to define a function G(theta), which returns these observables (the range and the mean) of the sinusoid given a parameter vector. ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"function G(theta)\n amplitude, vert_shift = theta\n sincurve = model(amplitude, vert_shift)\n return [maximum(sincurve) - minimum(sincurve), mean(sincurve)]\nend","category":"page"},{"location":"examples/sinusoid_example/#Calibrate","page":"Simple example walkthrough","title":"Calibrate","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We are interested in learning the posterior distribution of theta for the inverse problem y_obs=G(theta)+mathcalN(0Gamma). We first carry out calibration, which aims to solve the inverse problem for point estimates of the optimal values for theta. Specifically, we use an ensemble based calibration method, such as Ensemble Kalman Inversion, because it provides us with ensembles of G(theta) evaluations that are focused near to the optimal values for theta. These ensembles provide us with a suitable dataset for training an emulator to be used in sampling the posterior distribution. ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We are using the EnsembleKalmanProcesses.jl package for Ensemble Kalman Inversion (EKI). We start with user-defined prior distributions and sample an ensemble of parameters theta, which we use to evaluate G(theta). Then, we iteratively update the ensemble until our parameters theta are near to the optimal.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"First, we will load the packages we need from CES:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"# CES\nusing CalibrateEmulateSample\nconst EKP = CalibrateEmulateSample.EnsembleKalmanProcesses\nconst PD = EKP.ParameterDistributions","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We define prior distributions on the two parameters. For the amplitude, we define a prior with mean 2 and standard deviation 1. It is additionally constrained to be nonnegative. For the vertical shift we define a Gaussian prior with mean 0 and standard deviation 5.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"prior_u1 = PD.constrained_gaussian(\"amplitude\", 2, 1, 0, Inf)\nprior_u2 = PD.constrained_gaussian(\"vert_shift\", 0, 5, -Inf, Inf)\nprior = PD.combine_distributions([prior_u1, prior_u2])\n# Plot priors\np = plot(prior, fill = :lightgray)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: prior)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We now generate the initial ensemble and set up the EKI.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"N_ensemble = 10\nN_iterations = 5\n\ninitial_ensemble = EKP.construct_initial_ensemble(prior, N_ensemble)\n\nensemble_kalman_process = EKP.EnsembleKalmanProcess(initial_ensemble, y_obs, Γ, EKP.Inversion())","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We are now ready to carry out the inversion. At each iteration, we get the ensemble from the last iteration, apply G(theta) to each ensemble member, and apply the Kalman update to the ensemble.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"for i in 1:N_iterations\n params_i = EKP.get_ϕ_final(prior, ensemble_kalman_process)\n\n G_ens = hcat([G(params_i[:, i]) for i in 1:N_ensemble]...)\n\n EKP.update_ensemble!(ensemble_kalman_process, G_ens)\nend","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Finally, we get the ensemble after the last iteration. This provides our estimate of the parameters.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"final_ensemble = EKP.get_ϕ_final(prior, ensemble_kalman_process)\n\n# Check that the ensemble mean is close to the theta_true\nprintln(\"Ensemble mean: \", mean(final_ensemble, dims=2)) # [3.05, 6.37]\nprintln(\"True parameters: \", theta_true) # [3.0, 7.0]","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Parameter Truth EKI mean\nAmplitude 3.0 3.05\nVertical shift 7.0 6.37","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"The EKI ensemble mean at the final iteration is close to the true parameters, which is good. We can also see how the ensembles evolve at each iteration in the plot below.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: eki)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"The ensembles are initially spread out but move closer to the true parameter values with each iteration, indicating the EKI algorithm is converging towards the minimum. Taking the mean of the ensemble gives a point estimate of the optimal parameters. However, EKI does not give us an estimate of the uncertainty, as the ensemble collapses. To carry out uncertainty quantification, we can sample from the posterior distribution, which requires a \"cheap\" method to evaluate our model, i.e., an emulator. In the next step of CES, we will build an emulator using the dataset generated in EKI.","category":"page"},{"location":"examples/sinusoid_example/#Emulate","page":"Simple example walkthrough","title":"Emulate","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"In the previous calibrate step, we learned point estimates for the optimal parameters theta, but for uncertainty quantification, we want to learn posterior distributions on our parameters. We can sample from posterior distributions with Markov chain Monte Carlo (MCMC) methods, but these typically require many model evaluations. In many scientific problems, model evaluations are highly costly, making this infeasible. To get around this, we build an emulator of our model, which allows us to approximate the expensive model almost instantaneously. An emulator can also be helpful for noisy problems as they provide a smoother approximation, leading to better MCMC convergence properties. In this section, we show how the codebase can be used to build emulators of our sinusoid model.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We ran Ensemble Kalman Inversion with an ensemble size of 10 for 5 iterations. This generated a total of 50 input output pairs from our model. We will use these samples to train an emulator. The EKI samples make a suitable dataset for training an emulator because in the first iteration, the ensemble parameters are spread out according to the prior, meaning they cover the full support of the parameter space. This is important for building an emulator that can be evaluated anywhere in this space. In later iterations, the ensemble parameters are focused around the truth. This means the emulator that will be more accurate around this region.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"First, we load additional packages we need for this section:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"using CalibrateEmulateSample.Emulators\nconst CES = CalibrateEmulateSample","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We will build two types of emulator here for comparison: Gaussian processes and Random Features. First, set up the data in the correct format. CalibrateEmulateSample.jl uses a paired data container that matches the inputs (in the unconstrained space) to the outputs:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"input_output_pairs = CES.Utilities.get_training_points(ensemble_kalman_process, N_iterations)\nunconstrained_inputs = CES.Utilities.get_inputs(input_output_pairs)\ninputs = Emulators.transform_unconstrained_to_constrained(prior, unconstrained_inputs)\noutputs = CES.Utilities.get_outputs(input_output_pairs)","category":"page"},{"location":"examples/sinusoid_example/#Gaussian-process","page":"Simple example walkthrough","title":"Gaussian process","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We will set up a basic Gaussian process (GP) emulator using the ScikitLearn.jl package or GaussianProcesses.jl. See the Gaussian process page for more information and options, including choice of package and kernels.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"gppackage = Emulators.GPJL()\ngauss_proc = Emulators.GaussianProcess(gppackage, noise_learn = false)\n\n# Build emulator with data\nemulator_gp = Emulator(gauss_proc, input_output_pairs, normalize_inputs = true, obs_noise_cov = Γ)\noptimize_hyperparameters!(emulator_gp)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"For this simple example, we already know the observational noise Γ=0.2*I, so we set noise_learn = false. However, for more complicated problems we may want to learn the noise as an additional hyperparameter.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We will check performance of the GP by testing on unseen data in a moment, but first, we will build a random features emulator for comparison.","category":"page"},{"location":"examples/sinusoid_example/#Random-Features","page":"Simple example walkthrough","title":"Random Features","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"An alternative emulator can be created with random features (RF). Random features can approximate a Gaussian process with improved scaling properties, making them more suitable for higher dimensional problems. We use a Vector Random Features emulator here, chosen because we find it is a reasonable approximation to the Gaussian process emulator above. For new problems, you may need to play around with these parameter choices. More information can be found here.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"# We have two input dimensions and two output dimensions.\ninput_dim = 2\noutput_dim = 2\n# Select number of features\nn_features = 60\nnugget = 1e-9\nkernel_structure = NonseparableKernel(LowRankFactor(2, nugget))\noptimizer_options = Dict(\n \"n_ensemble\" => 50,\n \"cov_sample_multiplier\" => 10,\n \"scheduler\" => EKP.DataMisfitController(on_terminate = \"continue\"),\n \"n_iteration\" => 50,\n \"verbose\" => true,\n)\nrandom_features = VectorRandomFeatureInterface(\n n_features,\n input_dim,\n output_dim,\n kernel_structure = kernel_structure,\n optimizer_options = optimizer_options,\n)\nemulator_random_features =\n Emulator(random_features, input_output_pairs, normalize_inputs = true, obs_noise_cov = Γ, decorrelate = false)\noptimize_hyperparameters!(emulator_random_features)","category":"page"},{"location":"examples/sinusoid_example/#Emulator-Validation","page":"Simple example walkthrough","title":"Emulator Validation","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Now we will validate both GP and RF emulators and compare them against the ground truth, G(theta). Note this is only possible in our example because our true model, G(theta), is cheap to evaluate. In more complex systems, we would have limited data to validate emulator performance with. ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Here, we will compare emulator performance across a wide range of parameters, but we will pay close attention to performance near the final ensemble mean theta=(3 6). This is because we need high accuracy in this region in the next step, when we sample the posterior distribution.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"First, we check the ground truth model G(theta) over our parameter space. We can plot how the two outputs (range, mean), vary with the two input parameters (amplitude, vertical shift).","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: groundtruth)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"The first panel shows how the range varies with respect to the two parameters in the true forward map. The contours show the range is mostly dependent on the amplitude, with little variation with respect to the vertical shift. The second panel shows how the mean varies with the respect to the two parameters and is mostly dependent on the vertical shift. This result makes sense for our model setup.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Below, we recreate the same contour plot with the emulators. We will also overlay the training data points from the EKI, where the colors show the output from G(theta) evaluated at the training points. The emulator contours should agree with the training data.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"First, for the Gaussian process emulator:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: GP_emulator)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"This looks similar to the output from G(theta). Next, let's check the random features emulator:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: RF_emulator)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Both the GP and RF emulator give similar results to the ground truth G(theta), indicating they are correctly learning the relationships between the parameters and the outputs. We also see the contours agree with the colors of the training data points. ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We should also validate how accurate the emulators are by looking at the absolute difference between emulator predictions and the ground truth. ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"The Gaussian process absolute errors are plotted here:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: GP_errors)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"and the random features absolute errors are here:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: RF_errors)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Both these error maps look similar. Importantly, we want the emulator to show the low errors in the region around the true parameter values near theta=(3 6) (i.e, near where the EKI points converge, shown by the scatter points in the previous plot). This the region that we will be sampling in the next step. We see low errors near here for both outputs and for both emulators. Now we have validated these emulators, we will proceed the last step of CES: Sampling of the posterior distribution. ","category":"page"},{"location":"examples/sinusoid_example/#Sample","page":"Simple example walkthrough","title":"Sample","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Now that we have a cheap emulator for our model, we can carry out uncertainty quantification to learn the posterier distribution of the parameters, theta. We use Markov chain Monte Carlo (MCMC) to sample the posterior distribtion. In MCMC, we start with a sample from a prior distribution and propose a new sample from a proposal distribution, which is accepted with a probability relating the the ratio of the posterior distribution to the proposal distributions. If accepted, this proposed sample is added to the chain, or otherwise, the original sample is added to the chain. This is repeated over many iterations and eventually creates a sequence of samples from the posterior distribution. The CES code uses AbstractMCMC.jl, full details can be found here. For this example, we will use a random walk Metropolis-Hastings sampler (RWMHSampling), which assumes that the proposal distribution is a random walk, with a step-size delta. Usually, we have little knowledge of what this step size should be, but we can optimize this as shown below.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"First, we will load the additional packages we need:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"using CalibrateEmulateSample.MarkovChainMonteCarlo","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We will provide the API with the observations, priors and our cheap emulator from the previous section. In this example we use the GP emulator. First, we need to find a suitable starting point, ideally one that is near the posterior distribution. We will use the final ensemble mean from EKI as this will increase the chance of acceptance near the start of the chain, and reduce burn-in time.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"init_sample = EKP.get_u_mean_final(ensemble_kalman_process)\nprintln(\"initial parameters: \", init_sample) # (1.11, 6.37)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Now, we can set up and carry out the MCMC starting from this point. ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"mcmc = MCMCWrapper(RWMHSampling(), y_obs, prior, emulator_gp; init_params = init_sample)\n# First let's run a short chain to determine a good step size\nnew_step = optimize_stepsize(mcmc; init_stepsize = 0.1, N = 2000, discard_initial = 0)\n\n# Now begin the actual MCMC\nprintln(\"Begin MCMC - with step size \", new_step)\nchain = MarkovChainMonteCarlo.sample(mcmc, 100_000; stepsize = new_step, discard_initial = 2_000)\n\n# We can print summary statistics of the MCMC chain\ndisplay(chain)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"parameters mean std\namplitude 1.1068 0.0943\nvert_shift 6.3897 0.4601","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Note that these values are provided in the unconstrained space. The vertical shift seems reasonable, but the amplitude is not. This is because the amplitude is constrained to be positive, but the MCMC is run in the unconstrained space. We can transform to the real constrained space and re-calculate these values.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"# Extract posterior samples\nposterior = MarkovChainMonteCarlo.get_posterior(mcmc, chain)\n# Back to constrained coordinates\nconstrained_posterior = Emulators.transform_unconstrained_to_constrained(\n prior, MarkovChainMonteCarlo.get_distribution(posterior)\n)\nprintln(\"Amplitude mean: \", mean(constrained_posterior[\"amplitude\"]), \", std: \", std(constrained_posterior[\"amplitude\"]))\nprintln(\"Vertical shift mean: \", mean(constrained_posterior[\"vert_shift\"]), \", std: \", std(constrained_posterior[\"vert_shift\"]))","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"This gives:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"parameters mean std\namplitude 3.0382 0.2880\nvert_shift 6.3774 0.4586","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"This is in agreement with the true theta=(30 70) and with the observational covariance matrix we provided Gamma=02 * I (i.e., a standard deviation of approx. 045). CalibrateEmulateSample.jl has built-in plotting recipes to help us visualize the prior and posterior distributions. Note that these are the marginal distributions.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"# We can quickly plot priors and posterior using built-in capabilities\np = plot(prior, fill = :lightgray)\nplot!(posterior, fill = :darkblue, alpha = 0.5)\n","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: GP_posterior)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"The MCMC has learned the posterior distribution which is much narrower than the prior. For multidimensional problems, the posterior is typically multidimensional, and marginal distribution plots do not show how parameters co-vary. We plot a 2D histogram of theta_1 vs. theta_2 below, with the marginal distributions on each axis. ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: GP_2d_posterior)","category":"page"},{"location":"examples/sinusoid_example/#Sample-with-Random-Features","page":"Simple example walkthrough","title":"Sample with Random Features","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We can repeat the sampling method using the random features emulator instead of the Gaussian process and we find similar results: ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"parameters mean std\namplitude 3.3210 0.7216\nvert_shift 6.3986 0.5098","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: RF_2d_posterior)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"It is reassuring to see that our uncertainty quantification methods are robust to the different emulator choices here. This is because our particular GP and RF emulators showed similar accuracy during validation. However, this result is highly sensitive to the choices of GP kernel and RF kernel structure. If you find very different posterior distributions for different emulators, it is likely that the kernel choices need be refined. The kernel choices must be flexible enough to accurately capture the relationships between the inputs and outputs. We recommend trying a variety of different emulator configurations and carefully considering emulator validation on samples that the emulator has not been trained on. ","category":"page"},{"location":"contributing/#Contributing","page":"Contributing","title":"Contributing","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"Thank you for considering contributing to CalibrateEmulateSample! We encourage opening issues and pull requests (PRs).","category":"page"},{"location":"contributing/#What-to-contribute?","page":"Contributing","title":"What to contribute?","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"The easiest way to contribute is by using CalibrateEmulateSample, identifying problems and opening issues;\nYou can try to tackle an existing issue. It is best to outline your proposed solution in the issue thread before implementing it in a PR;\nWrite an example or tutorial. It is likely that other users may find your use of CalibrateEmulateSample insightful;\nImprove documentation or comments if you found something hard to use;\nImplement a new feature if you need it. We strongly encourage opening an issue to make sure the administrators are on board before opening a PR with an unsolicited feature addition. Examples could include implementing new statistical emulators, or implementing new data compression tools (beyond normalization, standardization and truncated SVD)","category":"page"},{"location":"contributing/#Using-git","page":"Contributing","title":"Using git","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"If you are unfamiliar with git and version control, the following guides will be helpful:","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"Atlassian (bitbucket) git tutorials. A set of tips and tricks for getting started with git.\nGitHub's git tutorials. A set of resources from GitHub to learn git.","category":"page"},{"location":"contributing/#Forks-and-branches","page":"Contributing","title":"Forks and branches","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"Create your own fork of CalibrateEmulateSample on GitHub and check out your copy:","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"$ git clone https://github.com//CalibrateEmulateSample.jl.git\n$ cd CalibrateEmulateSample.jl","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"Now you have access to your fork of CalibrateEmulateSample through origin. Create a branch for your feature; this will hold your contribution:","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"$ git checkout -b ","category":"page"},{"location":"contributing/#Some-useful-tips","page":"Contributing","title":"Some useful tips","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"When you start working on a new feature branch, make sure you start from main by running: git checkout main and git pull.\nCreate a new branch from main by using git checkout -b .","category":"page"},{"location":"contributing/#Develop-your-feature","page":"Contributing","title":"Develop your feature","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"Make sure you add tests for your code in test/ and appropriate documentation in the code and/or in docs/. Before committing your changes, you can verify their behavior by running the tests, the examples, and building the documentation locally. In addition, make sure your feature follows the formatting guidelines by running","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"julia --project=.dev .dev/climaformat.jl .","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"from the CalibrateEmulateSample.jl directory.","category":"page"},{"location":"contributing/#Squash-and-rebase","page":"Contributing","title":"Squash and rebase","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"When your PR is ready for review, clean up your commit history by squashing and make sure your code is current with CalibrateEmulateSample.jl main by rebasing. The general rule is that a PR should contain a single commit with a descriptive message.","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"To make sure you are up to date with main, you can use the following workflow:","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"$ git checkout main\n$ git pull\n$ git checkout \n$ git rebase main","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"This may create conflicts with the local branch. The conflicted files will be outlined by git. To resolve conflicts, we have to manually edit the files (e.g. with vim). The conflicts will appear between >>>>, ===== and <<<<<. We need to delete these lines and pick what version we want to keep.","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"To squash your commits, you can use the following command:","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"$ git rebase -i HEAD~n","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"where n is the number of commits you need to squash into one. Then, follow the instructions in the terminal. For example, to squash 4 commits:","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"$ git rebase -i HEAD~4","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"will open the following file in (typically) vim:","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":" pick 01d1124 \n pick 6340aaa \n pick ebfd367 \n pick 30e0ccb \n\n # Rebase 60709da..30e0ccb onto 60709da\n #\n # Commands:\n # p, pick = use commit\n # e, edit = use commit, but stop for amending\n # s, squash = use commit, but meld into previous commit\n #\n # If you remove a line here THAT COMMIT WILL BE LOST.\n # However, if you remove everything, the rebase will be aborted.\n##","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"We want to keep the first commit and squash the last 3. We do so by changing the last three commits to squash and then do :wq on vim.","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":" pick 01d1124 \n squash 6340aaa \n squash ebfd367 \n squash 30e0ccb \n\n # Rebase 60709da..30e0ccb onto 60709da\n #\n # Commands:\n # p, pick = use commit\n # e, edit = use commit, but stop for amending\n # s, squash = use commit, but meld into previous commit\n #\n # If you remove a line here THAT COMMIT WILL BE LOST.\n # However, if you remove everything, the rebase will be aborted.","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"Then in the next screen that appears, we can just delete all messages that we do not want to show in the commit. After this is done and we are back to the console, we have to force push. We need to force push because we rewrote the local commit history.","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"$ git push -u origin --force","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"You can find more information about squashing here.","category":"page"},{"location":"contributing/#Unit-testing","page":"Contributing","title":"Unit testing","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"Currently a number of checks are run per commit for a given PR.","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"JuliaFormatter checks if the PR is formatted with .dev/climaformat.jl.\nDocumentation rebuilds the documentation for the PR and checks if the docs are consistent and generate valid output.\nUnit Tests run subsets of the unit tests defined in tests/, using Pkg.test(). The tests are run in parallel to ensure that they finish in a reasonable time. The tests only run the latest commit for a PR, branch and will kill any stale jobs on push. These tests are only run on linux (Ubuntu LTS).","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"Unit tests are run against every new commit for a given PR, the status of the unit-tests are not checked during the merge process but act as a sanity check for developers and reviewers. Depending on the content changed in the PR, some CI checks that are not necessary will be skipped. For example doc only changes do not require the unit tests to be run.","category":"page"},{"location":"contributing/#The-merge-process","page":"Contributing","title":"The merge process","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"We ensure that all unit tests across several environments, Documentation builds, and integration tests (managed by Buildkite), pass before merging any PR into main. The integration tests currently run some of our example cases in examples/.","category":"page"},{"location":"installation_instructions/#Installation-Instructions","page":"Installation instructions","title":"Installation Instructions","text":"","category":"section"},{"location":"installation_instructions/#Installing-CalibrateEmulateSample.jl","page":"Installation instructions","title":"Installing CalibrateEmulateSample.jl","text":"","category":"section"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"Currently CalibrateEmulateSample (CES) depends on some external python dependencies including scipy (version 1.8.1 works) and scikit-learn (version 1.1.1 works) that are wrapped by ScikitLearn.jl.","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"If you have dependencies installed already, then the code can be used by simply entering","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"julia --project\n> ]\n> add CalibrateEmulateSample","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"One may instead clone the project into a new local repository (using SSH or https link from github), to easily access the CES codebase (e.g. to run our example suite) .","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"If you do not have the dependencies installed, we have found it is easiest to install them via Julia's \"Conda.jl\",","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"julia --project\n> ]\n> add Conda\n> add CalibrateEmulateSample","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"Then install the dependencies by having the project use its own Conda environment variable (set by exporting the ENV variable PYTHON=\"\").","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"> PYTHON=\"\" julia --project -e 'using Pkg; Pkg.instantiate()'","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"This call should build Conda and Pycall. The scikit-learn package (along with scipy) then has to be installed if using a Julia project-specific Conda environment:","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"> PYTHON=\"\" julia --project -e 'using Conda; Conda.add(\"scipy=1.8.1\", channel=\"conda-forge\")'\n> PYTHON=\"\" julia --project -e 'using Conda; Conda.add(\"scikit-learn=1.1.1\")'\n","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"See the PyCall.jl documentation for more information about how to configure the local Julia / Conda / Python environment. ","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"To test that the package is working:","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"> julia --project -e 'using Pkg; Pkg.test()'","category":"page"},{"location":"installation_instructions/#Building-the-documentation-locally","page":"Installation instructions","title":"Building the documentation locally","text":"","category":"section"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"You need to first build the top-level project before building the documentation:","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"cd CalibrateEmulateSample.jl\njulia --project -e 'using Pkg; Pkg.instantiate()'","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"Then you can build the project documentation under the docs/ sub-project:","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"julia --project=docs/ -e 'using Pkg; Pkg.instantiate()'\njulia --project=docs/ docs/make.jl","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"The locally rendered HTML documentation can be viewed at docs/build/index.html. Occasional figures may only be viewable in the online documentation due to the fancy-url package.","category":"page"},{"location":"API/Utilities/#Utilities","page":"Utilities","title":"Utilities","text":"","category":"section"},{"location":"API/Utilities/","page":"Utilities","title":"Utilities","text":"Modules = [CalibrateEmulateSample.Utilities]\nOrder = [:module, :type, :function]","category":"page"},{"location":"API/Utilities/#CalibrateEmulateSample.Utilities.get_obs_sample-Union{Tuple{IT}, Tuple{Random.AbstractRNG, EnsembleKalmanProcesses.Observations.Observation}} where IT<:Int64","page":"Utilities","title":"CalibrateEmulateSample.Utilities.get_obs_sample","text":"get_obs_sample(\n rng::Random.AbstractRNG,\n obs::EnsembleKalmanProcesses.Observations.Observation;\n rng_seed\n) -> Any\n\n\nReturn a random sample from the observations, for use in the MCMC.\n\nrng - optional RNG object used to pick random sample; defaults to Random.GLOBAL_RNG.\nobs - Observation struct with the observations (extract will pick one of the sample observations to train).\nrng_seed - optional kwarg; if provided, used to re-seed rng before sampling.\n\n\n\n\n\n","category":"method"},{"location":"API/Utilities/#CalibrateEmulateSample.Utilities.get_training_points-Union{Tuple{P}, Tuple{IT}, Tuple{FT}, Tuple{EnsembleKalmanProcesses.EnsembleKalmanProcess{FT, IT, P}, Union{AbstractVector{IT}, IT}}} where {FT, IT, P}","page":"Utilities","title":"CalibrateEmulateSample.Utilities.get_training_points","text":"get_training_points(\n ekp::EnsembleKalmanProcesses.EnsembleKalmanProcess{FT, IT, P},\n train_iterations::Union{AbstractVector{IT}, IT} where IT\n) -> EnsembleKalmanProcesses.DataContainers.PairedDataContainer\n\n\nExtract the training points needed to train the Gaussian process regression.\n\nekp - EnsembleKalmanProcess holding the parameters and the data that were produced during the Ensemble Kalman (EK) process.\ntrain_iterations - Number (or indices) EK layers/iterations to train on.\n\n\n\n\n\n","category":"method"},{"location":"API/RandomFeatures/#RandomFeatures","page":"Random Features","title":"RandomFeatures","text":"","category":"section"},{"location":"API/RandomFeatures/","page":"Random Features","title":"Random Features","text":"CurrentModule = CalibrateEmulateSample.Emulators","category":"page"},{"location":"API/RandomFeatures/#Kernel-and-Covariance-structure","page":"Random Features","title":"Kernel and Covariance structure","text":"","category":"section"},{"location":"API/RandomFeatures/","page":"Random Features","title":"Random Features","text":"OneDimFactor\nDiagonalFactor\nCholeskyFactor\nLowRankFactor\nHierarchicalLowRankFactor\nSeparableKernel\nNonseparableKernel\ncalculate_n_hyperparameters\nhyperparameters_from_flat\nbuild_default_prior","category":"page"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.OneDimFactor","page":"Random Features","title":"CalibrateEmulateSample.Emulators.OneDimFactor","text":"struct OneDimFactor <: CalibrateEmulateSample.Emulators.CovarianceStructureType\n\ncovariance structure for a one-dimensional space\n\n\n\n\n\n","category":"type"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.DiagonalFactor","page":"Random Features","title":"CalibrateEmulateSample.Emulators.DiagonalFactor","text":"struct DiagonalFactor{FT<:AbstractFloat} <: CalibrateEmulateSample.Emulators.CovarianceStructureType\n\nbuilds a diagonal covariance structure\n\n\n\n\n\n","category":"type"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.CholeskyFactor","page":"Random Features","title":"CalibrateEmulateSample.Emulators.CholeskyFactor","text":"struct CholeskyFactor{FT<:AbstractFloat} <: CalibrateEmulateSample.Emulators.CovarianceStructureType\n\nbuilds a general positive-definite covariance structure\n\n\n\n\n\n","category":"type"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.LowRankFactor","page":"Random Features","title":"CalibrateEmulateSample.Emulators.LowRankFactor","text":"struct LowRankFactor{FT<:AbstractFloat} <: CalibrateEmulateSample.Emulators.CovarianceStructureType\n\nbuilds a covariance structure that deviates from the identity with a low-rank perturbation. This perturbation is diagonalized in the low-rank space\n\n\n\n\n\n","category":"type"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.HierarchicalLowRankFactor","page":"Random Features","title":"CalibrateEmulateSample.Emulators.HierarchicalLowRankFactor","text":"struct HierarchicalLowRankFactor{FT<:AbstractFloat} <: CalibrateEmulateSample.Emulators.CovarianceStructureType\n\nbuilds a covariance structure that deviates from the identity with a more general low-rank perturbation\n\n\n\n\n\n","category":"type"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.SeparableKernel","page":"Random Features","title":"CalibrateEmulateSample.Emulators.SeparableKernel","text":"struct SeparableKernel{CST1<:CalibrateEmulateSample.Emulators.CovarianceStructureType, CST2<:CalibrateEmulateSample.Emulators.CovarianceStructureType} <: CalibrateEmulateSample.Emulators.KernelStructureType\n\nBuilds a separable kernel, i.e. one that accounts for input and output covariance structure separately\n\n\n\n\n\n","category":"type"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.NonseparableKernel","page":"Random Features","title":"CalibrateEmulateSample.Emulators.NonseparableKernel","text":"struct NonseparableKernel{CST<:CalibrateEmulateSample.Emulators.CovarianceStructureType} <: CalibrateEmulateSample.Emulators.KernelStructureType\n\nBuilds a nonseparable kernel, i.e. one that accounts for a joint input and output covariance structure\n\n\n\n\n\n","category":"type"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.calculate_n_hyperparameters","page":"Random Features","title":"CalibrateEmulateSample.Emulators.calculate_n_hyperparameters","text":"calculate_n_hyperparameters(\n d::Int64,\n odf::CalibrateEmulateSample.Emulators.OneDimFactor\n) -> Int64\n\n\ncalculates the number of hyperparameters generated by the choice of covariance structure\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.hyperparameters_from_flat","page":"Random Features","title":"CalibrateEmulateSample.Emulators.hyperparameters_from_flat","text":"hyperparameters_from_flat(\n x::AbstractVector,\n odf::CalibrateEmulateSample.Emulators.OneDimFactor\n)\n\n\nreshapes a list of hyperparameters into a covariance matrix based on the selected structure\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.build_default_prior","page":"Random Features","title":"CalibrateEmulateSample.Emulators.build_default_prior","text":"build_default_prior(\n name::AbstractString,\n n_hp::Int64,\n odf::CalibrateEmulateSample.Emulators.OneDimFactor\n)\n\n\nbuilds a prior distribution for the kernel hyperparameters to initialize optimization.\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#Scalar-interface","page":"Random Features","title":"Scalar interface","text":"","category":"section"},{"location":"API/RandomFeatures/","page":"Random Features","title":"Random Features","text":"ScalarRandomFeatureInterface\nScalarRandomFeatureInterface(::Int,::Int)\nbuild_models!(::ScalarRandomFeatureInterface, ::PairedDataContainer{FT}) where {FT <: AbstractFloat}\npredict(::ScalarRandomFeatureInterface, ::M) where {M <: AbstractMatrix}","category":"page"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface","page":"Random Features","title":"CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface","text":"struct ScalarRandomFeatureInterface{S<:AbstractString, RNG<:Random.AbstractRNG, KST<:CalibrateEmulateSample.Emulators.KernelStructureType} <: CalibrateEmulateSample.Emulators.RandomFeatureInterface\n\nStructure holding the Scalar Random Feature models. \n\nFields\n\nrfms::Vector{RandomFeatures.Methods.RandomFeatureMethod}: vector of RandomFeatureMethods, contains the feature structure, batch-sizes and regularization\nfitted_features::Vector{RandomFeatures.Methods.Fit}: vector of Fits, containing the matrix decomposition and coefficients of RF when fitted to data\nbatch_sizes::Union{Nothing, Dict{S, Int64}} where S<:AbstractString: batch sizes\nn_features::Union{Nothing, Int64}: n_features\ninput_dim::Int64: input dimension\nrng::Random.AbstractRNG: choice of random number generator\nkernel_structure::CalibrateEmulateSample.Emulators.KernelStructureType: Kernel structure type (e.g. Separable or Nonseparable)\nfeature_decomposition::AbstractString: Random Feature decomposition, choose from \"svd\" or \"cholesky\" (default)\noptimizer_options::Dict{S} where S<:AbstractString: dictionary of options for hyperparameter optimizer\n\n\n\n\n\n","category":"type"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface-Tuple{Int64, Int64}","page":"Random Features","title":"CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface","text":"ScalarRandomFeatureInterface(\n n_features::Int64,\n input_dim::Int64;\n kernel_structure,\n batch_sizes,\n rng,\n feature_decomposition,\n optimizer_options\n) -> CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface{String, Random._GLOBAL_RNG, CalibrateEmulateSample.Emulators.SeparableKernel{CST1, CalibrateEmulateSample.Emulators.OneDimFactor}} where CST1<:CalibrateEmulateSample.Emulators.CovarianceStructureType\n\n\nConstructs a ScalarRandomFeatureInterface <: MachineLearningTool interface for the RandomFeatures.jl package for multi-input and single- (or decorrelated-)output emulators.\n\nn_features - the number of random features\ninput_dim - the dimension of the input space\nkernel_structure - - a prescribed form of kernel structure\nbatch_sizes = nothing - Dictionary of batch sizes passed RandomFeatures.jl object (see definition there)\nrng = Random.GLOBAL_RNG - random number generator \nfeature_decomposition = \"cholesky\" - choice of how to store decompositions of random features, cholesky or svd available\noptimizer_options = nothing - Dict of options to pass into EKI optimization of hyperparameters (defaults created in ScalarRandomFeatureInterface constructor):\n\"prior\": the prior for the hyperparameter optimization \n\"priorinscale\": use this to tune the input prior scale\n\"n_ensemble\": number of ensemble members\n\"n_iteration\": number of eki iterations\n\"covsamplemultiplier\": increase for more samples to estimate covariance matrix in optimization (default 10.0, minimum 0.0) \n\"scheduler\": Learning rate Scheduler (a.k.a. EKP timestepper) Default: DataMisfitController\n\"tikhonov\": tikhonov regularization parameter if >0\n\"inflation\": additive inflation ∈ [0,1] with 0 being no inflation\n\"train_fraction\": e.g. 0.8 (default) means 80:20 train - test split\n\"nfeaturesopt\": fix the number of features for optimization (default n_features, as used for prediction)\n\"multithread\": how to multithread. \"ensemble\" (default) threads across ensemble members \"tullio\" threads random feature matrix algebra\n\"accelerator\": use EKP accelerators (default is no acceleration)\n\"verbose\" => false, verbose optimizer statements\n\n\n\n\n\n","category":"method"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.build_models!-Union{Tuple{FT}, Tuple{CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface, EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT}}} where FT<:AbstractFloat","page":"Random Features","title":"CalibrateEmulateSample.Emulators.build_models!","text":"build_models!(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface,\n input_output_pairs::EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT<:AbstractFloat}\n)\n\n\nBuilds the random feature method from hyperparameters. We use cosine activation functions and a Multivariate Normal distribution (from Distributions.jl) with mean M=0, and input covariance U built with the CovarianceStructureType.\n\n\n\n\n\n","category":"method"},{"location":"API/RandomFeatures/#GaussianProcesses.predict-Union{Tuple{M}, Tuple{CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface, M}} where M<:(AbstractMatrix)","page":"Random Features","title":"GaussianProcesses.predict","text":"predict(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface,\n new_inputs::AbstractMatrix;\n multithread\n) -> Tuple{Any, Any}\n\n\nPrediction of data observation (not latent function) at new inputs (passed in as columns in a matrix). That is, we add the observational noise into predictions.\n\n\n\n\n\n","category":"method"},{"location":"API/RandomFeatures/#Vector-Interface","page":"Random Features","title":"Vector Interface","text":"","category":"section"},{"location":"API/RandomFeatures/","page":"Random Features","title":"Random Features","text":"VectorRandomFeatureInterface\nVectorRandomFeatureInterface(::Int, ::Int, ::Int)\nbuild_models!(::VectorRandomFeatureInterface, ::PairedDataContainer{FT}) where {FT <: AbstractFloat}\npredict(::VectorRandomFeatureInterface, ::M) where {M <: AbstractMatrix}","category":"page"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface","page":"Random Features","title":"CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface","text":"struct VectorRandomFeatureInterface{S<:AbstractString, RNG<:Random.AbstractRNG, KST<:CalibrateEmulateSample.Emulators.KernelStructureType} <: CalibrateEmulateSample.Emulators.RandomFeatureInterface\n\nStructure holding the Vector Random Feature models. \n\nFields\n\nrfms::Vector{RandomFeatures.Methods.RandomFeatureMethod}: A vector of RandomFeatureMethods, contains the feature structure, batch-sizes and regularization\nfitted_features::Vector{RandomFeatures.Methods.Fit}: vector of Fits, containing the matrix decomposition and coefficients of RF when fitted to data\nbatch_sizes::Union{Nothing, Dict{S, Int64}} where S<:AbstractString: batch sizes\nn_features::Union{Nothing, Int64}: number of features\ninput_dim::Int64: input dimension\noutput_dim::Int64: output_dimension\nrng::Random.AbstractRNG: rng\nregularization::Vector{Union{LinearAlgebra.Diagonal, LinearAlgebra.UniformScaling, Matrix}}: regularization\nkernel_structure::CalibrateEmulateSample.Emulators.KernelStructureType: Kernel structure type (e.g. Separable or Nonseparable)\nfeature_decomposition::AbstractString: Random Feature decomposition, choose from \"svd\" or \"cholesky\" (default)\noptimizer_options::Dict: dictionary of options for hyperparameter optimizer\n\n\n\n\n\n","category":"type"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface-Tuple{Int64, Int64, Int64}","page":"Random Features","title":"CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface","text":"VectorRandomFeatureInterface(\n n_features::Int64,\n input_dim::Int64,\n output_dim::Int64;\n kernel_structure,\n batch_sizes,\n rng,\n feature_decomposition,\n optimizer_options\n) -> CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface{String, Random._GLOBAL_RNG, CalibrateEmulateSample.Emulators.SeparableKernel{CST1, CST2}} where {CST1<:CalibrateEmulateSample.Emulators.CovarianceStructureType, CST2<:CalibrateEmulateSample.Emulators.CovarianceStructureType}\n\n\nConstructs a VectorRandomFeatureInterface <: MachineLearningTool interface for the RandomFeatures.jl package for multi-input and multi-output emulators.\n\nn_features - the number of random features\ninput_dim - the dimension of the input space\noutput_dim - the dimension of the output space\nkernel_structure - - a prescribed form of kernel structure\nbatch_sizes = nothing - Dictionary of batch sizes passed RandomFeatures.jl object (see definition there)\nrng = Random.GLOBAL_RNG - random number generator \nfeature_decomposition = \"cholesky\" - choice of how to store decompositions of random features, cholesky or svd available\noptimizer_options = nothing - Dict of options to pass into EKI optimization of hyperparameters (defaults created in VectorRandomFeatureInterface constructor):\n\"prior\": the prior for the hyperparameter optimization\n\"priorinscale\"/\"prioroutscale\": use these to tune the input/output prior scale.\n\"n_ensemble\": number of ensemble members\n\"n_iteration\": number of eki iterations\n\"scheduler\": Learning rate Scheduler (a.k.a. EKP timestepper) Default: DataMisfitController\n\"covsamplemultiplier\": increase for more samples to estimate covariance matrix in optimization (default 10.0, minimum 0.0) \n\"tikhonov\": tikhonov regularization parameter if > 0\n\"inflation\": additive inflation ∈ [0,1] with 0 being no inflation\n\"train_fraction\": e.g. 0.8 (default) means 80:20 train - test split\n\"nfeaturesopt\": fix the number of features for optimization (default n_features, as used for prediction)\n\"multithread\": how to multithread. \"ensemble\" (default) threads across ensemble members \"tullio\" threads random feature matrix algebra\n\"accelerator\": use EKP accelerators (default is no acceleration)\n\"verbose\" => false, verbose optimizer statements to check convergence, priors and optimal parameters.\n\n\n\n\n\n","category":"method"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.build_models!-Union{Tuple{FT}, Tuple{CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface, EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT}}} where FT<:AbstractFloat","page":"Random Features","title":"CalibrateEmulateSample.Emulators.build_models!","text":"build_models!(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface,\n input_output_pairs::EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT<:AbstractFloat};\n regularization_matrix\n) -> Vector{Union{LinearAlgebra.Diagonal, LinearAlgebra.UniformScaling, Matrix}}\n\n\nBuild Vector Random Feature model for the input-output pairs subject to regularization, and optimizes the hyperparameters with EKP. \n\n\n\n\n\n","category":"method"},{"location":"API/RandomFeatures/#GaussianProcesses.predict-Union{Tuple{M}, Tuple{CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface, M}} where M<:(AbstractMatrix)","page":"Random Features","title":"GaussianProcesses.predict","text":"predict(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface,\n new_inputs::AbstractMatrix\n) -> Tuple{Any, Any}\n\n\nPrediction of data observation (not latent function) at new inputs (passed in as columns in a matrix). That is, we add the observational noise into predictions.\n\n\n\n\n\n","category":"method"},{"location":"API/RandomFeatures/#Other-utilities","page":"Random Features","title":"Other utilities","text":"","category":"section"},{"location":"API/RandomFeatures/","page":"Random Features","title":"Random Features","text":"get_rfms\nget_fitted_features\nget_batch_sizes\nget_n_features\nget_input_dim\nget_output_dim\nget_rng\nget_kernel_structure\nget_feature_decomposition\nget_optimizer_options\noptimize_hyperparameters!(::ScalarRandomFeatureInterface) \noptimize_hyperparameters!(::VectorRandomFeatureInterface) \nshrinkage_cov","category":"page"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_rfms","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_rfms","text":"get_rfms(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface\n) -> Vector{RandomFeatures.Methods.RandomFeatureMethod}\n\n\ngets the rfms field\n\n\n\n\n\nget_rfms(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> Vector{RandomFeatures.Methods.RandomFeatureMethod}\n\n\nGets the rfms field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_fitted_features","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_fitted_features","text":"get_fitted_features(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface\n) -> Vector{RandomFeatures.Methods.Fit}\n\n\ngets the fitted_features field\n\n\n\n\n\nget_fitted_features(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> Vector{RandomFeatures.Methods.Fit}\n\n\nGets the fitted_features field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_batch_sizes","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_batch_sizes","text":"get_batch_sizes(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface\n) -> Union{Nothing, Dict{S, Int64}} where S<:AbstractString\n\n\ngets batch_sizes the field\n\n\n\n\n\nget_batch_sizes(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> Union{Nothing, Dict{S, Int64}} where S<:AbstractString\n\n\nGets the batch_sizes field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_n_features","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_n_features","text":"get_n_features(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface\n) -> Union{Nothing, Int64}\n\n\ngets the n_features field\n\n\n\n\n\nget_n_features(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> Union{Nothing, Int64}\n\n\nGets the n_features field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_input_dim","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_input_dim","text":"get_input_dim(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface\n) -> Int64\n\n\ngets the input_dim field\n\n\n\n\n\nget_input_dim(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> Int64\n\n\nGets the input_dim field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_output_dim","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_output_dim","text":"get_output_dim(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> Int64\n\n\nGets the output_dim field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_rng","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_rng","text":"get_rng(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface\n) -> Random.AbstractRNG\n\n\ngets the rng field\n\n\n\n\n\nget_rng(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> Random.AbstractRNG\n\n\nGets the rng field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_kernel_structure","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_kernel_structure","text":"get_kernel_structure(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface\n) -> CalibrateEmulateSample.Emulators.KernelStructureType\n\n\nGets the kernel_structure field\n\n\n\n\n\nget_kernel_structure(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> CalibrateEmulateSample.Emulators.KernelStructureType\n\n\nGets the kernel_structure field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_feature_decomposition","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_feature_decomposition","text":"get_feature_decomposition(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface\n) -> AbstractString\n\n\ngets the feature_decomposition field\n\n\n\n\n\nget_feature_decomposition(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> AbstractString\n\n\nGets the feature_decomposition field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_optimizer_options","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_optimizer_options","text":"get_optimizer_options(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface\n) -> Dict{S} where S<:AbstractString\n\n\ngets the optimizer_options field\n\n\n\n\n\nget_optimizer_options(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> Dict\n\n\nGets the optimizer_options field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.optimize_hyperparameters!-Tuple{CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface}","page":"Random Features","title":"CalibrateEmulateSample.Emulators.optimize_hyperparameters!","text":"optimize_hyperparameters!(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface,\n args...;\n kwargs...\n)\n\n\nEmpty method, as optimization takes place within the build_models stage\n\n\n\n\n\n","category":"method"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.optimize_hyperparameters!-Tuple{CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface}","page":"Random Features","title":"CalibrateEmulateSample.Emulators.optimize_hyperparameters!","text":"optimize_hyperparameters!(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface,\n args...;\n kwargs...\n)\n\n\nEmpty method, as optimization takes place within the build_models stage\n\n\n\n\n\n","category":"method"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.shrinkage_cov","page":"Random Features","title":"CalibrateEmulateSample.Emulators.shrinkage_cov","text":"shrinkage_cov(sample_mat::AbstractMatrix) -> Any\n\n\nCalculate the empirical covariance, additionally applying a shrinkage operator (here the Ledoit Wolf 2004 shrinkage operation). Known to have better stability properties than Monte-Carlo for low sample sizes\n\n\n\n\n\n","category":"function"},{"location":"glossary/#Glossary","page":"Glossary","title":"Glossary","text":"","category":"section"},{"location":"glossary/","page":"Glossary","title":"Glossary","text":"The following list includes the names and symbols of recurring concepts in CalibrateEmulateSample.jl. Some of these variables do not appear in the codebase, which relies on array programming for performance. Contributions to the codebase require following this notational convention. Similarly, if you find inconsistencies in the documentation or codebase, please report an issue on GitHub.","category":"page"},{"location":"glossary/","page":"Glossary","title":"Glossary","text":"Name Symbol (Theory/Docs) Symbol (Code)\nParameter vector, Parameters (unconstrained space) theta θ\nParameter vector size, Number of parameters p N_par\nEnsemble size J N_ens\nEnsemble particles, members theta^(j) \nNumber of iterations N_rm it N_iter\nObservation vector, Observations, Data vector y y\nObservation vector size, Data vector size d N_obs\nObservational noise eta obs_noise\nObservational noise covariance Gamma_y obs_noise_cov\nHilbert space inner product langle phi Gamma^-1 psi rangle \nForward map mathcalG G\nDynamical model Psi Ψ\nTransform map (constrained to unconstrained) mathcalT T\nObservation map mathcalH H\nPrior covariance (unconstrained space) Gamma_theta prior_cov\nPrior mean (unconstrained space) m_theta prior_mean","category":"page"},{"location":"examples/lorenz_example/#Lorenz-96-example","page":"Lorenz example","title":"Lorenz 96 example","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"info: How do I run this code?\nThe full code is found in the examples/ directory of the github repository","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The Lorenz 96 (hereafter L96) example is a toy-problem for the application of the CalibrateEmulateSample.jl optimization and approximate uncertainty quantification methodologies. Here is L96 with additional periodic-in-time forcing, we try to determine parameters (sinusoidal amplitude and stationary component of the forcing) from some output statistics. The standard L96 equations are implemented with an additional forcing term with time dependence. The output statistics which are used for learning are the finite time-averaged variances.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The standard single-scale L96 equations are implemented. The Lorenz 96 system (Lorenz, 1996) is given by ","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"fracd x_id t = (x_i+1 - x_i-2) x_i-1 - x_i + F","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"with i indicating the index of the given longitude. The number of longitudes is given by N. The boundary conditions are given by","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"x_-1 = x_N-1 x_0 = x_N x_N+1 = x_1","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The time scaling is such that the characteristic time is 5 days (Lorenz, 1996). For very small values of F, the solutions x_i decay to F after the initial transient feature. For moderate values of F, the solutions are periodic, and for larger values of F, the system is chaotic. The solution variance is a function of the forcing magnitude. Variations in the base state as a function of time can be imposed through a time-dependent forcing term F(t).","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"A temporal forcing term is defined","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"F = F_s + A sin(omega t)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"with steady-state forcing F_s, transient forcing amplitude A, and transient forcing frequency omega. The total forcing F must be within the chaotic regime of L96 for all time given the prescribed N.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The L96 dynamics are solved with RK4 integration.","category":"page"},{"location":"examples/lorenz_example/#Structure","page":"Lorenz example","title":"Structure","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The example is structured with two distinct components: 1) L96 dynamical system solver; 2) calibrate-emulate sample code. Each of these are described below.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The forward mapping from input parameters to output statistics of the L96 system is solved using the GModel.jl code, which runs the L96 model across different input parameters theta. The source code for the L96 system solution is within the GModel_common.jl code. ","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The Calibrate code is located in calibrate.jl which provides the functionality to run the L96 dynamical system (within the GModel.jl code), extract time-averaged statistics from the L96 states, and use the time-average statistics for calibration. While this example description is self-contained, there is an additional description of the use of EnsembleKalmanProcesses.jl for the L96 example that is accessible here.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The Emulate-Sample code is located in emulate_sample.jl which provides the functionality to use the input-output pairs from the Calibrate stage for emulation and sampling (uncertainty quantification). The emulate_sample.jl code relies on outputs from the calibrate.jl code","category":"page"},{"location":"examples/lorenz_example/#Walkthrough-of-the-code","page":"Lorenz example","title":"Walkthrough of the code","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"This walkthrough covers calibrate-emulate-sample for the L96 problem defined above. The goal is to learn parameters F_s and A based on the time averaged statistics in a perfect model setting. This document focuses on the emulate-sample (emulate_sample.jl) stages, but discussion of the calibration stage calibrate.jl are made when necessary. This code relies on data generated by first running calibrate.jl. A detailed walkthrough of the calibration stage of CES for the L96 example is available here. ","category":"page"},{"location":"examples/lorenz_example/#Inputs","page":"Lorenz example","title":"Inputs","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"First, we load standard packages","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"# Import modules\nusing Distributions # probability distributions and associated functions\nusing LinearAlgebra\nusing StatsPlots\nusing Plots\nusing Random\nusing JLD2","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"Then, we load CalibrateEmulateSample.jl packages","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"# CES \nusing CalibrateEmulateSample.Emulators\nusing CalibrateEmulateSample.MarkovChainMonteCarlo\nusing CalibrateEmulateSample.Utilities\nusing CalibrateEmulateSample.EnsembleKalmanProcesses\nusing CalibrateEmulateSample.ParameterDistributions\nusing CalibrateEmulateSample.DataContainers\nusing CalibrateEmulateSample.Observations","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The first input settings define which input-output pairs to use for training the emulator. The Calibrate stage (run using calibrate.jl) generates parameter-to-data pairs by running the L96 system using an iterative optimization approach (EnsembleKalmanProcess.jl). So we first define which iterations we would like to use data from for our emulator training","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"min_iter = 1\nmax_iter = 5 # number of EKP iterations to use data from is at most this","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The second input settings define the Lorenz dynamics. The emulate_sample.jl code does not actually run the L96 system, it only uses L96 system runs from the calibrate.jl stage to train an emulator and to perform sampling. Therefore, the settings governing the L96 dynamics are fully defined in calibrate.jl and can be modified as necessary. The rest of the input settings in this section are defined in calibrate.jl. ","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"F_true = 8.0 # Mean F\nA_true = 2.5 # Transient F amplitude\nω_true = 2.0 * π / (360.0 / τc) # Frequency of the transient F (non-dim)\nparams_true = [F_true, A_true]\nparam_names = [\"F\", \"A\"]","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The use of the transient forcing term is with the flag, dynamics. Stationary forcing is dynamics=1 (A=0) and transient forcing is used with dynamics=2 (Aneq0). The system with N longitudes is solved over time horizon t_start to Tfit at fixed time step dt.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"N = 36\ndt = 1/64\nt_start = 100\n# Characteristic time scale\nτc = 5.0 # days, prescribed by the L96 problem\n# This has to be less than 360 and 360 must be divisible by Ts_days\nTs_days = 30.0 # Integration length in days (will be made non-dimensional later)\n# Integration length\nTfit = Ts_days / τc","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The states are integrated over time Ts_days to construct the time averaged statistics for use by the Ensemble Kalman Process calibration. The specification of the statistics to be gathered from the states are provided by stats_type.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"We implement (biased) priors as follows","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"prior_means = [F_true + 1.0, A_true + 0.5]\nprior_stds = [2.0, 0.5 * A_true]\n# constrained_gaussian(\"name\", desired_mean, desired_std, lower_bd, upper_bd)\nprior_F = constrained_gaussian(param_names[1], prior_means[1], prior_stds[1], 0, Inf)\nprior_A = constrained_gaussian(param_names[2], prior_means[2], prior_stds[2], 0, Inf)\npriors = combine_distributions([prior_F, prior_A])","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"We use the recommended [constrained_gaussian] to add the desired scale and bounds to the prior distribution, in particular we place lower bounds to preserve positivity. ","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The priors can be plotted directly using plot(priors), as seen below in the example code from calibrate.jl","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"# Plot the prior distribution\np = plot(priors, title = \"prior\")\nplot!(p.subplots[1], [F_true], seriestype = \"vline\", w = 1.5, c = :steelblue, ls = :dash, xlabel = \"F\") # vline on top histogram\nplot!(p.subplots[2], [A_true], seriestype = \"vline\", w = 1.5, c = :steelblue, ls = :dash, xlabel = \"A\") # vline on top histogram","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The observational noise can be generated using the L96 system or prescribed, as specified by var_prescribe. var_prescribe==false The observational noise is constructed by generating independent instantiations of the L96 statistics of interest at the true parameters for different initial conditions. The empirical covariance matrix is constructed.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"var_prescribe==true The observational noise is prescribed as a Gaussian distribution with prescribed mean and variance.","category":"page"},{"location":"examples/lorenz_example/#Calibrate","page":"Lorenz example","title":"Calibrate","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The calibration stage must be run before the emulate-sample stages. The calibration stage is run using calibrate.jl. This code will generate parameter-data pairs that will be used to train the emulator. The parameter-data pairs are visualized below","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"","category":"page"},{"location":"examples/lorenz_example/#Emulate","page":"Lorenz example","title":"Emulate","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"Having run the calibrate.jl code to generate input-output pairs from parameters to data using EnsembleKalmanProcesses.jl, we will now run the Emulate and Sample stages (emulate_sample.jl). First, we need to define which machine learning model we will use for the emulation. We have 8 cases that the user can toggle or customize","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"cases = [\n \"GP\", # diagonalize, train scalar GP, assume diag inputs\n \"RF-scalar-diagin\", # diagonalize, train scalar RF, assume diag inputs (most comparable to GP)\n \"RF-scalar\", # diagonalize, train scalar RF, do not asume diag inputs\n \"RF-vector-svd-diag\",\n \"RF-vector-svd-nondiag\",\n \"RF-vector-nosvd-diag\",\n \"RF-vector-nosvd-nondiag\",\n \"RF-vector-svd-nonsep\",\n]","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The first is for GP with GaussianProcesses.jl interface. The next two are for the scalar RF interface, which most closely follows exactly replacing a GP. The rest are examples of vector RF with different types of data processing, (svd = same processing as scalar RF, nosvd = unprocessed) and different RF kernel structures in the output space of increasing complexity/flexibility (diag = Separable diagonal, nondiag = Separable nondiagonal, nonsep = nonseparable nondiagonal).","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The example then loads the relevant training data that was constructed in the calibrate.jl call. ","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"# loading relevant data\nhomedir = pwd()\nprintln(homedir)\nfigure_save_directory = joinpath(homedir, \"output/\")\ndata_save_directory = joinpath(homedir, \"output/\")\ndata_save_file = joinpath(data_save_directory, \"calibrate_results.jld2\")\nekiobj = load(data_save_file)[\"eki\"]\npriors = load(data_save_file)[\"priors\"]\ntruth_sample_mean = load(data_save_file)[\"truth_sample_mean\"]\ntruth_sample = load(data_save_file)[\"truth_sample\"]\ntruth_params_constrained = load(data_save_file)[\"truth_input_constrained\"] #true parameters in constrained space\ntruth_params = transform_constrained_to_unconstrained(priors, truth_params_constrained)\nΓy = ekiobj.obs_noise_cov","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"We then set up the structure of the emulator. An example for GP (GP)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"gppackage = Emulators.GPJL()\npred_type = Emulators.YType()\nmlt = GaussianProcess(\n gppackage;\n kernel = nothing, # use default squared exponential kernel\n prediction_type = pred_type,\n noise_learn = false,\n)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"which calls GaussianProcess.jl. In this L96 example, since we focus on learning F_s and A, we do not need to explicitly learn the noise, so noise_learn = false.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"An example for scalar RF (RF-scalar)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"n_features = 100\nkernel_structure = SeparableKernel(LowRankFactor(2, nugget), OneDimFactor())\nmlt = ScalarRandomFeatureInterface(\n n_features,\n n_params,\n rng = rng,\n kernel_structure = kernel_structure,\n optimizer_options = overrides,\n)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"Optimizer options for ScalarRandomFeature.jl are provided throough overrides","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"overrides = Dict(\n \"verbose\" => true,\n \"scheduler\" => DataMisfitController(terminate_at = 100.0),\n \"cov_sample_multiplier\" => 1.0,\n \"n_iteration\" => 20,\n )\n# we do not want termination, as our priors have relatively little interpretation","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"We then build the emulator with the parameters as defined above","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"emulator = Emulator(\n mlt,\n input_output_pairs;\n obs_noise_cov = Γy,\n normalize_inputs = normalized,\n standardize_outputs = standardize,\n standardize_outputs_factors = norm_factor,\n retained_svd_frac = retained_svd_frac,\n decorrelate = decorrelate,\n )","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"For RF and some GP packages, the training occurs during construction of the Emulator, however sometimes one must call an optimize step afterwards","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"optimize_hyperparameters!(emulator)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The emulator is checked for accuracy by evaluating its predictions on the true parameters","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"# Check how well the Gaussian Process regression predicts on the\n# true parameters\ny_mean, y_var = Emulators.predict(emulator, reshape(truth_params, :, 1), transform_to_real = true)\ny_mean_test, y_var_test = Emulators.predict(emulator, get_inputs(input_output_pairs_test), transform_to_real = true)\n\nprintln(\"ML prediction on true parameters: \")\nprintln(vec(y_mean))\nprintln(\"true data: \")\nprintln(truth_sample) # what was used as truth\nprintln(\" ML predicted standard deviation\")\nprintln(sqrt.(diag(y_var[1], 0)))\nprintln(\"ML MSE (truth): \")\nprintln(mean((truth_sample - vec(y_mean)) .^ 2))\nprintln(\"ML MSE (next ensemble): \")\nprintln(mean((get_outputs(input_output_pairs_test) - y_mean_test) .^ 2))","category":"page"},{"location":"examples/lorenz_example/#Sample","page":"Lorenz example","title":"Sample","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"Now the emulator is constructed and validated, so we next focus on the MCMC sampling. First, we run a short chain (2000 steps) to determine the step size","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"# First lets run a short chain to determine a good step size\nmcmc = MCMCWrapper(RWMHSampling(), truth_sample, priors, emulator; init_params = u0)\nnew_step = optimize_stepsize(mcmc; init_stepsize = 0.1, N = 2000, discard_initial = 0)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The step size has been determined, so now we run the full MCMC (100000 steps where the first 2000 are discarded)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"# Now begin the actual MCMC\nprintln(\"Begin MCMC - with step size \", new_step)\nchain = MarkovChainMonteCarlo.sample(mcmc, 100_000; stepsize = new_step, discard_initial = 2_000)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"And we finish by extracting the posterior samples","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"posterior = MarkovChainMonteCarlo.get_posterior(mcmc, chain)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"And evaluate the results with these printed statements","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"post_mean = mean(posterior)\npost_cov = cov(posterior)\nprintln(\"post_mean\")\nprintln(post_mean)\nprintln(\"post_cov\")\nprintln(post_cov)\nprintln(\"D util\")\nprintln(det(inv(post_cov)))\nprintln(\" \")","category":"page"},{"location":"examples/lorenz_example/#Running-the-Example-and-Postprocessing","page":"Lorenz example","title":"Running the Example and Postprocessing","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"First, the calibrate code must be executed, which will perform the calibration step and, generating input-output pairs of the parameter to data mapping. Then, the emulate-sample code is run, which will load the input-ouput pairs that were generated in the calibration step.","category":"page"},{"location":"examples/lorenz_example/#Calibrate-2","page":"Lorenz example","title":"Calibrate","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The L96 parameter calibration can be run using julia --project calibrate.jl","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The output will provide the estimated parameters in the constrained ϕ-space. The priors are required in the get-method to apply these constraints.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"Printed output:","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"# EKI results: Has the ensemble collapsed toward the truth?\nprintln(\"True parameters: \")\nprintln(params_true)\nprintln(\"\\nEKI results:\")\nprintln(get_ϕ_mean_final(priors, ekiobj))","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The parameters and forward model outputs will be saved in parameter_storage.jld2 and data_storage.jld2, respectively. The data will be saved in the directory output. A scatter plot animation of the ensemble convergence to the true parameters is saved in the directory output. These points represent the training points that are used for the emulator.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"","category":"page"},{"location":"examples/lorenz_example/#Emulate-sample","page":"Lorenz example","title":"Emulate-sample","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The L96 parameter estimation can be run using julia --project emulate_sample.jl","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The output will provide the estimated posterior distribution over the parameters. The emulate-sample code will run for several choices in the machine learning model that is used for the emulation stage, inclding Gaussian Process regression and RF, and using singular value data decorrelation or not. ","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The sampling results from two emulators are shown below. We can see that the posterior is relatively insensitive to the choice of the machine learning emulation tool in this L96 example.","category":"page"},{"location":"examples/lorenz_example/#L96-CES-example-case:-GP-regression-emulator-(case\"GP\")","page":"Lorenz example","title":"L96 CES example case: GP regression emulator (case=\"GP\")","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"","category":"page"},{"location":"examples/lorenz_example/#L96-CES-example-case:-RF-scalar-emulator-(case\"RF-scalar\")","page":"Lorenz example","title":"L96 CES example case: RF scalar emulator (case=\"RF-scalar\")","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"","category":"page"},{"location":"examples/emulators/regression_2d_2d/#Regression-of-\\mathbb{R}2-\\to-\\mathbb{R}2-smooth-function","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"","category":"section"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"info: How do I run this code?\nThe full code is found in the examples/Emulator/ directory of the github repository","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"In this example, we assess directly the performance of our machine learning emulators. The task is to learn the function:","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"Gcolon 02pi^2 to mathbbR^2 G(x_1x_2) = (sin(x_1) + cos(x_2) sin(x_1) - cos(x_2)) ","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"observed at 150 points, subject to additive (and possibly correlated) Gaussian noise N(0Sigma).","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We have several different emulator configurations in this example that the user can play around with. The goal of this example is to predict the function (i.e. posterior mean) and uncertainty (i.e posterior pointwise variance) on a 200times200 grid providing a mean square error between emulated and true function and with plot_flag = true we also save several plots.","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We will term scalar-output Gaussin process emulator as \"GP\", scalar-output random feature emulator as \"scalar RF\", and vector-output random feature emulator as \"vector RF\" henceforth.","category":"page"},{"location":"examples/emulators/regression_2d_2d/#Walkthrough-of-the-code","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Walkthrough of the code","text":"","category":"section"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We first import some standard packages","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"using Random\nusing StableRNGs\nusing Distributions\nusing Statistics\nusing LinearAlgebra","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"and relevant CES packages needed to define the emulators, packages and kernel structures","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"using CalibrateEmulateSample.Emulators\n# Contains `Emulator`, `GaussianProcess`, `ScalarRandomFeatureInterface`, `VectorRandomFeatureInterface`\n# `GPJL`, `SKLJL`, `SeparablKernel`, `NonSeparableKernel`, `OneDimFactor`, `LowRankFactor`, `DiagonalFactor`\nusing CalibrateEmulateSample.DataContainers # Contains `PairedDataContainer`","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"To play with the hyperparameter optimization of RF, the optimizer options sometimes require EnsembleKalmanProcesses.jl structures, so we load this too","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"using CalibrateEmulateSample.EnsembleKalmanProcesses # Contains `DataMisfitController`","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We have 9 cases that the user can toggle or customize","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"cases = [\n \"gp-skljl\",\n \"gp-gpjl\", # Very slow prediction...\n \"rf-scalar\",\n \"rf-svd-diag\",\n \"rf-svd-nondiag\",\n \"rf-nosvd-diag\",\n \"rf-nosvd-nondiag\",\n \"rf-svd-nonsep\",\n \"rf-nosvd-nonsep\",\n]","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"The first two are for GP with either ScikitLearn.jl or GaussianProcesses.jl interface. The third is for the scalar RF interface, which most closely follows exactly replacing a GP. The rest are examples of vector RF with different types of data processing, (svd = same processing as scalar RF, nosvd = unprocessed) and different RF kernel structures in the output space of increasing complexity/flexibility (diag = Separable diagonal, nondiag = Separable nondiagonal, nonsep = nonseparable nondiagonal).","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We set up the learning problem specification, defining input and output dimensions, and number of data to train on, and the function g and the perturbed samples y with correlated additive noise","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"n = 150 # number of training points\np = 2 # input dim \nd = 2 # output dim\nX = 2.0 * π * rand(p, n)\n# G(x1, x2)\ng1x = sin.(X[1, :]) .+ cos.(X[2, :])\ng2x = sin.(X[1, :]) .- cos.(X[2, :])\ngx = zeros(2, n)\ngx[1, :] = g1x\ngx[2, :] = g2x\n# Add noise η\nμ = zeros(d)\nΣ = 0.1 * [[0.8, 0.1] [0.1, 0.5]] # d x d\nnoise_samples = rand(MvNormal(μ, Σ), n)\n# y = G(x) + η\nY = gx .+ noise_samples","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We then enter this in a paired data container, which gives a standard of how the data will be read","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"iopairs = PairedDataContainer(X, Y, data_are_columns = true)","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We define some common settings for all emulators, e.g. the number of random features to use, and some hyperparameter optimizer options","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"# common Gaussian feature setup\npred_type = YType()\n\n# common random feature setup\nn_features = 150\noptimizer_options = Dict(\"n_iteration\" => 10, \"scheduler\" => DataMisfitController(on_terminate = \"continue\"))\nnugget = 1e-12","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We then build the emulators. An example for GP (gp-skljl)","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"# use scikit learn\ngppackage = SKLJL()\n# build a GP that learns an additional white noise kernel (along with the default RBF kernel)\ngaussian_process = GaussianProcess(gppackage, noise_learn = true)\n# the data processing normalizes input data, and decorrelates output data with information from Σ\nemulator = Emulator(gaussian_process, iopairs, obs_noise_cov = Σ, normalize_inputs = true) ","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"An example for scalar RF (rf-scalar)","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"# build a scalar RF with a rank-2 kernel in input space (placeholder 1D kernel in output space) and use the optimizer options during training\nsrfi = ScalarRandomFeatureInterface(\n n_features, \n p, \n kernel_structure = SeparableKernel(LowRankFactor(2, nugget), OneDimFactor()), \n optimizer_options = optimizer_options,\n)\n# the data processing normalizes input data, and decorrelates output data with information from Σ\nemulator = Emulator(srfi, iopairs, obs_noise_cov = Σ, normalize_inputs = true)","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"An example for vector RF (rf-nosvd-nonsep)","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"# build a vector RF with a rank-4 nonseparable kernel and use the optimizer options during training\nvrfi = VectorRandomFeatureInterface(\n n_features,\n p,\n d, # additionally provide the output dimensions size\n kernel_structure = NonseparableKernel(LowRankFactor(4, nugget)),\n optimizer_options = optimizer_options,\n)\n# the data processing normalizes input data, and does not decorrelate outputs\nemulator = Emulator(vrfi, iopairs, obs_noise_cov = Σ, normalize_inputs = true, decorrelate = false)","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"For RF and some GP packages, the training occurs during construction of the Emulator, however sometimes one must call an optimize step afterwards","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"optimize_hyperparameters!(emulator)","category":"page"},{"location":"examples/emulators/regression_2d_2d/#Validation-and-Plots","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Validation and Plots","text":"","category":"section"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We create an evaluation grid for our models, in the right shape:","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"n_pts = 200\nx1 = range(0.0, stop = 2 * π, length = n_pts)\nx2 = range(0.0, stop = 2 * π, length = n_pts)\nX1, X2 = meshgrid(x1, x2)\ninputs = permutedims(hcat(X1[:], X2[:]), (2, 1))","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We predict using the emulators at the new inputs, and transform_to_real inverts the data processing back to physical values","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"em_mean, em_cov = predict(emulator, inputs, transform_to_real = true)","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We then plot the predicted mean and pointwise variances, and calculate the errors from the three highlighted cases:","category":"page"},{"location":"examples/emulators/regression_2d_2d/#Gaussian-Process-Emulator-(Sci-kit-learn:-gp-skljl)","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Gaussian Process Emulator (Sci-kit learn: gp-skljl)","text":"","category":"section"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"L^2 error of mean and latent truth:0.0008042391077774167","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"\n","category":"page"},{"location":"examples/emulators/regression_2d_2d/#Random-Feature-Emulator-(rf-scalar)","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Random Feature Emulator (rf-scalar)","text":"","category":"section"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"L^2 error of mean and latent truth:0.0012253119679379056","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"\n","category":"page"},{"location":"examples/emulators/regression_2d_2d/#Random-Feature-Emulator-(vector:-rf-nosvd-nonsep)","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Random Feature Emulator (vector: rf-nosvd-nonsep)","text":"","category":"section"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"L^2 error of mean and latent truth:0.0011094292509180393","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"\n","category":"page"},{"location":"GaussianProcessEmulator/#Gaussian-Process-Emulator","page":"Gaussian Process","title":"Gaussian Process Emulator","text":"","category":"section"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"One type of MachineLearningTool we provide for emulation is a Gaussian process. Gaussian processes are a generalization of the Gaussian probability distribution, extended to functions rather than random variables. They can be used for statistical emulation, as they provide both mean and covariances. To build a Gaussian process, we first define a prior over all possible functions, by choosing the covariance function or kernel. The kernel describes how similar two outputs (y_i, y_j) are, given the similarities between their input values (x_i, x_j). Kernels encode the functional form of these relationships and are defined by hyperparameters, which are usually initially unknown to the user. To learn the posterior Gaussian process, we condition on data using Bayes theorem and optimize the hyperparameters of the kernel. Then, we can make predictions to predict a mean function and covariance for new data points.","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"A useful resource to learn about Gaussian processes is Rasmussen and Williams (2006).","category":"page"},{"location":"GaussianProcessEmulator/#User-Interface","page":"Gaussian Process","title":"User Interface","text":"","category":"section"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"CalibrateEmulateSample.jl allows the Gaussian process emulator to be built using either GaussianProcesses.jl or ScikitLearn.jl. Different packages may be optimized for different settings, we recommend users give both a try, and checkout the individual package documentation to make a choice for their problem setting. ","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"To use GaussianProcesses.jl, define the package type as","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"gppackage = Emulators.GPJL()","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"To use ScikitLearn.jl, define the package type as","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"gppackage = Emulators.SKLJL()","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"Initialize a basic Gaussian Process with","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"gauss_proc = GaussianProcess(gppackage)","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"This initializes the prior Gaussian process. We train the Gaussian process by feeding the gauss_proc alongside the data into the Emulator struct and optimizing the hyperparameters, described here.","category":"page"},{"location":"GaussianProcessEmulator/#Prediction-Type","page":"Gaussian Process","title":"Prediction Type","text":"","category":"section"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"You can specify the type of prediction when initializing the Gaussian Process emulator. The default type of prediction is to predict data, YType(). You can create a latent function type prediction with","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"gauss_proc = GaussianProcess(\n gppackage,\n prediction_type = FType())\n","category":"page"},{"location":"GaussianProcessEmulator/#Kernels","page":"Gaussian Process","title":"Kernels","text":"","category":"section"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"The Gaussian process above assumes the default kernel: the Squared Exponential kernel, also called the Radial Basis Function (RBF). A different type of kernel can be specified when the Gaussian process is initialized. Read more about kernel options here.","category":"page"},{"location":"GaussianProcessEmulator/#GPJL","page":"Gaussian Process","title":"GPJL","text":"","category":"section"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"For the GaussianProcess.jl package, there are a range of kernels to choose from. For example, ","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"using GaussianProcesses\nmy_kernel = GaussianProcesses.Mat32Iso(0., 0.) # Create a Matern 3/2 kernel with lengthscale=0 and sd=0\ngauss_proc = GaussianProcess(\n gppackage;\n kernel = my_kernel )","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"You do not need to provide useful hyperparameter values when you define the kernel, as these are learned in optimize_hyperparameters!(emulator).","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"You can also combine kernels together through linear operations, for example,","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"using GaussianProcesses\nkernel_1 = GaussianProcesses.Mat32Iso(0., 0.) # Create a Matern 3/2 kernel with lengthscale=0 and sd=0\nkernel_2 = GaussianProcesses.Lin(0.) # Create a linear kernel with lengthscale=0\nmy_kernel = kernel_1 + kernel_2 # Create a new additive kernel\ngauss_proc = GaussianProcess(\n gppackage;\n kernel = my_kernel )","category":"page"},{"location":"GaussianProcessEmulator/#SKLJL","page":"Gaussian Process","title":"SKLJL","text":"","category":"section"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"Alternatively if you are using the ScikitLearn.jl package, you can find the list of kernels here. These need this preamble:","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"using PyCall\nusing ScikitLearn\nconst pykernels = PyNULL()\nfunction __init__()\n copy!(pykernels, pyimport(\"sklearn.gaussian_process.kernels\"))\nend","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"Then they are accessible, for example, as","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"my_kernel = pykernels.RBF(length_scale = 1)\ngauss_proc = GaussianProcess(\n gppackage;\n kernel = my_kernel )","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"You can also combine multiple ScikitLearn kernels via linear operations in the same way as above.","category":"page"},{"location":"GaussianProcessEmulator/#Learning-additional-white-noise","page":"Gaussian Process","title":"Learning additional white noise","text":"","category":"section"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"Often it is useful to learn the discrepancy between the Gaussian process prediction and the data, by learning additional white noise. Though one often knows, and provides, the discrepancy between the true model and data with an observational noise covariance; the additional white kernel can help account for approximation error from the selected Gaussian process kernel and the true model. This is added with the Boolean keyword noise_learn when initializing the Gaussian process. The default is true. ","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"gauss_proc = GaussianProcess(\n gppackage;\n noise_learn = true )","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"When noise_learn is true, an additional white noise kernel is added to the kernel. This white noise is present across all parameter values, including the training data. The scale parameters of the white noise kernel are learned in optimize_hyperparameters!(emulator). ","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"You may not need to learn the noise if you already have a good estimate of the noise from your training data, and if the Gaussian process kernel is well specified. When noise_learn is false, a small additional regularization is added for stability. The default value is 1e-3 but this can be chosen through the optional argument alg_reg_noise:","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"gauss_proc = GaussianProcess(\n gppackage;\n noise_learn = false,\n alg_reg_noise = 1e-3 )","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/#Integrating-Lorenz-63-with-an-emulated-integrator","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"","category":"section"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"info: How do I run this code?\nThe full code is found in the examples/Emulator/ directory of the github repository","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"In this example, we assess directly the performance of our machine learning emulators. The task is to learn the forward Euler integrator of a Lorenz 63 system. The model parameters are set to their classical settings (sigma rho beta) = (1028frac83) to exhibit chaotic behavior. The discrete system is given as:","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"beginaligned\nx(t_n+1) = x(t_n) + Delta t(y(t_n) - x(t_n))\ny(t_n+1) = y(t_n) + Delta t(x(t_n)(28 - z(t_n)) - y(t_n))\nz(t_n+1) = z(t_n) + Delta t(x(t_n)y(t_n) - frac83z(t_n))\nendaligned","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"where t_n = nDelta t. The data consists of pairs (x(t_k)y(t_k)z(t_k)) (x(t_k+1)y(t_k+1)z(t_k+1)+eta_k for 600 values of k, with each output subjected to independent, additive Gaussian noise eta_ksim N(0Gamma_y).","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"We have several different emulator configurations in this example that the user can play around with. The goal of the emulator is that the posterior mean will approximate this discrete update map, or integrator, for any point on the Lorenz attractor from the sparse noisy data. To validate this, we recursively apply the trained emulator to the state, plotting the evolution of the trajectory and marginal statistics of the states over short and long timescales. We include a repeats option (n_repeats) to run the randomized training for multiple trials and illustrate robustness of marginal statistics by plotting long time marginal cdfs of the state. ","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"We will term scalar-output Gaussin process emulator as \"GP\", and scalar- or vector-output random feature emulator as \"RF\".","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/#Walkthrough-of-the-code","page":"Integrating Lorenz 63 with an emulated integrator","title":"Walkthrough of the code","text":"","category":"section"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"We first import some standard packages","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"using Random, Distributions, LinearAlgebra # utilities\nusing CairoMakie, ColorSchemes # for plots\nusing JLD2 # for saved data","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"For the true integrator of the Lorenz system we import","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"using OrdinaryDiffEq ","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"For relevant CES packages needed to define the emulators, packages and kernel structures","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"using CalibrateEmulateSample.Emulators\n# Contains `Emulator`, `GaussianProcess`, `ScalarRandomFeatureInterface`, `VectorRandomFeatureInterface`\n# `GPJL`, `SeparablKernel`, `NonSeparableKernel`, `OneDimFactor`, `LowRankFactor`, `DiagonalFactor`\nusing CalibrateEmulateSample.DataContainers # Contains `PairedDataContainer`","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"and if one wants to play with optimizer options for the random feature emulators we import","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"using CalibrateEmulateSample.EnsembleKalmanProcesses # Contains `DataMisfitController`","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"We generate the truth data using OrdinaryDiffEq: the time series sol is used for training data, sol_test is used for plotting short time trajectories, and sol_hist for plotting histograms of the state over long times:","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"# Run L63 from 0 -> tmax\nu0 = [1.0; 0.0; 0.0]\ntmax = 20\ndt = 0.01\ntspan = (0.0, tmax)\nprob = ODEProblem(lorenz, u0, tspan)\nsol = solve(prob, Euler(), dt = dt)\n\n# Run L63 from end for test trajectory data\ntmax_test = 100\ntspan_test = (0.0, tmax_test)\nu0_test = sol.u[end]\nprob_test = ODEProblem(lorenz, u0_test, tspan_test)\nsol_test = solve(prob_test, Euler(), dt = dt)\n\n# Run L63 from end for histogram matching data\ntmax_hist = 1000\ntspan_hist = (0.0, tmax_hist)\nu0_hist = sol_test.u[end]\nprob_hist = ODEProblem(lorenz, u0_hist, tspan_hist)\nsol_hist = solve(prob_hist, Euler(), dt = dt)","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"We generate the training data from sol within [tburn, tmax]. The user has the option of how many training points to take n_train_pts and whether these are selected randomly or sequentially (sample_rand). The true outputs are perturbed by noise of variance 1e-4 and pairs are stored in the compatible data format PairedDataContainer","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"tburn = 1 # NB works better with no spin-up!\nburnin = Int(floor(tburn / dt))\nn_train_pts = 600 \nsample_rand = true\nif sample_rand\n ind = Int.(shuffle!(rng, Vector(burnin:(tmax / dt - 1)))[1:n_train_pts])\nelse\n ind = burnin:(n_train_pts + burnin)\nend\nn_tp = length(ind)\ninput = zeros(3, n_tp)\noutput = zeros(3, n_tp)\nΓy = 1e-4 * I(3)\nnoise = rand(rng, MvNormal(zeros(3), Γy), n_tp)\nfor i in 1:n_tp\n input[:, i] = sol.u[ind[i]]\n output[:, i] = sol.u[ind[i] + 1] + noise[:, i]\nend\niopairs = PairedDataContainer(input, output)","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"We have several cases the user can play with,","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"cases = [\"GP\", \"RF-scalar\", \"RF-scalar-diagin\", \"RF-svd-nonsep\", \"RF-nosvd-nonsep\", \"RF-nosvd-sep\"]","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"Then, looping over the repeats, we first define some common hyperparamter optimization options for the \"RF-\" cases. In this case, the options are used primarily for diagnostics and acceleration (not required in general to solve this problem) ","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"rf_optimizer_overrides = Dict(\n \"verbose\" => true, # output diagnostics from the hyperparameter optimizer\n \"scheduler\" => DataMisfitController(terminate_at = 1e4), # timestepping method for the optimizer\n \"cov_sample_multiplier\" => 0.5, # 0.5*default number of samples to estimate covariances in optimizer\n \"n_features_opt\" => 200, # number of features during hyperparameter optimization\n \"n_iteration\" => 20, # iterations of the optimizer solver\n)","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"Then we build the machine learning tools. Here we highlight scalar-output Gaussian process (GP), where we use the default squared-exponential kernel, and learn a lengthscale hyperparameter in each input dimension. To handle multiple outputs, we will use a decorrelation in the output space, and so will actually train three of these models.","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"gppackage = Emulators.GPJL() # use GaussianProcesses.jl\npred_type = Emulators.YType() # predicted variances are for data not latent function\nmlt = GaussianProcess(\n gppackage;\n prediction_type = pred_type,\n noise_learn = false, # do not additionally learn a white kernel\n)","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"we also highlight the Vector Random Feature with nonseparable kernel (RF-nosvd-nonsep), this can natively handle multiple outputs without decorrelation of the output space. This kernel is a rank-3 representation with small nugget term.","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"nugget = 1e-12\nkernel_structure = NonseparableKernel(LowRankFactor(3, nugget))\nn_features = 500 # number of features for prediction\nmlt = VectorRandomFeatureInterface(\n n_features,\n 3, # input dimension\n 3, # output dimension\n rng = rng, # pin random number generator\n kernel_structure = kernel_structure,\n optimizer_options = rf_optimizer_overrides, \n) ","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"With machine learning tools specified, we build the emulator object","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"# decorrelate = true for `GP`\n# decorrelate = false for `RF-nosvd-nonsep`\nemulator = Emulator(mlt, iopairs; obs_noise_cov = Γy, decorrelate = decorrelate) \noptimize_hyperparameters!(emulator) # some GP packages require this additional call ","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/#Plots","page":"Integrating Lorenz 63 with an emulated integrator","title":"Plots","text":"","category":"section"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"We predict the trained emulator mean, over the short-timescale validation trajectory","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"u_test_tmp = zeros(3, length(xspan_test))\nu_test_tmp[:, 1] = sol_test.u[1] # initialize at the final-time solution of the training period\n\nfor i in 1:(length(xspan_test) - 1)\n rf_mean, _ = predict(emulator, u_test_tmp[:, i:i], transform_to_real = true) # 3x1 matrix\n u_test_tmp[:, i + 1] = rf_mean\nend","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"The other trajectories are similar. We then produce the following plots. In all figures, the results from evolving the state with the true integrator is orange, and with the emulated integrators are blue.","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/#Gaussian-Process-Emulator-(Sci-kit-learn:-GP)","page":"Integrating Lorenz 63 with an emulated integrator","title":"Gaussian Process Emulator (Sci-kit learn: GP)","text":"","category":"section"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"For one example fit","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"\n","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/#Random-Feature-Emulator-(RF-nosvd-nonsep)","page":"Integrating Lorenz 63 with an emulated integrator","title":"Random Feature Emulator (RF-nosvd-nonsep)","text":"","category":"section"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"For one example fit","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"\n","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"and here are CDFs over 20 randomized trials of the random feature hyperparameter optimization","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"","category":"page"},{"location":"API/GaussianProcess/#GaussianProcess","page":"Gaussian Process","title":"GaussianProcess","text":"","category":"section"},{"location":"API/GaussianProcess/","page":"Gaussian Process","title":"Gaussian Process","text":"CurrentModule = CalibrateEmulateSample.Emulators","category":"page"},{"location":"API/GaussianProcess/","page":"Gaussian Process","title":"Gaussian Process","text":"GaussianProcessesPackage\nPredictionType\nGaussianProcess\nGaussianProcess(\n ::GPPkg;\n ::Union{K, KPy, Nothing},\n ::Any,\n ::FT,\n ::PredictionType,\n) where {GPPkg <: GaussianProcessesPackage, K <: Kernel, KPy <: PyObject, FT <: AbstractFloat}\nbuild_models!(::GaussianProcess{GPJL}, ::PairedDataContainer{FT}) where {FT <: AbstractFloat}\noptimize_hyperparameters!(::GaussianProcess{GPJL})\npredict(::GaussianProcess{GPJL}, ::AbstractMatrix{FT}) where {FT <: AbstractFloat}","category":"page"},{"location":"API/GaussianProcess/#CalibrateEmulateSample.Emulators.GaussianProcessesPackage","page":"Gaussian Process","title":"CalibrateEmulateSample.Emulators.GaussianProcessesPackage","text":"abstract type GaussianProcessesPackage\n\nType to dispatch which GP package to use:\n\nGPJL for GaussianProcesses.jl,\nSKLJL for the ScikitLearn GaussianProcessRegressor.\n\n\n\n\n\n","category":"type"},{"location":"API/GaussianProcess/#CalibrateEmulateSample.Emulators.PredictionType","page":"Gaussian Process","title":"CalibrateEmulateSample.Emulators.PredictionType","text":"abstract type PredictionType\n\nPredict type for GPJL in GaussianProcesses.jl:\n\nYType\nFType latent function.\n\n\n\n\n\n","category":"type"},{"location":"API/GaussianProcess/#CalibrateEmulateSample.Emulators.GaussianProcess","page":"Gaussian Process","title":"CalibrateEmulateSample.Emulators.GaussianProcess","text":"struct GaussianProcess{GPPackage, FT} <: CalibrateEmulateSample.Emulators.MachineLearningTool\n\nStructure holding training input and the fitted Gaussian process regression models.\n\nFields\n\nmodels::Vector{Union{Nothing, PyCall.PyObject, GaussianProcesses.GPE}}: The Gaussian Process (GP) Regression model(s) that are fitted to the given input-data pairs.\nkernel::Union{Nothing, var\"#s17\", var\"#s18\"} where {var\"#s17\"<:GaussianProcesses.Kernel, var\"#s18\"<:PyCall.PyObject}: Kernel object.\nnoise_learn::Bool: Learn the noise with the White Noise kernel explicitly?\nalg_reg_noise::Any: Additional observational or regularization noise in used in GP algorithms\nprediction_type::CalibrateEmulateSample.Emulators.PredictionType: Prediction type (y to predict the data, f to predict the latent function).\n\n\n\n\n\n","category":"type"},{"location":"API/GaussianProcess/#CalibrateEmulateSample.Emulators.GaussianProcess-Union{Tuple{FT}, Tuple{KPy}, Tuple{K}, Tuple{GPPkg}} where {GPPkg<:CalibrateEmulateSample.Emulators.GaussianProcessesPackage, K<:GaussianProcesses.Kernel, KPy<:PyCall.PyObject, FT<:AbstractFloat}","page":"Gaussian Process","title":"CalibrateEmulateSample.Emulators.GaussianProcess","text":"GaussianProcess(\n package::AbstractFloat;\n kernel,\n noise_learn,\n alg_reg_noise,\n prediction_type\n)\n\n\npackage - GaussianProcessPackage object.\nkernel - GaussianProcesses kernel object. Default is a Squared Exponential kernel.\nnoise_learn - Boolean to additionally learn white noise in decorrelated space. Default is true.\nalg_reg_noise - Float to fix the (small) regularization parameter of algorithms when noise_learn = true\nprediction_type - PredictionType object. Default predicts data, not latent function (FType()).\n\n\n\n\n\n","category":"method"},{"location":"API/GaussianProcess/#CalibrateEmulateSample.Emulators.build_models!-Union{Tuple{FT}, Tuple{CalibrateEmulateSample.Emulators.GaussianProcess{CalibrateEmulateSample.Emulators.GPJL}, EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT}}} where FT<:AbstractFloat","page":"Gaussian Process","title":"CalibrateEmulateSample.Emulators.build_models!","text":"build_models!(\n gp::CalibrateEmulateSample.Emulators.GaussianProcess{CalibrateEmulateSample.Emulators.GPJL},\n input_output_pairs::EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT<:AbstractFloat}\n)\n\n\nMethod to build Gaussian process models based on the package.\n\n\n\n\n\n","category":"method"},{"location":"API/GaussianProcess/#CalibrateEmulateSample.Emulators.optimize_hyperparameters!-Tuple{CalibrateEmulateSample.Emulators.GaussianProcess{CalibrateEmulateSample.Emulators.GPJL}}","page":"Gaussian Process","title":"CalibrateEmulateSample.Emulators.optimize_hyperparameters!","text":"optimize_hyperparameters!(\n gp::CalibrateEmulateSample.Emulators.GaussianProcess{CalibrateEmulateSample.Emulators.GPJL},\n args...;\n kwargs...\n)\n\n\nOptimize Gaussian process hyperparameters using in-build package method.\n\nWarning: if one uses GPJL() and wishes to modify positional arguments. The first positional argument must be the Optim method (default LBGFS()).\n\n\n\n\n\n","category":"method"},{"location":"API/GaussianProcess/#GaussianProcesses.predict-Union{Tuple{FT}, Tuple{CalibrateEmulateSample.Emulators.GaussianProcess{CalibrateEmulateSample.Emulators.GPJL}, AbstractMatrix{FT}}} where FT<:AbstractFloat","page":"Gaussian Process","title":"GaussianProcesses.predict","text":"predict(\n gp::CalibrateEmulateSample.Emulators.GaussianProcess{CalibrateEmulateSample.Emulators.GPJL},\n new_inputs::AbstractArray{FT<:AbstractFloat, 2}\n) -> Tuple{Any, Any}\n\n\nPredict means and covariances in decorrelated output space using Gaussian process models.\n\n\n\n\n\n","category":"method"},{"location":"sample/#The-Sample-stage","page":"Sample","title":"The Sample stage","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"CurrentModule = CalibrateEmulateSample.MarkovChainMonteCarlo","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"The \"sample\" part of CES refers to exact sampling from the emulated posterior, in our current framework this is achieved with a Markov chain Monte Carlo algorithm (MCMC). Within this paradigm, we want to provide the flexibility to use multiple sampling algorithms; the approach we take is to use the general-purpose AbstractMCMC.jl API, provided by the Turing.jl probabilistic programming framework.","category":"page"},{"location":"sample/#User-interface","page":"Sample","title":"User interface","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"We briefly outline an instance of how one sets up and uses MCMC within the CES package. The user first loads the MCMC module, and provides one of the Protocols (i.e. how one wishes to generate sampling proposals)","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"using CalibrateEmulateSample.MarkovChainMonteCarlo\nprotocol = RWMHSampling() # Random-Walk algorithm\n# protocol = pCNMHSampling() # preconditioned-Crank-Nicholson algorithm","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"Then one builds the MCMC by providing the standard Bayesian ingredients (prior and data) from the calibrate stage, alongside the trained statistical emulator from the emulate stage:","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"mcmc = MCMCWrapper(\n protocol,\n truth_sample, \n prior,\n emulator;\n init_params=mean_u_final,\n burnin=10_000,\n)","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"The keyword arguments init_params give a starting step of the chain (often taken to be the mean of the final iteration of calibrate stage), and a burnin gives a number of initial steps to be discarded when drawing statistics from the sampling method.","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"For good efficiency, one often needs to run MCMC with a problem-dependent step size. We provide a simple utility to help choose this. Here the optimizer runs short chains (of length N), and adjusts the step-size until the MCMC acceptance rate falls within an acceptable range, returning this step size.","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"new_step = optimize_stepsize(\nmcmc;\ninit_stepsize = 1,\nN = 2000\n)","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"To generate 10^5 samples with a given step size (and optional random number generator rng), one calls","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"chain = sample(rng, mcmc, 100_000; stepsize = new_step)\ndisplay(chain) # gives diagnostics","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"The return argument is stored in an MCMCChains.Chains object. To convert this back into a ParameterDistribution type (which contains e.g. the transformation maps) one can call","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"posterior = get_posterior(mcmc, chain)\nconstrained_posterior = transform_unconstrained_to_constrained(prior, get_distribution(posterior))","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"One can quickly plot the marginals of the prior and posterior distribution with","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"using Plots\nplot(prior)\nplot!(posterior)","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"or extract statistics of the (unconstrained) distribution with","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"mean_posterior = mean(posterior)\ncov_posterior = cov(posterior)","category":"page"},{"location":"sample/#AbstractMCMC-sampling-API","page":"Sample","title":"Further details on the implementation","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"This page provides a summary of AbstractMCMC which augments the existing documentation ([1], [2]) and highlights how it's used by the CES package in MarkovChainMonteCarlo. It's not meant to be a complete description of the AbstractMCMC package.","category":"page"},{"location":"sample/#Use-in-MarkovChainMonteCarlo","page":"Sample","title":"Use in MarkovChainMonteCarlo","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"At present, Turing has limited support for derivative-free optimization, so we only use this abstract API and not Turing itself. We also use two related dependencies, AdvancedMH and MCMCChains. ","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"Julia's philosophy is to use small, composable packages rather than monoliths, but this can make it difficult to remember where methods are defined! Below we describe the relevant parts of ","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"The AbstractMCMC API,\nExtended to the case of Metropolis-Hastings (MH) sampling by AdvancedMH,\nFurther extended for the needs of CES in Markov chain Monte Carlo.","category":"page"},{"location":"sample/#Sampler","page":"Sample","title":"Sampler","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"A Sampler is AbstractMCMC's term for an implementation of a MCMC sampling algorithm, along with all its configuration parameters. All samplers are a subtype of AbstractMCMC's AbstractSampler. ","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"Currently CES only implements the Metropolis-Hastings (MH) algorithm. Because it's so straightforward, much of AbstractMCMC isn't needed. We implement two variants of MH with two different Samplers: RWMetropolisHastings and pCNMetropolisHastings, both of which are subtypes of AdvancedMH.MHSampler. The constructor for both Samplers is MetropolisHastingsSampler; the different Samplers are specified by passing a MCMCProtocol object to this constructor.","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"The MHSampler has only one field, proposal, the distribution used to generate new MH proposals via additive stochastic perturbations to the current parameter values. This is done by AdvancedMH.propose(), which gets called for each MCMC step(). The difference between Samplers comes from how the proposal is generated:","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"RWMHSampling does vanilla random-walk proposal generation with a constant, user-specified step size (this differs from the AdvancedMH implementation, which doesn't provide for a step size.)\npCNMHSampling for preconditioned Crank-Nicholson proposals. Vanilla random walk sampling doesn't have a well-defined limit for high-dimensional parameter spaces; pCN replaces the random walk with an Ornstein–Uhlenbeck [AR(1)] process so that the Metropolis acceptance probability remains non-zero in this limit. See Beskos et. al. (2008) and Cotter et. al. (2013).","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"Generated proposals are then either accepted or rejected according to the same MH criterion (in step(), below.)","category":"page"},{"location":"sample/#Models","page":"Sample","title":"Models","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"In Turing, the Model is the distribution one performs inference on, which may involve observed and hidden variables and parameters. For CES, we simply want to sample from the posterior, so our Model distribution is simply the emulated likelihood (see Emulators) together with the prior. This is constructed by EmulatorPosteriorModel.","category":"page"},{"location":"sample/#Sampling-with-the-MCMC-Wrapper-object","page":"Sample","title":"Sampling with the MCMC Wrapper object","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"At a high level, a Sampler and Model is all that's needed to do MCMC sampling. This is done by the sample method provided by AbstractMCMC (extending the method from BaseStats). ","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"To be more user-friendly, in CES we wrap the Sampler, Model and other necessary configuration into a MCMCWrapper object. The constructor for this object ensures that all its components are created consistently, and performs necessary bookkeeping, such as converting coordinates to the decorrelated basis. We extend sample with methods to use this object (that simply unpack its fields and call the appropriate method from AbstractMCMC.)","category":"page"},{"location":"sample/#Chain","page":"Sample","title":"Chain","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"The MCMCChain package provides the Chains container to store the results of the MCMC sampling; the package provides methods to for quick diagnostics and plot utilities of the the Chains objects. For example,","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"using MCMCChains\nusing StatsPlots\n\n# ... from our MCMC example above ...\n# chain = sample(rng, mcmc, 100_000; stepsize = new_step)\n\ndisplay(chain) # diagnostics\nplot(chain) # plots samples over iteration and PDFs for each parameter","category":"page"},{"location":"sample/#Internals:-Transitions","page":"Sample","title":"Internals: Transitions","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"Implementing MCMC involves defining states and transitions of a Markov process (whose stationary distribution is what we seek to sample from). AbstractMCMC's terminology is a bit confusing for the MH case; states of the chain are described by Transition objects, which contain the current sample (and other information like its log-probability). ","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"AdvancedMH defines an AbstractTransition base class for use with its methods; we implement our own child class, MCMCState, in order to record statistics on the MH acceptance ratio.","category":"page"},{"location":"sample/#Internals:-Markov-steps","page":"Sample","title":"Internals: Markov steps","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"Markov transitions of the chain are defined by overloading AbstractMCMC's step method, which takes the Sampler and current Transition and implements the Sampler's logic to returns an updated Transition representing the chain's new state (actually, a pair of Transitions, for cases where the Sampler doesn't obey detailed balance; this isn't relevant for us). ","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"For example, in Metropolis-Hastings sampling this is where we draw a proposal sample and accept or reject it according to the MH criterion. AdvancedMH implements this here; we re-implement this method because 1) we need to record whether a proposal was accepted or rejected, and 2) our calls to propose() are stepsize-dependent.","category":"page"},{"location":"API/MarkovChainMonteCarlo/#MarkovChainMonteCarlo","page":"MarkovChainMonteCarlo","title":"MarkovChainMonteCarlo","text":"","category":"section"},{"location":"API/MarkovChainMonteCarlo/","page":"MarkovChainMonteCarlo","title":"MarkovChainMonteCarlo","text":"CurrentModule = CalibrateEmulateSample.MarkovChainMonteCarlo","category":"page"},{"location":"API/MarkovChainMonteCarlo/#Top-level-class-and-methods","page":"MarkovChainMonteCarlo","title":"Top-level class and methods","text":"","category":"section"},{"location":"API/MarkovChainMonteCarlo/","page":"MarkovChainMonteCarlo","title":"MarkovChainMonteCarlo","text":"MCMCWrapper\nMCMCWrapper(mcmc_alg::MCMCProtocol, obs_sample::AbstractVector{FT}, prior::ParameterDistribution, em::Emulator;init_params::AbstractVector{FT}, burnin::IT, kwargs...) where {FT<:AbstractFloat, IT<:Integer}\nsample\nget_posterior\noptimize_stepsize","category":"page"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCWrapper","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCWrapper","text":"struct MCMCWrapper\n\nTop-level class holding all configuration information needed for MCMC sampling: the prior, emulated likelihood and sampling algorithm (DensityModel and Sampler, respectively, in AbstractMCMC's terminology).\n\nFields\n\nprior::EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution: ParameterDistribution object describing the prior distribution on parameter values.\nlog_posterior_map::AbstractMCMC.AbstractModel: AdvancedMH.DensityModel object, used to evaluate the posterior density being sampled from.\nmh_proposal_sampler::AbstractMCMC.AbstractSampler: Object describing a MCMC sampling algorithm and its settings.\nsample_kwargs::NamedTuple: NamedTuple of other arguments to be passed to AbstractMCMC.sample().\n\n\n\n\n\n","category":"type"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCWrapper-Union{Tuple{IT}, Tuple{FT}, Tuple{CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCProtocol, AbstractVector{FT}, EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution, CalibrateEmulateSample.Emulators.Emulator}} where {FT<:AbstractFloat, IT<:Integer}","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCWrapper","text":"MCMCWrapper(\n mcmc_alg::CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCProtocol,\n obs_sample::AbstractArray{FT<:AbstractFloat, 1},\n prior::EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution,\n em::CalibrateEmulateSample.Emulators.Emulator;\n init_params,\n burnin,\n kwargs...\n)\n\n\nConstructor for MCMCWrapper which performs the same standardization (SVD decorrelation) that was applied in the Emulator. It creates and wraps an instance of EmulatorPosteriorModel, for sampling from the Emulator, and MetropolisHastingsSampler, for generating the MC proposals.\n\nmcmc_alg: MCMCProtocol describing the MCMC sampling algorithm to use. Currently implemented algorithms are:\nRWMHSampling: Metropolis-Hastings sampling from a vanilla random walk with fixed stepsize.\npCNMHSampling: Metropolis-Hastings sampling using the preconditioned Crank-Nicholson algorithm, which has a well-behaved small-stepsize limit.\nobs_sample: A single sample from the observations. Can, e.g., be picked from an Observation struct using get_obs_sample.\nprior: ParameterDistribution object containing the parameters' prior distributions.\nem: Emulator to sample from. \nstepsize: MCMC step size, applied as a scaling to the prior covariance.\ninit_params: Starting parameter values for MCMC sampling.\nburnin: Initial number of MCMC steps to discard from output (pre-convergence).\n\n\n\n\n\n","category":"method"},{"location":"API/MarkovChainMonteCarlo/#StatsBase.sample","page":"MarkovChainMonteCarlo","title":"StatsBase.sample","text":"sample([rng,] mcmc::MCMCWrapper, args...; kwargs...)\n\nExtends the sample methods of AbstractMCMC (which extends StatsBase) to sample from the emulated posterior, using the MCMC sampling algorithm and Emulator configured in MCMCWrapper. Returns a MCMCChains.Chains object containing the samples. \n\nSupported methods are:\n\nsample([rng, ]mcmc, N; kwargs...)\nReturn a MCMCChains.Chains object containing N samples from the emulated posterior.\nsample([rng, ]mcmc, isdone; kwargs...)\nSample from the model with the Markov chain Monte Carlo sampler until a convergence criterion isdone returns true, and return the samples. The function isdone has the signature\n isdone(rng, model, sampler, samples, state, iteration; kwargs...)\nwhere state and iteration are the current state and iteration of the sampler, respectively. It should return true when sampling should end, and false otherwise.\nsample([rng, ]mcmc, parallel_type, N, nchains; kwargs...)\nSample nchains Monte Carlo Markov chains in parallel according to parallel_type, which may be MCMCThreads() or MCMCDistributed() for thread and parallel sampling, respectively.\n\n\n\n\n\n","category":"function"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.get_posterior","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.get_posterior","text":"get_posterior(\n mcmc::CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCWrapper,\n chain::MCMCChains.Chains\n) -> EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution\n\n\nReturns a ParameterDistribution object corresponding to the empirical distribution of the samples in chain.\n\nnote: Note\nThis method does not currently support combining samples from multiple Chains.\n\n\n\n\n\n","category":"function"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.optimize_stepsize","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.optimize_stepsize","text":"optimize_stepsize(\n rng::Random.AbstractRNG,\n mcmc::CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCWrapper;\n init_stepsize,\n N,\n max_iter,\n sample_kwargs...\n) -> Float64\n\n\nUses a heuristic to return a stepsize for the mh_proposal_sampler element of MCMCWrapper which yields fast convergence of the Markov chain.\n\nThe criterion used is that Metropolis-Hastings proposals should be accepted between 15% and 35% of the time.\n\n\n\n\n\n","category":"function"},{"location":"API/MarkovChainMonteCarlo/","page":"MarkovChainMonteCarlo","title":"MarkovChainMonteCarlo","text":"See AbstractMCMC sampling API for background on our use of Turing.jl's AbstractMCMC API for MCMC sampling.","category":"page"},{"location":"API/MarkovChainMonteCarlo/#Sampler-algorithms","page":"MarkovChainMonteCarlo","title":"Sampler algorithms","text":"","category":"section"},{"location":"API/MarkovChainMonteCarlo/","page":"MarkovChainMonteCarlo","title":"MarkovChainMonteCarlo","text":"MCMCProtocol\nRWMHSampling\npCNMHSampling\nMetropolisHastingsSampler","category":"page"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCProtocol","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCProtocol","text":"abstract type MCMCProtocol\n\nType used to dispatch different methods of the MetropolisHastingsSampler constructor, corresponding to different sampling algorithms.\n\n\n\n\n\n","category":"type"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.RWMHSampling","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.RWMHSampling","text":"struct RWMHSampling <: CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCProtocol\n\nMCMCProtocol which uses Metropolis-Hastings sampling that generates proposals for new parameters as as vanilla random walk, based on the covariance of prior.\n\n\n\n\n\n","category":"type"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.pCNMHSampling","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.pCNMHSampling","text":"struct pCNMHSampling <: CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCProtocol\n\nMCMCProtocol which uses Metropolis-Hastings sampling that generates proposals for new parameters according to the preconditioned Crank-Nicholson (pCN) algorithm, which is usable for MCMC in the stepsize → 0 limit, unlike the vanilla random walk. Steps are based on the covariance of prior.\n\n\n\n\n\n","category":"type"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.MetropolisHastingsSampler","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.MetropolisHastingsSampler","text":"MetropolisHastingsSampler(\n _::CalibrateEmulateSample.MarkovChainMonteCarlo.RWMHSampling,\n prior::EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution\n) -> CalibrateEmulateSample.MarkovChainMonteCarlo.RWMetropolisHastings{D} where D<:(AdvancedMH.RandomWalkProposal{false})\n\n\nConstructor for all Sampler objects, with one method for each supported MCMC algorithm.\n\nwarning: Warning\nBoth currently implemented Samplers use a Gaussian approximation to the prior: specifically, new Metropolis-Hastings proposals are a scaled combination of the old parameter values and a random shift distributed as a Gaussian with the same covariance as the prior. This suffices for our current use case, in which our priors are Gaussian (possibly in a transformed space) and we assume enough fidelity in the Emulator that inference isn't prior-dominated.\n\n\n\n\n\n","category":"function"},{"location":"API/MarkovChainMonteCarlo/#Emulated-posterior-(Model)","page":"MarkovChainMonteCarlo","title":"Emulated posterior (Model)","text":"","category":"section"},{"location":"API/MarkovChainMonteCarlo/","page":"MarkovChainMonteCarlo","title":"MarkovChainMonteCarlo","text":"EmulatorPosteriorModel","category":"page"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.EmulatorPosteriorModel","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.EmulatorPosteriorModel","text":"EmulatorPosteriorModel(\n prior::EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution,\n em::CalibrateEmulateSample.Emulators.Emulator{FT<:AbstractFloat},\n obs_sample::AbstractArray{FT<:AbstractFloat, 1}\n) -> AdvancedMH.DensityModel{F} where F<:(CalibrateEmulateSample.MarkovChainMonteCarlo.var\"#1#2\"{EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution{PDType, CType, ST}, CalibrateEmulateSample.Emulators.Emulator{FT}, <:AbstractVector{FT1}} where {PDType<:EnsembleKalmanProcesses.ParameterDistributions.ParameterDistributionType, CType<:EnsembleKalmanProcesses.ParameterDistributions.ConstraintType, ST<:AbstractString, FT<:AbstractFloat, FT1<:AbstractFloat})\n\n\nFactory which constructs AdvancedMH.DensityModel objects given a prior on the model parameters (prior) and an Emulator of the log-likelihood of the data given parameters. Together these yield the log posterior density we're attempting to sample from with the MCMC, which is the role of the DensityModel class in the AbstractMCMC interface.\n\n\n\n\n\n","category":"function"},{"location":"API/MarkovChainMonteCarlo/#Internals-MCMC-State","page":"MarkovChainMonteCarlo","title":"Internals - MCMC State","text":"","category":"section"},{"location":"API/MarkovChainMonteCarlo/","page":"MarkovChainMonteCarlo","title":"MarkovChainMonteCarlo","text":"MCMCState\naccept_ratio","category":"page"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCState","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCState","text":"struct MCMCState{T, L<:Real} <: AdvancedMH.AbstractTransition\n\nExtends the AdvancedMH.Transition (which encodes the current state of the MC during sampling) with a boolean flag to record whether this state is new (arising from accepting a Metropolis-Hastings proposal) or old (from rejecting a proposal).\n\nFields\n\nparams::Any: Sampled value of the parameters at the current state of the MCMC chain.\nlog_density::Real: Log probability of params, as computed by the model using the prior.\naccepted::Bool: Whether this state resulted from accepting a new MH proposal.\n\n\n\n\n\n","category":"type"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.accept_ratio","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.accept_ratio","text":"accept_ratio(chain::MCMCChains.Chains) -> Any\n\n\nFraction of MC proposals in chain which were accepted (according to Metropolis-Hastings.)\n\n\n\n\n\n","category":"function"},{"location":"API/MarkovChainMonteCarlo/#Internals-Other","page":"MarkovChainMonteCarlo","title":"Internals - Other","text":"","category":"section"},{"location":"API/MarkovChainMonteCarlo/","page":"MarkovChainMonteCarlo","title":"MarkovChainMonteCarlo","text":"to_decorrelated","category":"page"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.to_decorrelated","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.to_decorrelated","text":"to_decorrelated(\n data::AbstractArray{FT<:AbstractFloat, 2},\n em::CalibrateEmulateSample.Emulators.Emulator{FT<:AbstractFloat}\n) -> Any\n\n\nTransform samples from the original (correlated) coordinate system to the SVD-decorrelated coordinate system used by Emulator. Used in the constructor for MCMCWrapper.\n\n\n\n\n\n","category":"function"},{"location":"random_feature_emulator/#Random-Feature-Emulator","page":"Random Features","title":"Random Feature Emulator","text":"","category":"section"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"note: Have a go with Gaussian processes first\nWe recommend that users first try GaussianProcess for their problems. As random features are a more recent tool, the training procedures and interfaces are still experimental and in development. ","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Random features provide a flexible framework to approximates a Gaussian process. Using random sampling of features, the method is a low-rank approximation leading to advantageous scaling properties (with the number of training points, input, and output dimensions). In the infinite sample limit, there are often (known) explicit Gaussian process kernels that the random feature representation converges to.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"We provide two types of MachineLearningTool for random feature emulation, the ScalarRandomFeatureInterface and the VectorRandomFeatureInterface.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"The ScalarRandomFeatureInterface closely mimics the role of a GaussianProcess package, by training a scalar-output function distribution. It can be applied to multidimensional output problems (as with GaussianProcess) by relying on data processing tools, such as performed when the decorrelate=true keyword argument is provided to the Emulator.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"The VectorRandomFeatureInterface, when applied to multidimensional problems, directly trains a function distribution between multi-dimensional spaces. This approach is not restricted to the data processing of the scalar method (though this can still be helpful). It can be cheaper to evaluate, but on the other hand the training can be more challenging/computationally expensive.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Building a random feature interface is similar to building a Gaussian process: one defines a kernel to encode similarities between outputs (y_iy_j) based on inputs (x_ix_j). Additionally, one must specify the number of random feature samples to be taken to build the emulator.","category":"page"},{"location":"random_feature_emulator/#Recommended-configuration","page":"Random Features","title":"Recommended configuration","text":"","category":"section"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Below is listed a recommended configuration that is flexible and requires learning relatively few parameters. Users can increase r to balance flexibility against having more kernel hyperparameters to learn.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"using CalibrateEmulateSample.Emulators\n# given input_dim, output_dim, and a PairedDataContainer\n\n# define number of features for prediction\nn_features = 400 # number of features for prediction \n\n# define kernel \nnugget = 1e8*eps() # small nugget term\nr = 1 # start with smallest rank \nlr_perturbation = LowRankFactor(r, nugget) \nnonsep_lrp_kernel = NonseparableKernel(lr_perturbation) \n\n# configure optimizer\noptimizer_options = Dict(\n \"verbose\" => true, # print diagnostics for optimizer\n \"n_features_opt\" => 100, # use less features during hyperparameter optimization/kernel learning\n \"cov_sample_multiplier\" => 1.0, # use to reduce/increase number of samples in initial cov estimation stage\n)\n\nmachine_learning_tool = VectorRandomFeatureInterface(\n n_features,\n input_dim,\n output_dim,\n kernel_structure = nonsep_lrp_kernel,\n optimizer_options = optimizer_options\n)","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Users can change the kernel complexity with r, and the number of features for prediciton with n_features and optimization with n_features_opt. ","category":"page"},{"location":"random_feature_emulator/#User-Interface","page":"Random Features","title":"User Interface","text":"","category":"section"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"CalibrateEmulateSample.jl allows the random feature emulator to be built using the external package RandomFeatures.jl. In the notation of this package's documentation, our interface allows for families of RandomFourierFeature objects to be constructed with different Gaussian distributions of the \"xi\" a.k.a weight distribution, and with a learnable \"sigma\", a.k.a scaling parameter.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"note: Relating features and kernels\nThe parallels of random features and gaussian processes can be quite strong. For example:The restriction to RandomFourierFeature objects is a restriction to the approximation of shift-invariant kernels (i.e. K(xy) = K(x-y))\nThe restriction of the weight (\"xi\") distribution to Gaussians is a restriction of approximating squared-exponential kernels. Other distributions (e.g. student-t) leads to other kernels (e.g. Matern)","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"The interfaces are defined minimally with","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"srfi = ScalarRandomFeatureInterface(n_features, input_dim; ...)\nvrfi = VectorRandomFeatureInterface(n_features, input_dim, output_dim; ...)","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"This will build an interface around a random feature family based on n_features features and mapping between spaces of dimenstion input_dim to 1 (scalar), or output_dim (vector).","category":"page"},{"location":"random_feature_emulator/#The-kernel_structure-keyword-for-flexibility","page":"Random Features","title":"The kernel_structure keyword - for flexibility","text":"","category":"section"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"To adjust the expressivity of the random feature family one can define the keyword argument kernel_structure. The more expressive the kernel, the more hyperparameters are learnt in the optimization. ","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"We have two types,","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"separable_kernel = SeparableKernel(input_cov_structure, output_cov_structure)\nnonseparable_kernel = NonseparableKernel(cov_structure)","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"where the cov_structure implies some imposed user structure on the covariance structure. The basic covariance structures are given by ","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"oned_cov_structure = OneDimFactor() # the problem dimension is 1\ndiagonal_structure = DiagonalFactor() # impose diagonal structure (e.g. ARD kernel)\ncholesky_structure = CholeskyFactor() # general positive definite matrix\nlr_perturbation = LowRankFactor(r) # assume structure is a rank-r perturbation from identity","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"All covariance structures (except OneDimFactor) have their final positional argument being a \"nugget\" term adding +epsilon I to the covariance structure. Set to 1 by default.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"The current default kernels are as follows:","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"scalar_default_kernel = SeparableKernel(LowRankFactor(Int(ceil(sqrt(input_dim)))), OneDimFactor())\nvector_default_kernel = SeparableKernel(LowRankFactor(Int(ceil(sqrt(output_dim)))), LowRankFactor(Int(ceil(sqrt(output_dim)))))","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"note: Relating covariance structure and training\nThe parallels between random feature and Gaussian process also extends to the hyperparameter learning. For example,A ScalarRandomFeatureInterface with a DiagonalFactor input covariance structure approximates a Gaussian process with automatic relevance determination (ARD) kernel, where one learns a lengthscale in each dimension of the input space","category":"page"},{"location":"random_feature_emulator/#The-optimizer_options-keyword-for-performance","page":"Random Features","title":"The optimizer_options keyword - for performance","text":"","category":"section"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Passed as a dictionary, this keyword allows the user to configure many options from their defaults in the hyperparameter optimization. The optimizer itself relies on the EnsembleKalmanProcesses package.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"We recommend users experiment with a subset of these flags. At first enable","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Dict(\"verbose\" => true)","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"If the covariance sampling takes too long, run with multithreading (e.g. julia --project -t n_threads script.jl). Sampling is embarassingly parallel so this acheives near linear scaling,","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"If sampling still takes too long, try setting","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Dict(\n \"cov_sample_multiplier\" => csm,\n \"train_fraction\" => tf,\n)","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Decreasing csm (default 10.0) towards 0.0 directly reduces the number of samples to estimate a covariance matrix in the optimizer, by using a shrinkage estimator to improve matrix conditioning. Guide: more samples implies less shrinkage for good conditioning and less approximation error. The amount of shrinkage is returned to user as a value between 0 (no shrinkage) and 1 (shrink to diagonal matrix), it is suggested that users choose csm to keep the shrinkage amount below 0.2.\nIncreasing tf towards 1 changes the train-validate split, reducing samples but increasing cost-per-sample and reducing the available validation data (default 0.8, suggested range (0.5,0.95)).","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"If optimizer convergence stagnates or is too slow, or if it terminates before producing good results, try:","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Dict(\n \"n_ensemble\" => n_e, \n \"n_iteration\" => n_i,\n \"localization\" => loc,\n \"scheduler\" => sch,\n)","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"We suggest looking at the EnsembleKalmanProcesses documentation for more details; but to summarize","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Reducing optimizer samples n_e and iterations n_i reduces computation time but may limit convergence progress, see here.\nIf n_e becomes less than the number of hyperparameters, the updates may fail and a localizer must be specified in loc, see here. \nIf the algorithm terminates at T=1 and resulting emulators looks unacceptable one can change or add arguments in sch e.g. DataMisfitController(\"on_terminate\"=continue), see here","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"note: Note\nWidely robust defaults here are a work in progress","category":"page"},{"location":"random_feature_emulator/#Key-methods","page":"Random Features","title":"Key methods","text":"","category":"section"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"To interact with the kernel/covariance structures we have standard get_* methods along with some useful functions","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"cov_structure_from_string(string,dim) creates a basic covariance structure from a predefined string: onedim, diagonal, cholesky, lowrank etc. and a dimension\ncalculate_n_hyperparameters(in_dim, out_dim, kernel_structure) calculates the number of hyperparameters created by using the given kernel structure (can be applied to the covariance structure individually too)\nbuild_default_priors(in_dim, out_dim, kernel_structure) creates a ParameterDistribution for the hyperparameters based on the kernel structure. This serves as the initialization of the training procedure.","category":"page"},{"location":"random_feature_emulator/#Example-families-and-their-hyperparameters","page":"Random Features","title":"Example families and their hyperparameters","text":"","category":"section"},{"location":"random_feature_emulator/#Scalar:-\\mathbb{R}5-\\to-\\mathbb{R}-at-defaults","page":"Random Features","title":"Scalar: mathbbR^5 to mathbbR at defaults","text":"","category":"section"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"using CalibrateEmulateSample.Emulators\ninput_dim = 5\n# build the default scalar kernel directly (here it will be a rank-3 perturbation from the identity)\nscalar_default_kernel = SeparableKernel(\n cov_structure_from_string(\"lowrank\", input_dim),\n cov_structure_from_string(\"onedim\", 1)\n) \n\ncalculate_n_hyperparameters(input_dim, scalar_default_kernel) \n# answer = 19, 18 for the covariance structure, and one scaling parameter\n\nbuild_default_prior(input_dim, scalar_default_kernel)\n# builds a 3-entry distribution\n# 3-dim positive distribution 'input_lowrank_diagonal'\n# 15-dim unbounded distribution 'input_lowrank_U'\n# 1-dim positive distribution `sigma`","category":"page"},{"location":"random_feature_emulator/#Vector,-separable:-\\mathbb{R}{25}-\\to-\\mathbb{R}{50}-at-defaults","page":"Random Features","title":"Vector, separable: mathbbR^25 to mathbbR^50 at defaults","text":"","category":"section"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Or take a diagonalized 8-dimensional input, and assume full 6-dimensional output","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"using CalibrateEmulateSample.Emulators\ninput_dim = 25\noutput_dim = 50\n# build the default vector kernel directly (here it will be a rank-5 input and rank-8 output)\nvector_default_kernel = SeparableKernel(\n cov_structure_from_string(\"lowrank\", input_dim),\n cov_structure_from_string(\"lowrank\", output_dim)\n)\n\ncalculate_n_hyperparameters(input_dim, output_dim, vector_default_kernel) \n# answer = 539; 130 for input, 408 for the output, and 1 scaling\n\nbuild_default_prior(input_dim, output_dim, vector_default_kernel)\n# builds a 5-entry distribution\n# 5-dim positive distribution 'input_lowrank_diagonal'\n# 125-dim unbounded distribution 'input_lowrank_U'\n# 8-dim positive distribution 'output_lowrank_diagonal'\n# 400-dim unbounded distribution 'output_lowrank_U'\n# 1-dim postive distribution `sigma`","category":"page"},{"location":"random_feature_emulator/#Vector,-nonseparable:-\\mathbb{R}{25}-\\to-\\mathbb{R}{50}","page":"Random Features","title":"Vector, nonseparable: mathbbR^25 to mathbbR^50","text":"","category":"section"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"The following represents the most general kernel case.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"note: Note\nUse low-rank/diagonls representations where possible to control the number of hyperparameters.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"using CalibrateEmulateSample.Emulators\ninput_dim = 25\noutput_dim = 50\neps = 1e-8\nrank=5\n# build a full-rank nonseparable vector kernel\nvector_lowrank_kernel = NonseparableKernel(LowRankFactor(rank, eps))\n\ncalculate_n_hyperparameters(input_dim, output_dim, vector_lowrank_kernel)\n# answer = 6256; 6255 for the joint input-output space, and 1 scaling\n\nbuild_default_prior(input_dim, output_dim, vector_lowrank_kernel)\n# builds a 2-entry distribution\n# 5-dim positive distribution 'full_lowrank_diagonal'\n# 6250-dim unbounded distribution 'full_lowrank_U'\n# 1-dim positive distribution `sigma`","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"warning: Warning\nNaive representations lead to very large numbers of hyperparameters.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"using CalibrateEmulateSample.Emulators\ninput_dim = 25\noutput_dim = 50\neps = 1e-8\n# build a full-rank nonseparable vector kernel\nvector_general_kernel = NonseparableKernel(CholeskyFactor(eps))\n\ncalculate_n_hyperparameters(input_dim, output_dim, vector_general_kernel)\n# answer = 781876; 781875 for the joint input-output space, and 1 scaling\n\nbuild_default_prior(input_dim, output_dim, vector_general_kernel)\n# builds a 2-entry distribution\n# 781875-dim unbounded distribution 'full_cholesky'\n# 1-dim positive distribution `sigma`","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"See the API for more details.","category":"page"},{"location":"calibrate/#The-Calibrate-stage","page":"Calibrate","title":"The Calibrate stage","text":"","category":"section"},{"location":"calibrate/","page":"Calibrate","title":"Calibrate","text":"Calibration of the computer model entails finding an optimal parameter theta^* that maximizes the posterior probability","category":"page"},{"location":"calibrate/","page":"Calibrate","title":"Calibrate","text":"rho(thetavert y Gamma_y) = dfrace^-mathcalL(theta y)Z(yvertGamma_y)rho_mathrmprior(theta) qquad mathcalL(theta y) = langle mathcalG(theta) - y Gamma_y^-1 left ( mathcalG(theta) - y right ) rangle","category":"page"},{"location":"calibrate/","page":"Calibrate","title":"Calibrate","text":"where mathcalL is the loss or negative log-likelihood, Z(yvertGamma) is a normalizing constant, y represents the data, Gamma_y is the noise covariance matrix and rho_mathrmprior(theta) is the prior density. Calibration is performed using ensemble Kalman processes, which generate input-output pairs theta mathcalG(theta) in high density from the prior initial guess to the found optimal parameter theta^*. These input-output pairs are then used as the data to train an emulator of the forward model mathcalG.","category":"page"},{"location":"calibrate/#Ensemble-Kalman-Processes","page":"Calibrate","title":"Ensemble Kalman Processes","text":"","category":"section"},{"location":"calibrate/","page":"Calibrate","title":"Calibrate","text":"Calibration can be performed using different ensemble Kalman processes: ensemble Kalman inversion (Iglesias et al, 2013), ensemble Kalman sampler (Garbuno-Inigo et al, 2020), and unscented Kalman inversion (Huang et al, 2022). All algorithms are implemented in EnsembleKalmanProcesses.jl. Documentation of each algorithm is available in the EnsembleKalmanProcesses docs.","category":"page"},{"location":"calibrate/#Typical-construction-of-the-EnsembleKalmanProcess","page":"Calibrate","title":"Typical construction of the EnsembleKalmanProcess","text":"","category":"section"},{"location":"calibrate/","page":"Calibrate","title":"Calibrate","text":"Documentation on how to construct an EnsembleKalmanProcess from the computer model and the data can be found in the EnsembleKalmanProcesses docs.","category":"page"},{"location":"calibrate/#Julia-free-forward-model","page":"Calibrate","title":"Julia-free forward model","text":"","category":"section"},{"location":"calibrate/","page":"Calibrate","title":"Calibrate","text":"One draw of our approach is that it does not require the forward map to be written in Julia. To aid construction of such a workflow, EnsembleKalmanProcesses.jl provides a documented example of a BASH workflow for the sinusoid problem, with source code here. The forward map interacts with the calibration tools (EKP) only though TOML file reading an writing, and thus can be written in any language; for example, to be used with slurm HPC scripts, with source code here.","category":"page"},{"location":"examples/Cloudy_example/#Cloudy-example","page":"Cloudy example","title":"Learning the initial parameters of a droplet mass distribution in Cloudy","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"info: How do I run this code?\nThe full code is found in the examples/ directory of the github repository","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"This example is based on Cloudy, a microphysics model that simulates how cloud droplets collide and coalesce into larger drops. Collision-coalescence is a crucial process for the formation of rain. ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"Cloudy is initialized with a mass distribution of the cloud droplets; this distribution is then stepped forward in time, with more and more droplets colliding and combining into bigger drops according to the droplet-droplet interactions specified by a collision-coalescence kernel. The evolution of the droplet distribution is completely determined by the shape of the initial distribution and the form of the kernel.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We will show how Calibrate-Emulate-Sample (CES) can be used to learn the parameters of the initial cloud droplet mass distribution from observations of the moments of that mass distribution at a later time. ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"Cloudy is used here in a \"perfect model\" (aka \"known truth\") setting, which means that the \"observations\" are generated by Cloudy itself, by running it with the true parameter values–-in more realistic applications, one would use actual measurements of cloud properties.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The following schematic gives an overview of the example:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"(Image: cloudy_schematic)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The input to the CES algorithm consists of data y, the observational covariance Γ, and prior parameter distributions. The data, a vector of moments of the droplet mass distribution, are obtained by running Cloudy with the parameters set to their true values. The covariance is obtained from model output. The calibration stage is performed by an ensemble Kalman inversion (EKI), in which Cloudy has to be run once per iteration and for each ensemble member. The resulting input-output pairs theta_i mathcalG(theta_i)_i are used to train an emulator model. This emulator widetildemathcalG(theta) is cheap to evaluate; it replaces the original parameter-to-data map in the Markov chain Monte Carlo (MCMC) sampling, which produces (approximate) samples of the posterior parameter distribution. These samples are the final output of the CES algorithm. ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"This paper describes Cloudy in much more detail and shows results of experiments using CES to learn model parameters.","category":"page"},{"location":"examples/Cloudy_example/#Running-the-example","page":"Cloudy example","title":"Running the example","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"Cloudy_calibrate.jl performs the calibration using ensemble Kalman inversion; Cloudy_emulate_sample.jl fits an emulator and uses it to sample the posterior distributions of the parameters. Once Cloudy is installed, the example can be run from the julia REPL:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"include(\"Cloudy_calibrate.jl\")\ninclude(\"Cloudy_emulate_sample.jl\")","category":"page"},{"location":"examples/Cloudy_example/#Walkthrough-of-the-code:-Cloudy_calibrate.jl","page":"Cloudy example","title":"Walkthrough of the code: Cloudy_calibrate.jl","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"This file performs the calibration stage of CES.","category":"page"},{"location":"examples/Cloudy_example/#Import-packagages-and-modules","page":"Cloudy example","title":"Import packagages and modules","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"First we load standard packages,","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"using Distributions\nusing StatsBase\nusing LinearAlgebra\nusing StatsPlots\nusing Plots\nusing Plots.PlotMeasures\nusing Random\nusing JLD2","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"the Cloudy modules,","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"using Cloudy\nusing Cloudy.ParticleDistributions\nusing Cloudy.KernelTensors\n\n# Import the module that runs Cloudy\ninclude(joinpath(@__DIR__, \"DynamicalModel.jl\"))","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"and finally the EKP packages.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"using EnsembleKalmanProcesses\nusing EnsembleKalmanProcesses.Observations\nusing EnsembleKalmanProcesses.ParameterDistributions\nusing EnsembleKalmanProcesses.DataContainers\nusing EnsembleKalmanProcesses.PlotRecipes","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The module DynamicalModel.jl is the forward solver; it provides a function that runs Cloudy with a given instance of the parameter vector we want to learn.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"include(\"DynamicalModel.jl\")","category":"page"},{"location":"examples/Cloudy_example/#Define-the-true-parameters","page":"Cloudy example","title":"Define the true parameters","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We define the true parameters–-they are known here because this is a known truth example. Knowing the true parameters will allow us to assess how well Calibrate-Emulate-Sample has managed to solve the inverse problem.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We will assume that the true particle mass distribution is a Gamma distribution, which at time t = 0 has parameters phi_0 = N_0 0 k_0 theta_0. We will then try to learn these parameters from observations y = M_0(t_end) M_1(t_end) M_2(t_end) of the zeroth-, first-, and second-order moments of the distribution at time t_end 0 (where t_end = 1.0 in this example). The true parameters phi_0 texttrue are defined as follows:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"param_names = [\"N0\", \"θ\", \"k\"]\nn_params = length(param_names)\nN0_true = 300.0 # number of particles (scaling factor for Gamma distribution)\nθ_true = 1.5597 # scale parameter of Gamma distribution\nk_true = 0.0817 # shape parameter of Gamma distribution\nϕ_true = [N0_true, θ_true, k_true] # true parameters in constrained space\ndist_true = ParticleDistributions.GammaPrimitiveParticleDistribution(ϕ_true...)","category":"page"},{"location":"examples/Cloudy_example/#Define-priors-for-the-parameters","page":"Cloudy example","title":"Define priors for the parameters","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"As we are working with Bayesian methods, we treat the parameters we want to learn as random variables whose prior distributions we specify here. The prior distributions will behave like an \"initial guess\" for the likely region of parameter space where we expect the solution to be located. We use constrained_gaussian to add the desired scale and bounds to the prior distribution, in particular we place lower bounds to preserve positivity (and numerical stability). ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"# We choose to use normal distributions to represent the prior distributions of\n# the parameters in the transformed (unconstrained) space.\nprior_N0 = constrained_gaussian(param_names[1], 400, 300, 0.4 * N0_true, Inf)\nprior_θ = constrained_gaussian(param_names[2], 1.0, 5.0, 1e-1, Inf)\nprior_k = constrained_gaussian(param_names[3], 0.2, 1.0, 1e-4, Inf)\npriors = combine_distributions([prior_N0, prior_θ, prior_k])","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The plot recipe for ParameterDistribution types allows for quick visualization of the priors:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"# Plot the priors\np = plot(priors, constrained=false)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"(Image: priors)","category":"page"},{"location":"examples/Cloudy_example/#Generate-(synthetic)-observations","page":"Cloudy example","title":"Generate (synthetic) observations","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We generate synthetic observations by running Cloudy 100 times with the true parameters (i.e., with the true initial Gamma distribution of droplet masses) and then adding noise to simulate measurement error.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"dyn_model_settings_true = DynamicalModel.ModelSettings(\n kernel, dist_true, moments, tspan)\n\nG_t = DynamicalModel.run_dyn_model(ϕ_true, dyn_model_settings_true)\nn_samples = 100\ny_t = zeros(length(G_t), n_samples)\n# In a perfect model setting, the \"observational noise\" represents the \n# internal model variability. Since Cloudy is a purely deterministic model, \n# there is no straightforward way of coming up with a covariance structure \n# for this internal model variability. We decide to use a diagonal \n# covariance, with entries (variances) largely proportional to their \n# corresponding data values, G_t\nΓy = convert(Array, Diagonal([100.0, 5.0, 30.0]))\nμ = zeros(length(G_t))\n\n# Add noise\nfor i in 1:n_samples\n y_t[:, i] = G_t .+ rand(MvNormal(μ, Γy))\nend\n\ntruth = Observations.Observation(y_t, Γy, data_names)\ntruth_sample = truth.mean ","category":"page"},{"location":"examples/Cloudy_example/#Perform-ensemble-Kalman-inversion","page":"Cloudy example","title":"Perform ensemble Kalman inversion","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We sample the initial ensemble from the prior and create the EnsembleKalmanProcess object as an ensemble Kalman inversion (EKI) algorithm using the Inversion() keyword. We also use the DataMisfitController() learning rate scheduler. The number of ensemble members must be larger than the dimension of the parameter space to ensure a full rank ensemble covariance.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"N_ens = 50 # number of ensemble members\nN_iter = 8 # number of EKI iterations\n# initial parameters: n_params x N_ens\ninitial_params = construct_initial_ensemble(rng, priors, N_ens)\nekiobj = EnsembleKalmanProcess(\n initial_params,\n truth_sample,\n truth.obs_noise_cov,\n Inversion(),\n scheduler=DataMisfitController()\n)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We perform the inversion loop. Remember that within calls to get_ϕ_final the EKP transformations are applied, thus the ensemble that is returned will be the gamma distribution parameters that can be used directly to run the forward model, rather than their corresponding values in the unconstrained space where the EKI takes place. Each ensemble member is stored as a column and therefore for uses such as plotting one needs to reshape to the desired dimension.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"# Initialize a ParticleDistribution with dummy parameters. The parameters \n# will then be set within `run_dyn_model`\ndummy = ones(n_params)\ndist_type = ParticleDistributions.GammaPrimitiveParticleDistribution(dummy...)\nmodel_settings = DynamicalModel.ModelSettings(kernel, dist_type, moments, tspan)\n# EKI iterations\nfor n in 1:N_iter\n # Return transformed parameters in physical/constrained space\n ϕ_n = get_ϕ_final(priors, ekiobj)\n # Evaluate forward map\n G_n = [DynamicalModel.run_dyn_model(ϕ_n[:, i], model_settings) for i in 1:N_ens]\n G_ens = hcat(G_n...) # reformat\n EnsembleKalmanProcesses.update_ensemble!(ekiobj, G_ens)\nend","category":"page"},{"location":"examples/Cloudy_example/#Visualize-and-store-the-results-of-the-calibration","page":"Cloudy example","title":"Visualize and store the results of the calibration","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The optimal parameter vector determined by the ensemble Kalman inversion is the ensemble mean of the particles after the last iteration, which is printed to standard output. An output directory is created, where a file cloudy_calibrate_results.jld2 is stored, which contains all parameters and model output from the ensemble Kalman iterations (both as DataContainers.DataContainer objects), the mean and one sample of the synthetic observations, as well as the true prameters and their priors. In addition, an animation is produced that shows the evolution of the ensemble of particles over subsequent iterations of the optimization, both in the computational (unconstrained) and physical (constrained) spaces.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"(Image: eki_iterations_animation)","category":"page"},{"location":"examples/Cloudy_example/#Walkthrough-of-the-code:-Cloudy_emulate_sample.jl","page":"Cloudy example","title":"Walkthrough of the code: Cloudy_emulate_sample.jl","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"This file performs the emulation and sampling stages of the CES algorithm.","category":"page"},{"location":"examples/Cloudy_example/#Import-packages-and-modules","page":"Cloudy example","title":"Import packages and modules","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"First, we import some standard packages","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"using Distributions\nusing StatsBase\nusing GaussianProcesses\nusing LinearAlgebra\nusing Random\nusing JLD2\nENV[\"GKSwstype\"] = \"100\"\nusing CairoMakie, PairPlots","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"as well as the relevant CES packages needed to construct the emulators and perform the Markov chain Monte Carlo (MCMC) sampling. We also need some functionality of EnsembleKalmanProcesses.jl.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"using CalibrateEmulateSample.Emulators\nusing CalibrateEmulateSample.MarkovChainMonteCarlo\nusing CalibrateEmulateSample.Utilities\nusing EnsembleKalmanProcesses\nusing EnsembleKalmanProcesses.ParameterDistributions\nusing EnsembleKalmanProcesses.DataContainers","category":"page"},{"location":"examples/Cloudy_example/#Load-the-calibration-results","page":"Cloudy example","title":"Load the calibration results","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We will train the emulator on the input-output pairs we obtained during the calibration. They are stored within the EnsembleKalmanProcess object (ekiobj), which is loaded here together with the other information that was saved in the calibration step.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"ekiobj = load(data_save_file)[\"eki\"]\npriors = load(data_save_file)[\"priors\"]\ntruth_sample_mean = load(data_save_file)[\"truth_sample_mean\"]\ntruth_sample = load(data_save_file)[\"truth_sample\"]\n# True parameters:\n# - ϕ: in constrained space\n# - θ: in unconstrained space\nϕ_true = load(data_save_file)[\"truth_input_constrained\"]\nθ_true = transform_constrained_to_unconstrained(priors, ϕ_true)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The user can choose one or more of the following three emulators: a Gaussian Process (GP) emulator with GaussianProcesses.jl interface (gp-gpjl), a scalar Random Feature (RF) interface (rf-scalar), and vector RF with a nonseparable, nondiagonal kernel structure in the output space (rf-nosvd-nonsep). See here for a complete overview of the available emulators. ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"cases = [\n \"rf-scalar\",\n \"gp-gpjl\", # Veeeery slow predictions\n \"rf-nosvd-nonsep\"\n]","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We first define some settings for the two emulators, e.g., the prediction type for the GP emulator, or the number of features and hyperparameter optimizer options for the RF emulator. The docs for GPs and RFs explain the different options in more detail and provide some useful heuristics for how to customize the settings depending on the problem at hand.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"# These settings are the same for all Gaussian Process cases\npred_type = YType() # we want to predict data\n\n# These settings are the same for all Random Feature cases\nn_features = 400 \nnugget = 1e-8\noptimizer_options = Dict(\n \"verbose\" => true,\n \"scheduler\" => DataMisfitController(terminate_at = 100.0),\n \"cov_sample_multiplier\" => 1.0,\n \"n_iteration\" => 20,\n)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"Emulation is performed through the construction of an Emulator object from the following components:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"a wrapper for the machine learning tool (mlt) to be used as emulator\nthe input-output pairs on which the emulator will be trained\noptional arguments specifying data processing and dimensionality reduction functionality ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"For gp-gpjl, this looks as follows:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"gppackage = GPJL()\n# Kernel is the sum of a squared exponential (SE), Matérn 5/2, and white noise\ngp_kernel = SE(1.0, 1.0) + Mat52Ard(zeros(3), 0.0) + Noise(log(2.0))\n\n# Wrapper for GP\nmlt = GaussianProcess(\n gppackage;\n kernel = gp_kernel,\n prediction_type = pred_type,\n noise_learn = false,\n)\n\ndecorrelate = true\nstandardize_outputs = true","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"And similarly for rf-scalar","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"kernel_rank = 3\nkernel_structure = SeparableKernel(\n LowRankFactor(kernel_rank, nugget),\n OneDimFactor()\n)\n\nmlt = ScalarRandomFeatureInterface(\n n_features,\n n_params,\n kernel_structure = kernel_structure,\n optimizer_options = optimizer_options,\n)\n\ndecorrelate = true\nstandardize_outputs = true","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"and for rf-nosvd-nonsep:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"kernel_rank = 4\nmlt = VectorRandomFeatureInterface(\n n_features,\n n_params,\n n_outputs,\n kernel_structure = NonseparableKernel(LowRankFactor(kernel_rank, nugget)),\n optimizer_options = optimizer_options\n)\n\n# Vector RF does not require decorrelation of outputs\ndecorrelate = false\nstandardize_outputs = false","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We construct the emulator using the input-output pairs obtained in the calibration stage (note that we're not using all available input-output pairs–-using all of them may not give the best results, especially if the EKI parameter converges rapidly and then \"stays in the same place\" during the remaining iterations). For the gp-gpjl and rf-scalar cases, we want the output data to be decorrelated with information from Γy, but for the vector RF case decorrelation is not required.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"input_output_pairs = get_training_points(ekiobj,\n length(get_u(ekiobj))-2)\n\n# Use the medians of the outputs as standardizing factors\nnorm_factors = get_standardizing_factors(\n get_outputs(input_output_pairs)\n)\n\n# The data processing normalizes input data, and decorrelates\n# output data with information from Γy, if required\n# Note: The `standardize_outputs_factors` are only used under the\n# condition that `standardize_outputs` is true.\nemulator = Emulator(\n mlt,\n input_output_pairs,\n decorrelate = decorrelate,\n obs_noise_cov = Γy,\n standardize_outputs = true,\n standardize_outputs_factors = vcat(norm_factors...),\n)","category":"page"},{"location":"examples/Cloudy_example/#Train-the-emulator","page":"Cloudy example","title":"Train the emulator","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The emulator is trained when we combine the machine learning tool and the data into the Emulator above. We must also optimize the hyperparameters:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"optimize_hyperparameters!(emulator)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"To test the predictive skill of the emulator, we can e.g. compare its prediction on the true parameters to the true data. (One could also hold out a subset of the input-output pairs from the training and evaluate the emulator's predictions on them).","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"# Check how well the emulator predicts on the true parameters\ny_mean, y_var = Emulators.predict(\n emulator,\n reshape(θ_true, :, 1);\n transform_to_real = true\n)\n\nprintln(\"Emulator ($(case)) prediction on true parameters: \")\nprintln(vec(y_mean))\nprintln(\"true data: \")\nprintln(truth_sample) # what was used as truth","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The emulator predicts both a mean value and a covariance.","category":"page"},{"location":"examples/Cloudy_example/#Sample-the-posterior-distributions-of-the-parameters","page":"Cloudy example","title":"Sample the posterior distributions of the parameters","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The last step is to plug the emulator into an MCMC algorithm, which is then used to produce samples from the posterior distribution of the parameters. Essentially, the emulator acts as a stand-in for the original forward model (which in most cases of interest is computationally expensive to run) during the MCMC sampling process.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We use the mean across all parameter ensembles from the EKI as the initial parameters for the MCMC. Before running the actual MCMC chain, we determine a good step size by running chains of length N = 2000:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"# initial values\nu0 = vec(mean(get_inputs(input_output_pairs), dims = 2))\nprintln(\"initial parameters: \", u0)\n\n# First let's run a short chain to determine a good step size\nyt_sample = truth_sample\nmcmc = MCMCWrapper(\n RWMHSampling(),\n truth_sample,\n priors,\n emulator;\n init_params = u0\n)\n\nnew_step = optimize_stepsize(\n mcmc;\n init_stepsize = 0.1,\n N = 2000,\n discard_initial = 0\n)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We choose a sample size of 100,000 for the actual MCMC, discarding the first 1,000 samples as burn-in:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"# Now begin the actual MCMC\nprintln(\"Begin MCMC - with step size \", new_step)\nchain = MarkovChainMonteCarlo.sample(\n mcmc,\n 100_000;\n stepsize = new_step,\n discard_initial = 1_000\n)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"After running the MCMC, we can extract the posterior samples as follows:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"posterior = MarkovChainMonteCarlo.get_posterior(mcmc, chain)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The samples of the posterior distributions represent the ultimate output of the CES process. By constructing histograms of these samples and comparing them with the known true parameter values, we can evaluate the results' accuracy. Ideally, the peak of the posterior distribution should be located near the true values, indicating a high-quality estimation. Additionally, visualizing the prior distributions alongside the posteriors shows the distributional change effected by the Bayesian learning process.","category":"page"},{"location":"examples/Cloudy_example/#Results","page":"Cloudy example","title":"Results","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We first produce pair plots (also known as corner plots or scatter plot matrices) to visualize the posterior parameter distributions as a grid of histograms. Recall that the task was to solve the inverse problem of finding the parameters N_0 0, k_0, and theta_0, which define a gamma distribution of droplet masses in Cloudy at time t = 0.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"# Make pair plots of the posterior distributions in the unconstrained\n# and in the constrained space (this uses `PairPlots.jl`)\nfigpath_unconstr = joinpath(output_directory,\n \"joint_posterior_unconstr.png\")\nfigpath_constr = joinpath(output_directory,\n \"joint_posterior_constr.png\")\nlabels = get_name(posterior)\n\ndata_unconstr = (; [(Symbol(labels[i]),\n posterior_samples_unconstr[i, :]) for i in 1:length(labels)]...)\ndata_constr = (; [(Symbol(labels[i]),\n posterior_samples_constr[i, :]) for i in 1:length(labels)]...)\n\np_unconstr = pairplot(data_unconstr => (PairPlots.Scatter(),))\np_constr = pairplot(data_constr => (PairPlots.Scatter(),))","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"For the GP emulator, the results (shown in the constrained/physical space) look as follows:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"(Image: pairplot_posterior_gpjl)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"And we can plot the same for the scalar RF emulator...","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"(Image: pairplot_posterior_rf-scalar)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"...and for the vector RF emulator:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"(Image: pairplot_posterior_rf-vec)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"In addition, we plot the marginals of the posterior distributions–-we are showing them here for the GP emulator case:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"for idx in 1:n_params\n\n # Find the range of the posterior samples\n xmin = minimum(posterior_samples_constr[idx, :])\n xmax = maximum(posterior_samples_constr[idx, :])\n\n # Create a figure and axis for plotting\n fig = Figure(; size = (800, 600))\n ax = Axis(fig[1, 1])\n\n # Histogram for posterior samples\n hist!(ax, posterior_samples_constr[idx, :], bins = 100,\n color = :darkorange, label = \"posterior\")\n\n # Plotting the prior distribution\n hist!(ax, prior_samples_constr[idx, :], bins = 10000,\n color = :slategray)\n\n # Adding a vertical line for the true value\n vlines!(ax, [ϕ_true[idx]], color = :indigo, linewidth = 2.6,\n label = \"true \" * param_names[idx])\n\n xlims!(ax, xmin, xmax)\n ylims!(ax, 0, Inf)\n\n # Setting title and labels\n ax.title = param_names[idx]\n ax.xlabel = \"Value\"\n ax.ylabel = \"Density\"","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"This is what the marginal distributions of the three parameters look like, for the case of the GP emulator, and in the constrained/physical space:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"(Image: posterior_N0_gpjl)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"(Image: posterior_theta_gpjl)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"(Image: posterior_k_gpjl)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"Here, the posterior distributions are shown as orange histograms, the prior distribution are shown as grey histograms (though with the exception of the parmaeter k, they are barely visible), and the true parameter values are marked as vertical purple lines.","category":"page"},{"location":"examples/Cloudy_example/#Appendix:-What-Does-Cloudy-Do?","page":"Cloudy example","title":"Appendix: What Does Cloudy Do?","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"For the purpose of Bayesian parameter learning, the forward model can be treated as a black box that processes input parameters to yield specific outputs. However, for those who wish to learn more about the inner workings of Cloudy, we refer to his paper and offer a brief outline below:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The mathematical starting point of Cloudy is the stochastic collection equation (SCE; sometimes also called Smoluchowski equation after Marian Smoluchowski), which describes the time rate of change of f = f(m t), the mass distribution function of liquid water droplets, due to the process of collision and coalescence. The distribution function f depends on droplet mass m and time t and is defined such that f(m) text dm denotes the number of droplets with masses in the interval m m + dm per unit volume. ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The stochastic collection equation is an integro-differential equation that can be written as ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":" fracpartial f(m t)partial t = frac12 int_m=0^infty f(m t) f(m-m t) mathcalC(m m-m)textdm - f(m t) int_m=0^infty f(m t)mathcalC(m m) textdm ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"where mathcalC(m m) is the collision-coalescence kernel, which encapsulates the physics of droplet-droplet interactions – it describes the rate at which two drops of masses m and m come into contact and coalesce into a drop of mass m + m. The first term on the right-hand side of the SCE describes the rate of increase of the number of drops having a mass m due to collision and coalescence of drops of masses m and m-m (where the factor frac12 avoids double counting), while the second term describes the rate of reduction of drops of mass m due to collision and coalescence of drops having a mass m with other drops. ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We can rewrite the SCE in terms of the moments M_k of f, which are the prognostic variables in Cloudy. They are defined by","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":" M_k = int_0^infty m^k f(m t) textdm","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The time rate of change of the k-th moment of f is obtained by multiplying the SCE by m^k and integrating over the entire range of droplet masses (from m=0 to infty), which yields","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":" fracpartial M_k(t)partial t = frac12int_0^infty left((m+m)^k - m^k - m^kright) mathcalC(m m)f(m t)f(m t) textdm textdm (1)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"In this example, the kernel is set to be constant – mathcalC(m m) = B = textconst – and the cloud droplet mass distribution is assumed to be a textGamma(k_t theta_t) distribution, scaled by a factor N_0t which denotes the droplet number concentration:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"f(m t) = fracN_0tGamma(k_t)theta_t^k m^k_t-1 exp(-mtheta_t)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The parameter vector phi_t= N_0t k_t theta_t changes over time (as indicated by the subscript t), as the shape of the distribution evolves. In fact, there is a priori no reason to assume that the distribution would retain its Gamma shape over time, but this is a common assumption that is made in order to solve the closure problem (without this assumption, one would have to keep track of infinitely many moments of the mass distribution in order to uniquely identify the distribution f at each time step, which is obviously not practicable).","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"For Gamma mass distribution functions, specifying the first three moments (M_0, M_1, and M_2) is sufficient to uniquely determine the parameter vector phi_t, hence Cloudy solves equation (1) for k = 0 1 2. This mapping of the parameters of the initial cloud droplet mass distribution to the (zeroth-, first-, and second-order) moments of the distribution at a specified end time is done by DynamicalModel.jl.","category":"page"},{"location":"API/Emulators/#Emulators","page":"General Interface","title":"Emulators","text":"","category":"section"},{"location":"API/Emulators/","page":"General Interface","title":"General Interface","text":"CurrentModule = CalibrateEmulateSample.Emulators","category":"page"},{"location":"API/Emulators/","page":"General Interface","title":"General Interface","text":"Emulator\noptimize_hyperparameters!(::Emulator)\npredict\nnormalize\nstandardize\nreverse_standardize\nsvd_transform\nsvd_reverse_transform_mean_cov","category":"page"},{"location":"API/Emulators/#CalibrateEmulateSample.Emulators.Emulator","page":"General Interface","title":"CalibrateEmulateSample.Emulators.Emulator","text":"struct Emulator{FT<:AbstractFloat}\n\nStructure used to represent a general emulator, independently of the algorithm used.\n\nFields\n\nmachine_learning_tool::CalibrateEmulateSample.Emulators.MachineLearningTool: Machine learning tool, defined as a struct of type MachineLearningTool.\ntraining_pairs::EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT} where FT<:AbstractFloat: Normalized, standardized, transformed pairs given the Booleans normalize_inputs, standardize_outputs, retained_svd_frac.\ninput_mean::AbstractVector{FT} where FT<:AbstractFloat: Mean of input; length input_dim.\nnormalize_inputs::Bool: If normalizing: whether to fit models on normalized inputs ((inputs - input_mean) * sqrt_inv_input_cov).\nnormalization::Union{Nothing, LinearAlgebra.UniformScaling{FT}, AbstractMatrix{FT}} where FT<:AbstractFloat: (Linear) normalization transformation; size input_dim × input_dim.\nstandardize_outputs::Bool: Whether to fit models on normalized outputs: outputs / standardize_outputs_factor.\nstandardize_outputs_factors::Union{Nothing, AbstractVector{FT}} where FT<:AbstractFloat: If standardizing: Standardization factors (characteristic values of the problem).\ndecomposition::Union{Nothing, LinearAlgebra.SVD}: The singular value decomposition of obs_noise_cov, such that obs_noise_cov = decomposition.U * Diagonal(decomposition.S) * decomposition.Vt. NB: the SVD may be reduced in dimensions.\nretained_svd_frac::AbstractFloat: Fraction of singular values kept in decomposition. A value of 1 implies full SVD spectrum information.\n\n\n\n\n\n","category":"type"},{"location":"API/Emulators/#CalibrateEmulateSample.Emulators.optimize_hyperparameters!-Tuple{CalibrateEmulateSample.Emulators.Emulator}","page":"General Interface","title":"CalibrateEmulateSample.Emulators.optimize_hyperparameters!","text":"optimize_hyperparameters!(\n emulator::CalibrateEmulateSample.Emulators.Emulator{FT<:AbstractFloat},\n args...;\n kwargs...\n) -> Any\n\n\nOptimizes the hyperparameters in the machine learning tool.\n\n\n\n\n\n","category":"method"},{"location":"API/Emulators/#GaussianProcesses.predict","page":"General Interface","title":"GaussianProcesses.predict","text":"predict(\n gp::CalibrateEmulateSample.Emulators.GaussianProcess{CalibrateEmulateSample.Emulators.GPJL},\n new_inputs::AbstractArray{FT<:AbstractFloat, 2}\n) -> Tuple{Any, Any}\n\n\nPredict means and covariances in decorrelated output space using Gaussian process models.\n\n\n\n\n\npredict(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface,\n new_inputs::AbstractMatrix;\n multithread\n) -> Tuple{Any, Any}\n\n\nPrediction of data observation (not latent function) at new inputs (passed in as columns in a matrix). That is, we add the observational noise into predictions.\n\n\n\n\n\npredict(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface,\n new_inputs::AbstractMatrix\n) -> Tuple{Any, Any}\n\n\nPrediction of data observation (not latent function) at new inputs (passed in as columns in a matrix). That is, we add the observational noise into predictions.\n\n\n\n\n\npredict(\n emulator::CalibrateEmulateSample.Emulators.Emulator{FT<:AbstractFloat},\n new_inputs::AbstractArray{FT<:AbstractFloat, 2};\n transform_to_real,\n vector_rf_unstandardize,\n mlt_kwargs...\n) -> Tuple{Any, Any}\n\n\nMakes a prediction using the emulator on new inputs (each new inputs given as data columns). Default is to predict in the decorrelated space.\n\n\n\n\n\n","category":"function"},{"location":"API/Emulators/#CalibrateEmulateSample.Emulators.normalize","page":"General Interface","title":"CalibrateEmulateSample.Emulators.normalize","text":"normalize(\n emulator::CalibrateEmulateSample.Emulators.Emulator,\n inputs::AbstractVecOrMat\n) -> Any\n\n\nNormalize the input data, with a normalizing function.\n\n\n\n\n\n","category":"function"},{"location":"API/Emulators/#CalibrateEmulateSample.Emulators.standardize","page":"General Interface","title":"CalibrateEmulateSample.Emulators.standardize","text":"standardize(\n outputs::AbstractVecOrMat,\n output_covs::Union{AbstractVector{<:AbstractMatrix}, AbstractVector{<:LinearAlgebra.UniformScaling}},\n factors::AbstractVector\n) -> Tuple{Any, Union{AbstractVector{<:AbstractMatrix}, AbstractVector{<:LinearAlgebra.UniformScaling}}}\n\n\nStandardize with a vector of factors (size equal to output dimension).\n\n\n\n\n\n","category":"function"},{"location":"API/Emulators/#CalibrateEmulateSample.Emulators.reverse_standardize","page":"General Interface","title":"CalibrateEmulateSample.Emulators.reverse_standardize","text":"reverse_standardize(\n emulator::CalibrateEmulateSample.Emulators.Emulator{FT<:AbstractFloat},\n outputs::AbstractVecOrMat,\n output_covs::AbstractVecOrMat\n) -> Tuple{Any, Any}\n\n\nReverse a previous standardization with the stored vector of factors (size equal to output dimension). output_cov is a Vector of covariance matrices, such as is returned by svd_reverse_transform_mean_cov.\n\n\n\n\n\n","category":"function"},{"location":"API/Emulators/#CalibrateEmulateSample.Emulators.svd_transform","page":"General Interface","title":"CalibrateEmulateSample.Emulators.svd_transform","text":"svd_transform(\n data::AbstractArray{FT<:AbstractFloat, 2},\n obs_noise_cov::Union{Nothing, AbstractArray{FT<:AbstractFloat, 2}};\n retained_svd_frac\n) -> Tuple{Any, Any}\n\n\nApply a singular value decomposition (SVD) to the data\n\ndata - GP training data/targets; size output_dim × N_samples\nobs_noise_cov - covariance of observational noise\ntruncate_svd - Project onto this fraction of the largest principal components. Defaults to 1.0 (no truncation).\n\nReturns the transformed data and the decomposition, which is a matrix factorization of type LinearAlgebra.SVD. \n\nNote: If F::SVD is the factorization object, U, S, V and Vt can be obtained via F.U, F.S, F.V and F.Vt, such that A = U * Diagonal(S) * Vt. The singular values in S are sorted in descending order.\n\n\n\n\n\n","category":"function"},{"location":"API/Emulators/#CalibrateEmulateSample.Emulators.svd_reverse_transform_mean_cov","page":"General Interface","title":"CalibrateEmulateSample.Emulators.svd_reverse_transform_mean_cov","text":"svd_reverse_transform_mean_cov(\n μ::AbstractArray{FT<:AbstractFloat, 2},\n σ2::AbstractVector,\n decomposition::LinearAlgebra.SVD\n) -> Tuple{Any, Any}\n\n\nTransform the mean and covariance back to the original (correlated) coordinate system\n\nμ - predicted mean; size output_dim × N_predicted_points.\nσ2 - predicted variance; size output_dim × N_predicted_points. - predicted covariance; size N_predicted_points array of size output_dim × output_dim.\ndecomposition - SVD decomposition of obs_noise_cov.\n\nReturns the transformed mean (size output_dim × N_predicted_points) and variance. Note that transforming the variance back to the original coordinate system results in non-zero off-diagonal elements, so instead of just returning the elements on the main diagonal (i.e., the variances), we return the full covariance at each point, as a vector of length N_predicted_points, where each element is a matrix of size output_dim × output_dim.\n\n\n\n\n\n","category":"function"},{"location":"emulate/#The-Emulate-stage","page":"Emulator","title":"The Emulate stage","text":"","category":"section"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"Emulation is performed through the construction of an Emulator object, which has two components","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"A wrapper for any statistical emulator,\nData-processing and dimensionality reduction functionality.","category":"page"},{"location":"emulate/#Typical-construction-from-Lorenz_example.jl","page":"Emulator","title":"Typical construction from Lorenz_example.jl","text":"","category":"section"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"First, obtain data in a PairedDataContainer, for example, get this from an EnsembleKalmanProcess ekpobj generated during the Calibrate stage, or see the constructor here","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"using CalibrateEmulateSample.Utilities\ninput_output_pairs = Utilities.get_training_points(ekpobj, 5) # use first 5 iterations as data","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"Wrapping a predefined machine learning tool, e.g. a Gaussian process gauss_proc, the Emulator can then be built:","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"emulator = Emulator(\n gauss_proc, \n input_output_pairs; # optional arguments after this\n obs_noise_cov = Γy,\n normalize_inputs = true,\n standardize_outputs = true,\n standardize_outputs_factors = factor_vector,\n retained_svd_frac = 0.95,\n)","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"The optional arguments above relate to the data processing.","category":"page"},{"location":"emulate/#Emulator-Training","page":"Emulator","title":"Emulator Training","text":"","category":"section"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"The emulator is trained when we combine the machine learning tool and the data into the Emulator above. For any machine learning tool, hyperparameters are optimized.","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"optimize_hyperparameters!(emulator)","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"For some machine learning packages however, this may be completed during construction automatically, and for others this will not. If automatic construction took place, the optimize_hyperparameters! line does not perform any new task, so may be safely called. In the Lorenz example, this line learns the hyperparameters of the Gaussian process, which depend on the choice of kernel, and the choice of GP package. Predictions at new inputs can then be made using","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"y, cov = Emulator.predict(emulator, new_inputs)","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"This returns both a mean value and a covariance.","category":"page"},{"location":"emulate/#Data-processing","page":"Emulator","title":"Data processing","text":"","category":"section"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"Some effects of the following are outlined in a practical setting in the results and appendices of Howland, Dunbar, Schneider, (2022).","category":"page"},{"location":"emulate/#Diagonalization-and-output-dimension-reduction","page":"Emulator","title":"Diagonalization and output dimension reduction","text":"","category":"section"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"This arises from the optional arguments","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"obs_noise_cov = Γy (default: nothing)","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"We always use singular value decomposition to diagonalize the output space, requiring output covariance Γy. Why? If we need to train a mathbbR^10 to mathbbR^100 emulator, diagonalization allows us to instead train 100 mathbbR^10 to mathbbR^1 emulators (far cheaper).","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"retained_svd_frac = 0.95 (default 1.0)","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"Performance is increased further by throwing away less informative output dimensions, if 95% of the information (i.e., variance) is in the first 40 diagonalized output dimensions then setting retained_svd_frac=0.95 will train only 40 emulators.","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"note: Note\nDiagonalization is an approximation. It is however a good approximation when the observational covariance varies slowly in the parameter space.","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"warn: Warn\nSevere approximation errors can occur if obs_noise_cov is not provided.","category":"page"},{"location":"emulate/#Normalization-and-standardization","page":"Emulator","title":"Normalization and standardization","text":"","category":"section"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"This arises from the optional arguments","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"normalize_inputs = true (default: true)","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"We normalize the input data in a standard way by centering, and scaling with the empirical covariance","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"standardize_outputs = true (default: false)\nstandardize_outputs_factors = factor_vector (default: nothing)","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"To help with poor conditioning of the covariance matrix, users can also standardize each output dimension with by a multiplicative factor given by the elements of factor_vector.","category":"page"},{"location":"emulate/#modular-interface","page":"Emulator","title":"Modular interface","text":"","category":"section"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"Developers may contribute new tools by performing the following","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"Create MyMLToolName.jl, and include \"MyMLToolName.jl\" in Emulators.jl\nCreate a struct MyMLTool <: MachineLearningTool, containing any arguments or optimizer options \nCreate the following three methods to build, train, and predict with your tool (use GaussianProcess.jl as a guide)","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"build_models!(mlt::MyMLTool, iopairs::PairedDataContainer) -> Nothing\noptimize_hyperparameters!(mlt::MyMLTool, args...; kwargs...) -> Nothing\nfunction predict(mlt::MyMLTool, new_inputs::Matrix; kwargs...) -> Matrix, Union{Matrix, Array{,3}","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"note: on dimensions of the predict inputs and outputs\nThe predict method takes as input, an input_dim-by-N_new matrix. It return both a predicted mean and a predicted (co)variance at new inputs. (i) for scalar-output methods relying on diagonalization, return output_dim-by-N_new matrices for mean and variance, (ii) For vector-output methods, return output_dim-by-N_new for mean and output_dim-by-output_dim-by-N_new for covariances.","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"Please get in touch with our development team when contributing new statistical emulators, to help us ensure the smoothest interface with any new tools.","category":"page"},{"location":"#CalibrateEmulateSample.jl","page":"Home","title":"CalibrateEmulateSample.jl","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"CalibrateEmulateSample.jl solves parameter estimation problems using accelerated (and approximate) Bayesian inversion.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The framework can be applied currently to learn:","category":"page"},{"location":"","page":"Home","title":"Home","text":"the joint distribution for a moderate numbers of parameters (<40),\nit is not inherently restricted to unimodal distributions.","category":"page"},{"location":"","page":"Home","title":"Home","text":"It can be used with computer models that:","category":"page"},{"location":"","page":"Home","title":"Home","text":"can be noisy or chaotic,\nare non-differentiable,\ncan only be treated as black-box (interfaced only with parameter files).","category":"page"},{"location":"","page":"Home","title":"Home","text":"The computer model is supplied by the user, as a parameter-to-data map mathcalG(theta) mathbbR^p rightarrow mathbbR^d. For example, mathcalG could be a map from any given parameter configuration theta to a collection of statistics of a dynamical system trajectory. mathcalG is referred to as the forward model in the Bayesian inverse problem setting.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The data produced by the forward model are compared to observations y, which are assumed to be corrupted by additive noise eta, such that","category":"page"},{"location":"","page":"Home","title":"Home","text":"y = mathcalG(theta) + eta","category":"page"},{"location":"","page":"Home","title":"Home","text":"where the noise eta is drawn from a d-dimensional Gaussian with distribution mathcalN(0 Gamma_y).","category":"page"},{"location":"#The-inverse-problem","page":"Home","title":"The inverse problem","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Given an observation y, the computer model mathcalG, the observational noise Gamma_y, and some broad prior information on theta, we return the joint distribution of a data-informed distribution for \"theta given y\".","category":"page"},{"location":"","page":"Home","title":"Home","text":"As the name suggests, CalibrateEmulateSample.jl breaks this problem into a sequence of three steps: calibration, emulation, and sampling. A comprehensive treatment of the calibrate-emulate-sample approach to Bayesian inverse problems can be found in Cleary et al. (2020).","category":"page"},{"location":"#The-three-steps-of-the-algorithm:-see-our-walkthrough-of-the-[Sinusoid-Example](@ref)","page":"Home","title":"The three steps of the algorithm: see our walkthrough of the Sinusoid Example","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Learn the vertical shift and amplitude of the signal given the noisy observation","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"","page":"Home","title":"Home","text":"The calibrate step of the algorithm consists of an application of Ensemble Kalman Processes, which generates input-output pairs theta mathcalG(theta) in high density around an optimal parameter theta^*. Here, theta are amplitude and vertical shift pairs, and mathcalG(theta) are the resulting signal mean and range. This theta^* will be near a mode of the posterior distribution (Note: This is the only time we interface with the forward model mathcalG).","category":"page"},{"location":"","page":"Home","title":"Home","text":"calibrate with EKP to generate data pairs...","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"","page":"Home","title":"Home","text":"The emulate step takes these pairs theta mathcalG(theta) and trains a statistical surrogate model (e.g., a Gaussian process), emulating the forward map mathcalG.","category":"page"},{"location":"","page":"Home","title":"Home","text":"emulate the map statistically from EKP pairs... ","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"","page":"Home","title":"Home","text":"The sample step uses this surrogate in place of mathcalG in a sampling method (Markov chain Monte Carlo) to sample the posterior distribution of theta.","category":"page"},{"location":"","page":"Home","title":"Home","text":"sample the emulated map with MCMC...","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"#Code-Components","page":"Home","title":"Code Components","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"CalibrateEmulateSample.jl contains the following modules:","category":"page"},{"location":"","page":"Home","title":"Home","text":"Module Purpose\nCalibrateEmulateSample.jl A wrapper for the pipeline\nEmulator.jl Modular template for the emulators\nGaussianProcess.jl A Gaussian process emulator\nScalar/VectorRandomFeatureInterface.jl A Scalar/Vector-output Random Feature emulator\nMarkovChainMonteCarlo.jl Modular template for Markov Chain Monte Carlo samplers\nUtilities.jl Helper functions","category":"page"},{"location":"#Authors","page":"Home","title":"Authors","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"CalibrateEmulateSample.jl is being developed by the Climate Modeling Alliance.","category":"page"},{"location":"examples/edmf_example/#Extended-Eddy-Diffusivity-Mass-Flux-(EDMF)-Scheme","page":"Turbulence example","title":"Extended Eddy-Diffusivity Mass-Flux (EDMF) Scheme","text":"","category":"section"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"info: How do I run this code?\nThe full code is found in the examples/ directory of the github repository","category":"page"},{"location":"examples/edmf_example/#Background","page":"Turbulence example","title":"Background","text":"","category":"section"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"The extended EDMF scheme is a unified model of turbulence and convection. More information about the model can be found here. This example builds an emulator of the extended EDMF scheme from input-output pairs obtained during a calibration process, and runs emulator-based MCMC to obtain an estimate of the joint parameter distribution.","category":"page"},{"location":"examples/edmf_example/#What-is-being-solved-here","page":"Turbulence example","title":"What is being solved here","text":"","category":"section"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"This example reads calibration data containing input-output pairs obtained during calibration of the EDMF scheme. The calibration is performed using ensemble Kalman inversion, an ensemble-based algorithm that updates the location of the input parameters from the prior to the posterior, thus ensuring an optimal placement of the data used to train the emulator. In this example, the input is formed by either two or five EDMF parameters, and the output is the time-averaged liquid water path (LWP) at 40 locations in the eastern Pacific Ocean. The calibration data also contains the prior distribution of EDMF parameters and the variance of the observed variables (LWP in this case), which is used as a proxy for the magnitude of observational noise.","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"More information about EDMF calibration can be found here. The calibration data is used to train the emulator.","category":"page"},{"location":"examples/edmf_example/#Running-the-examples","page":"Turbulence example","title":"Running the examples","text":"","category":"section"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"We have two example scenario data (output from a (C)alibration run) that must be simply unzipped before calibration:","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"ent-det-calibration.zip # two-parameter calibration\nent-det-tked-tkee-stab-calibration.zip # five-parameter calibration","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"To perform uncertainty quantification use the file uq_for_EDMF.jl. Set the experiment name, and date (for outputs), e.g.","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"exp_name = \"ent-det-tked-tkee-stab-calibration\" \ndate_of_run = Date(year, month, day)","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"and call,","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"> julia --project uq_for_EDMF.jl","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"info: Info\nThese runs take currently take ~1-3 hours to complete with Gaussian process emulator. Random feature training currently requires significant multithreading for performance and takes a similar amount of time.","category":"page"},{"location":"examples/edmf_example/#Solution-and-output","page":"Turbulence example","title":"Solution and output","text":"","category":"section"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"The solution is the posterior distribution, stored in the file posterior.jld2.","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"The posterior is visualized by using plot_posterior.jl, which produces corner-type scatter plots of posterior distribution, which show pairwise correlations. Again, set the exp_name and date_of_run values, then call","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"julia --project plot_posterior.jl","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"For example, using Random features for case exp_name = \"ent-det-calibration\" one obtains","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"and exp_name = \"ent-det-tked-tkee-stab-calibration\" or one obtains","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"The posterior samples can also be investigated directly. They are stored as a ParameterDistribution-type Samples object. One can load this and extract an array of parameters with:","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"# input:\n# path to posterior.jld2: posterior_filepath (string)\n\nusing CalibrateEmulateSample.ParameterDistribution\nposterior = load(posterior_filepath)[\"posterior\"]\nposterior_samples = vcat([get_distribution(posterior)[name] for name in get_name(posterior)]...) # samples are columns","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"To transform these samples into physical parameter space use the following:","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"transformed_posterior_samples =\nmapslices(x -> transform_unconstrained_to_constrained(posterior, x), posterior_samples, dims = 1)","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"info: Computational vs Physical space\nThe computational theta-space are the parameters on which the algorithms act. Statistics (e.g. mean/covariance) are most meaningful when taken in this space. The physical phi-space is a (nonlinear) transformation of the computational space to apply parameter constraints. To pass parameter values back into the forward model, one must transform them. Full details and examples can be found here","category":"page"}] +[{"location":"examples/emulators/ishigami_3d_1d/#Global-Sensitiviy-Analysis-for-an-emulated-Ishigami-function","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"","category":"section"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"info: How do I run this code?\nThe full code is found in the examples/Emulator/ directory of the github repository","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"In this example, we assess directly the performance of our machine learning emulators. The task is to learn a function for use in a global sensitivity analysis. In particular, we learn the Ishigami function","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"f(x a b) = (1 + bx_3^4)sin(x_1) + a sin(x_2) forall xin -pipi^3","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"with a=7 b=01. In this example, global sensitivity analysis refers to calculation of two Sobol indices. The first index collects proportions V_i (a.k.a firstorder) of the variance of f attributable to the input x_i, and the second index collects proportions TV_i (a.k.a totalorder) of the residual variance having removed contributions attributable to inputs x_j forall jneq i. The Ishigami function has an analytic formula for these Sobol indices, it is also known that one can obtain numerical approximation through quasi-Monto-Carlo methods by evaluating the Ishigami function on a special quasi-random Sobol sequence.","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"To emulate the Ishigami function, the data consists of 300 pairs xf(x)+eta where eta sim N(0Sigma) is additive noise, and the x are sampled from the Sobol sequence. The emulators are validated by evaluating the posterior mean function on the full 16000 points of the Sobol sequence and the Sobol indices are estimated. We rerun the experiment for many repeats of the random feature hyperparameter optimization and present the statistics of these indices, as well as plotting a realization of the emulator.","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"We use the package GlobalSensitivityAnalysis.jl for many of the GSA tools.","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/#Walkthrough-of-the-code","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Walkthrough of the code","text":"","category":"section"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"We first load some standard packages","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"using Distributions\nusing DataStructures # for `OrderedDict`\nusing Random\nusing LinearAlgebra\nusing CairoMakie, ColorSchemes ","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"and the packages for providing the Ishigami function, Sobol sequence, and evaluation of the indices","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"using GlobalSensitivityAnalysis # for `SobolData`\nconst GSA = GlobalSensitivityAnalysis","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"then the CES packages for the emulators","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"using CalibrateEmulateSample.Emulators # for `SKLJL`, `GaussianProcess`, `SeparableKernel`, `LowRankFactor`, `OneDimFactor`, `ScalarRandomFeatureInterface`, `Emulator`\nusing CalibrateEmulateSample.DataContainers # for `PairedDataContainer`\nusing CalibrateEmulateSample.EnsembleKalmanProcesses # for `DataMisfitController`","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"We set up the sampling procedure, evaluate the true ishigami function on these points, and calculate the sobol indices","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"n_data_gen = 2000 \n\ndata = SobolData(\n params = OrderedDict(:x1 => Uniform(-π, π), :x2 => Uniform(-π, π), :x3 => Uniform(-π, π)),\n N = n_data_gen,\n)\n\n# To perform global analysis,\n# one must generate samples using Sobol sequence (i.e. creates more than N points)\nsamples = GSA.sample(data)\nn_data = size(samples, 1) # [n_samples x 3]\n# run model (example)\ny = GSA.ishigami(samples)\n# perform Sobol Analysis\nresult = analyze(data, y)","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"Next we create the noisy training data from the sequence samples","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"n_train_pts = 300\nind = shuffle!(rng, Vector(1:n_data))[1:n_train_pts]\n# now subsample the samples data\nn_tp = length(ind)\ninput = zeros(3, n_tp)\noutput = zeros(1, n_tp)\nΓ = 1e-2\nnoise = rand(rng, Normal(0, Γ), n_tp)\nfor i in 1:n_tp\n input[:, i] = samples[ind[i], :]\n output[i] = y[ind[i]] + noise[i]\nend\niopairs = PairedDataContainer(input, output)","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"We have a few cases for the user to investigate","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"cases = [\n \"Prior\", # Scalar random feature emulator with no hyperparameter learning\n \"GP\", # Trained Sci-kit learn Gaussian process emulator\n \"RF-scalar\", # Trained scalar random feature emulator\n]","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"Each case sets up a different machine learning configuration in the Emulator object.","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"For the random feature case, RF-scalar, we use a rank-3 kernel in the input space, and 500 features for prediction, though for efficiency we use only 200 when learning the hyperparameters. The relevant code snippets are","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"nugget = Float64(1e-12)\noverrides = Dict(\n \"scheduler\" => DataMisfitController(terminate_at = 1e4),\n \"n_features_opt\" => 200,\n)\n\nkernel_structure = SeparableKernel(LowRankFactor(3, nugget), OneDimFactor())\nn_features = 500\nmlt = ScalarRandomFeatureInterface(\n n_features,\n 3,\n rng = rng,\n kernel_structure = kernel_structure,\n optimizer_options = overrides,\n)","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"For the gaussian process case GP we use the sci-kit learn package, a default squared exponential kernel with lengthscale learnt in each input dimensions. We do not learn an additional white kernel for the noise.","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"gppackage = Emulators.SKLJL()\npred_type = Emulators.YType()\nmlt = GaussianProcess(\n gppackage;\n prediction_type = pred_type,\n noise_learn = false,\n)","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"We finish by building the emulator object","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"emulator = Emulator(mlt, iopairs; obs_noise_cov = Γ * I, decorrelate = decorrelate)\noptimize_hyperparameters!(emulator) # (only needed for some Emulator packages)","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/#Results-and-plots","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Results and plots","text":"","category":"section"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"We validate the emulator by evaluating it on the entire Sobol sequence, and calculating the Sobol indices (presenting mean and std if using multiple repeats.","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"# predict on all Sobol points with emulator (example) \ny_pred, y_var = predict(emulator, samples', transform_to_real = true)\n\n# obtain emulated Sobol indices\nresult_pred = analyze(data, y_pred')","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/#Gaussian-Process-Emulator-(sci-kit-learn-GP)","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Gaussian Process Emulator (sci-kit learn GP)","text":"","category":"section"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"Here is the plot for one emulation","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"and the outputted table of Sobol indices","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"True Sobol Indices\n******************\n firstorder: [0.31390519114781146, 0.44241114479004084, 0.0]\n totalorder: [0.5575888552099592, 0.44241114479004084, 0.24368366406214775]\n \nSampled truth Sobol Indices (# points 16000)\n***************************\n firstorder: [0.31261591941512257, 0.441887746224135, -0.005810964687365922]\n totalorder: [0.5623611180844434, 0.44201284296404386, 0.24465876318633062]\n \nSampled Emulated Sobol Indices (# obs 300, noise var 0.01)\n***************************************************************\n firstorder: [0.3094638183079643, 0.4518400892052567, -0.007351344957260407]\n totalorder: [0.5502469909342245, 0.4587734278791574, 0.23542404141319245]","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/#Random-feature-emulator-(Separable-Low-rank-kernel-RF-scalar)","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Random feature emulator (Separable Low-rank kernel RF-scalar)","text":"","category":"section"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"Here is the plot for one emulation","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"Table for 20 repeats of the algorithm","category":"page"},{"location":"examples/emulators/ishigami_3d_1d/","page":"Global Sensitiviy Analysis for an emulated Ishigami function","title":"Global Sensitiviy Analysis for an emulated Ishigami function","text":"True Sobol Indices\n******************\n firstorder: [0.31390519114781146, 0.44241114479004084, 0.0]\n totalorder: [0.5575888552099592, 0.44241114479004084, 0.24368366406214775]\n \nSampled truth Sobol Indices (# points 16000)\n***************************\n firstorder: [0.31261591941512257, 0.441887746224135, -0.005810964687365922]\n totalorder: [0.5623611180844434, 0.44201284296404386, 0.24465876318633062]\n \nSampled Emulated Sobol Indices (# obs 300, noise var 0.01)\n***************************************************************\n(mean) firstorder: [0.33605548545490044, 0.41116050093679196, -0.0012213648484969539]\n(std) firstorder: [0.05909336956162543, 0.11484966121124164, 0.012908533302492602]\n(mean) totalorder: [0.5670345355855254, 0.4716028261179354, 0.24108222433317]\n(std) totalorder: [0.10619345801872732, 0.1041023777237331, 0.07200225781785778]\n","category":"page"},{"location":"examples/sinusoid_example/#Sinusoid-Example","page":"Simple example walkthrough","title":"Sinusoid Example","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"info: How do I run this code?\nThe full code is found in the examples/ directory of the github repository","category":"page"},{"location":"examples/sinusoid_example/#Background","page":"Simple example walkthrough","title":"Background","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"This example demonstrates how to use CalibrateEmulateSample.jl for a simple model that generates noisy observables of a signal. The sinusoid signal is defined by two parameters: its shift along the vertical axis and its amplitude. We make noisy observations of the signal and we can calculate the mean of the signal, which is informative about its shift along the axis, and the range of the signal, which is informative about the amplitude. Although our sinusoid function is simple and quick to evaluate, we shall pretend it is non-differentiable and expensive to evaluate, as a case study for carrying out uncertainty quantification on more complex systems. Additionally, we will work in a \"perfect model\" setting for this example, meaning we will generate pseudo-observations for our model and pretend that these are noisy observations of our system.","category":"page"},{"location":"examples/sinusoid_example/#Model","page":"Simple example walkthrough","title":"Model","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We have a model of a sinusoidal signal that is a function of parameters theta=(Av), where A is the amplitude of the signal and v is vertical shift of the signal:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"f(A v) = A sin(phi + t) + v forall t in 02pi","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Here, phi is the random phase of each signal. The goal is to estimate not just the point estimates of the parameters theta=(Av), but entire probability distributions of them, given some noisy observations. We will use the range and mean of a signal as our observable: ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"G(theta) = big textrangebig(f(theta)big) textmeanbig(f(theta)big) big ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"This highlights the role of choosing a good observable, in particular our choice of G is independent of the random phase shift phi and is in fact deterministic. This allows us to write out an expression for the noisy observation, y_obs:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"y_obs = G(theta) + gamma qquad gamma sim mathcalN(0 Gamma)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"where Gamma is the observational covariance matrix. We will assume the noise to be independent for each observable, giving us a diagonal covariance matrix.","category":"page"},{"location":"examples/sinusoid_example/#Walkthrough-of-code","page":"Simple example walkthrough","title":"Walkthrough of code","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"You can find the full scripts to reproduce this tutorial in examples/Sinusoid/. The code is split into four sections:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Model set up in sinusoid_setup.jl\nCalibrate in calibrate.jl\nEmulate in emulate.jl\nSample in sample.jl","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"You do not need to explicitly run sinusoid_setup.jl as it is called from calibrate.jl. However, this file contains the functions for the model and for generating pseudo-observations. You will need to run steps 2-4 in order as each one relies on output saved from the previous steps.","category":"page"},{"location":"examples/sinusoid_example/#Set-up","page":"Simple example walkthrough","title":"Set up","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"First, we load the packages we need for setting up the model:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"using LinearAlgebra, Random\nusing Plots\nusing JLD2\nusing Statistics, Distributions\n","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We define a model that generates a sinusoid given parameters theta=(Av) (amplitude and vertical shift). We will estimate these parameters from data. The model adds a random phase shift upon evaluation.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"# Define x-axis\ndt = 0.01\ntrange = 0:dt:(2 * pi + dt)\n\nfunction model(amplitude, vert_shift)\n # Set phi, the random phase\n phi = 2 * pi * rand()\n return amplitude * sin.(trange .+ phi) .+ vert_shift\nend\n","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We will define a \"true\" amplitude and vertical shift to generate some pseudo-observations. Let theta=(30 70).","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"amplitude_true = 3.0\nvert_shift_true = 7.0\n# Our input parameters are 2d and our outputs are 2d\ntheta_true = [amplitude_true, vert_shift_true]\ndim_params = 2\n# Generate the \"true\" signal for these parameters\nsignal_true = model(amplitude_true, vert_shift_true)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We will observe properties of the signal that inform us about the amplitude and vertical position. These properties will be the range (the difference between the maximum and the minimum), which is informative about the amplitude of the sinusoid, and the mean, which is informative about the vertical shift. ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"y1_true = maximum(signal_true) - minimum(signal_true)\ny2_true = mean(signal_true)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"However, our observations are typically not noise-free, so we add some white noise to our observables. We call this y_obs. The user can choose the observational covariance matrix, Gamma. We will assume the noise is independent (a diagonal covariance matrix Gamma=02 * I). ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"dim_output = 2\nΓ = 0.2 * I\nwhite_noise = MvNormal(zeros(dim_output), Γ)\ny_obs = [y1_true, y2_true] .+ rand(white_noise)\nprintln(\"Observations:\", y_obs)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"This gives y_obs=(615 642). We can plot the true signal in black, the true observables in red and the noisy observables in blue. (Image: signal)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"It will be helpful for us to define a function G(theta), which returns these observables (the range and the mean) of the sinusoid given a parameter vector. ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"function G(theta)\n amplitude, vert_shift = theta\n sincurve = model(amplitude, vert_shift)\n return [maximum(sincurve) - minimum(sincurve), mean(sincurve)]\nend","category":"page"},{"location":"examples/sinusoid_example/#Calibrate","page":"Simple example walkthrough","title":"Calibrate","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We are interested in learning the posterior distribution of theta for the inverse problem y_obs=G(theta)+mathcalN(0Gamma). We first carry out calibration, which aims to solve the inverse problem for point estimates of the optimal values for theta. Specifically, we use an ensemble based calibration method, such as Ensemble Kalman Inversion, because it provides us with ensembles of G(theta) evaluations that are focused near to the optimal values for theta. These ensembles provide us with a suitable dataset for training an emulator to be used in sampling the posterior distribution. ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We are using the EnsembleKalmanProcesses.jl package for Ensemble Kalman Inversion (EKI). We start with user-defined prior distributions and sample an ensemble of parameters theta, which we use to evaluate G(theta). Then, we iteratively update the ensemble until our parameters theta are near to the optimal.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"First, we will load the packages we need from CES:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"# CES\nusing CalibrateEmulateSample\nconst EKP = CalibrateEmulateSample.EnsembleKalmanProcesses\nconst PD = EKP.ParameterDistributions","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We define prior distributions on the two parameters. For the amplitude, we define a prior with mean 2 and standard deviation 1. It is additionally constrained to be nonnegative. For the vertical shift we define a Gaussian prior with mean 0 and standard deviation 5.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"prior_u1 = PD.constrained_gaussian(\"amplitude\", 2, 1, 0, Inf)\nprior_u2 = PD.constrained_gaussian(\"vert_shift\", 0, 5, -Inf, Inf)\nprior = PD.combine_distributions([prior_u1, prior_u2])\n# Plot priors\np = plot(prior, fill = :lightgray)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: prior)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We now generate the initial ensemble and set up the EKI.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"N_ensemble = 10\nN_iterations = 5\n\ninitial_ensemble = EKP.construct_initial_ensemble(prior, N_ensemble)\n\nensemble_kalman_process = EKP.EnsembleKalmanProcess(initial_ensemble, y_obs, Γ, EKP.Inversion())","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We are now ready to carry out the inversion. At each iteration, we get the ensemble from the last iteration, apply G(theta) to each ensemble member, and apply the Kalman update to the ensemble.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"for i in 1:N_iterations\n params_i = EKP.get_ϕ_final(prior, ensemble_kalman_process)\n\n G_ens = hcat([G(params_i[:, i]) for i in 1:N_ensemble]...)\n\n EKP.update_ensemble!(ensemble_kalman_process, G_ens)\nend","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Finally, we get the ensemble after the last iteration. This provides our estimate of the parameters.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"final_ensemble = EKP.get_ϕ_final(prior, ensemble_kalman_process)\n\n# Check that the ensemble mean is close to the theta_true\nprintln(\"Ensemble mean: \", mean(final_ensemble, dims=2)) # [3.05, 6.37]\nprintln(\"True parameters: \", theta_true) # [3.0, 7.0]","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Parameter Truth EKI mean\nAmplitude 3.0 3.05\nVertical shift 7.0 6.37","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"The EKI ensemble mean at the final iteration is close to the true parameters, which is good. We can also see how the ensembles evolve at each iteration in the plot below.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: eki)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"The ensembles are initially spread out but move closer to the true parameter values with each iteration, indicating the EKI algorithm is converging towards the minimum. Taking the mean of the ensemble gives a point estimate of the optimal parameters. However, EKI does not give us an estimate of the uncertainty, as the ensemble collapses. To carry out uncertainty quantification, we can sample from the posterior distribution, which requires a \"cheap\" method to evaluate our model, i.e., an emulator. In the next step of CES, we will build an emulator using the dataset generated in EKI.","category":"page"},{"location":"examples/sinusoid_example/#Emulate","page":"Simple example walkthrough","title":"Emulate","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"In the previous calibrate step, we learned point estimates for the optimal parameters theta, but for uncertainty quantification, we want to learn posterior distributions on our parameters. We can sample from posterior distributions with Markov chain Monte Carlo (MCMC) methods, but these typically require many model evaluations. In many scientific problems, model evaluations are highly costly, making this infeasible. To get around this, we build an emulator of our model, which allows us to approximate the expensive model almost instantaneously. An emulator can also be helpful for noisy problems as they provide a smoother approximation, leading to better MCMC convergence properties. In this section, we show how the codebase can be used to build emulators of our sinusoid model.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We ran Ensemble Kalman Inversion with an ensemble size of 10 for 5 iterations. This generated a total of 50 input output pairs from our model. We will use these samples to train an emulator. The EKI samples make a suitable dataset for training an emulator because in the first iteration, the ensemble parameters are spread out according to the prior, meaning they cover the full support of the parameter space. This is important for building an emulator that can be evaluated anywhere in this space. In later iterations, the ensemble parameters are focused around the truth. This means the emulator that will be more accurate around this region.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"First, we load additional packages we need for this section:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"using CalibrateEmulateSample.Emulators\nconst CES = CalibrateEmulateSample","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We will build two types of emulator here for comparison: Gaussian processes and Random Features. First, set up the data in the correct format. CalibrateEmulateSample.jl uses a paired data container that matches the inputs (in the unconstrained space) to the outputs:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"input_output_pairs = CES.Utilities.get_training_points(ensemble_kalman_process, N_iterations)\nunconstrained_inputs = CES.Utilities.get_inputs(input_output_pairs)\ninputs = Emulators.transform_unconstrained_to_constrained(prior, unconstrained_inputs)\noutputs = CES.Utilities.get_outputs(input_output_pairs)","category":"page"},{"location":"examples/sinusoid_example/#Gaussian-process","page":"Simple example walkthrough","title":"Gaussian process","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We will set up a basic Gaussian process (GP) emulator using the ScikitLearn.jl package or GaussianProcesses.jl. See the Gaussian process page for more information and options, including choice of package and kernels.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"gppackage = Emulators.GPJL()\ngauss_proc = Emulators.GaussianProcess(gppackage, noise_learn = false)\n\n# Build emulator with data\nemulator_gp = Emulator(gauss_proc, input_output_pairs, normalize_inputs = true, obs_noise_cov = Γ)\noptimize_hyperparameters!(emulator_gp)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"For this simple example, we already know the observational noise Γ=0.2*I, so we set noise_learn = false. However, for more complicated problems we may want to learn the noise as an additional hyperparameter.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We will check performance of the GP by testing on unseen data in a moment, but first, we will build a random features emulator for comparison.","category":"page"},{"location":"examples/sinusoid_example/#Random-Features","page":"Simple example walkthrough","title":"Random Features","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"An alternative emulator can be created with random features (RF). Random features can approximate a Gaussian process with improved scaling properties, making them more suitable for higher dimensional problems. We use a Vector Random Features emulator here, chosen because we find it is a reasonable approximation to the Gaussian process emulator above. For new problems, you may need to play around with these parameter choices. More information can be found here.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"# We have two input dimensions and two output dimensions.\ninput_dim = 2\noutput_dim = 2\n# Select number of features\nn_features = 60\nnugget = 1e-9\nkernel_structure = NonseparableKernel(LowRankFactor(2, nugget))\noptimizer_options = Dict(\n \"n_ensemble\" => 50,\n \"cov_sample_multiplier\" => 10,\n \"scheduler\" => EKP.DataMisfitController(on_terminate = \"continue\"),\n \"n_iteration\" => 50,\n \"verbose\" => true,\n)\nrandom_features = VectorRandomFeatureInterface(\n n_features,\n input_dim,\n output_dim,\n kernel_structure = kernel_structure,\n optimizer_options = optimizer_options,\n)\nemulator_random_features =\n Emulator(random_features, input_output_pairs, normalize_inputs = true, obs_noise_cov = Γ, decorrelate = false)\noptimize_hyperparameters!(emulator_random_features)","category":"page"},{"location":"examples/sinusoid_example/#Emulator-Validation","page":"Simple example walkthrough","title":"Emulator Validation","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Now we will validate both GP and RF emulators and compare them against the ground truth, G(theta). Note this is only possible in our example because our true model, G(theta), is cheap to evaluate. In more complex systems, we would have limited data to validate emulator performance with. ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Here, we will compare emulator performance across a wide range of parameters, but we will pay close attention to performance near the final ensemble mean theta=(3 6). This is because we need high accuracy in this region in the next step, when we sample the posterior distribution.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"First, we check the ground truth model G(theta) over our parameter space. We can plot how the two outputs (range, mean), vary with the two input parameters (amplitude, vertical shift).","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: groundtruth)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"The first panel shows how the range varies with respect to the two parameters in the true forward map. The contours show the range is mostly dependent on the amplitude, with little variation with respect to the vertical shift. The second panel shows how the mean varies with the respect to the two parameters and is mostly dependent on the vertical shift. This result makes sense for our model setup.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Below, we recreate the same contour plot with the emulators. We will also overlay the training data points from the EKI, where the colors show the output from G(theta) evaluated at the training points. The emulator contours should agree with the training data.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"First, for the Gaussian process emulator:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: GP_emulator)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"This looks similar to the output from G(theta). Next, let's check the random features emulator:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: RF_emulator)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Both the GP and RF emulator give similar results to the ground truth G(theta), indicating they are correctly learning the relationships between the parameters and the outputs. We also see the contours agree with the colors of the training data points. ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We should also validate how accurate the emulators are by looking at the absolute difference between emulator predictions and the ground truth. ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"The Gaussian process absolute errors are plotted here:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: GP_errors)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"and the random features absolute errors are here:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: RF_errors)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Both these error maps look similar. Importantly, we want the emulator to show the low errors in the region around the true parameter values near theta=(3 6) (i.e, near where the EKI points converge, shown by the scatter points in the previous plot). This the region that we will be sampling in the next step. We see low errors near here for both outputs and for both emulators. Now we have validated these emulators, we will proceed the last step of CES: Sampling of the posterior distribution. ","category":"page"},{"location":"examples/sinusoid_example/#Sample","page":"Simple example walkthrough","title":"Sample","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Now that we have a cheap emulator for our model, we can carry out uncertainty quantification to learn the posterier distribution of the parameters, theta. We use Markov chain Monte Carlo (MCMC) to sample the posterior distribtion. In MCMC, we start with a sample from a prior distribution and propose a new sample from a proposal distribution, which is accepted with a probability relating the the ratio of the posterior distribution to the proposal distributions. If accepted, this proposed sample is added to the chain, or otherwise, the original sample is added to the chain. This is repeated over many iterations and eventually creates a sequence of samples from the posterior distribution. The CES code uses AbstractMCMC.jl, full details can be found here. For this example, we will use a random walk Metropolis-Hastings sampler (RWMHSampling), which assumes that the proposal distribution is a random walk, with a step-size delta. Usually, we have little knowledge of what this step size should be, but we can optimize this as shown below.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"First, we will load the additional packages we need:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"using CalibrateEmulateSample.MarkovChainMonteCarlo","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We will provide the API with the observations, priors and our cheap emulator from the previous section. In this example we use the GP emulator. First, we need to find a suitable starting point, ideally one that is near the posterior distribution. We will use the final ensemble mean from EKI as this will increase the chance of acceptance near the start of the chain, and reduce burn-in time.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"init_sample = EKP.get_u_mean_final(ensemble_kalman_process)\nprintln(\"initial parameters: \", init_sample) # (1.11, 6.37)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Now, we can set up and carry out the MCMC starting from this point. ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"mcmc = MCMCWrapper(RWMHSampling(), y_obs, prior, emulator_gp; init_params = init_sample)\n# First let's run a short chain to determine a good step size\nnew_step = optimize_stepsize(mcmc; init_stepsize = 0.1, N = 2000, discard_initial = 0)\n\n# Now begin the actual MCMC\nprintln(\"Begin MCMC - with step size \", new_step)\nchain = MarkovChainMonteCarlo.sample(mcmc, 100_000; stepsize = new_step, discard_initial = 2_000)\n\n# We can print summary statistics of the MCMC chain\ndisplay(chain)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"parameters mean std\namplitude 1.1068 0.0943\nvert_shift 6.3897 0.4601","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"Note that these values are provided in the unconstrained space. The vertical shift seems reasonable, but the amplitude is not. This is because the amplitude is constrained to be positive, but the MCMC is run in the unconstrained space. We can transform to the real constrained space and re-calculate these values.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"# Extract posterior samples\nposterior = MarkovChainMonteCarlo.get_posterior(mcmc, chain)\n# Back to constrained coordinates\nconstrained_posterior = Emulators.transform_unconstrained_to_constrained(\n prior, MarkovChainMonteCarlo.get_distribution(posterior)\n)\nprintln(\"Amplitude mean: \", mean(constrained_posterior[\"amplitude\"]), \", std: \", std(constrained_posterior[\"amplitude\"]))\nprintln(\"Vertical shift mean: \", mean(constrained_posterior[\"vert_shift\"]), \", std: \", std(constrained_posterior[\"vert_shift\"]))","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"This gives:","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"parameters mean std\namplitude 3.0382 0.2880\nvert_shift 6.3774 0.4586","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"This is in agreement with the true theta=(30 70) and with the observational covariance matrix we provided Gamma=02 * I (i.e., a standard deviation of approx. 045). CalibrateEmulateSample.jl has built-in plotting recipes to help us visualize the prior and posterior distributions. Note that these are the marginal distributions.","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"# We can quickly plot priors and posterior using built-in capabilities\np = plot(prior, fill = :lightgray)\nplot!(posterior, fill = :darkblue, alpha = 0.5)\n","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: GP_posterior)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"The MCMC has learned the posterior distribution which is much narrower than the prior. For multidimensional problems, the posterior is typically multidimensional, and marginal distribution plots do not show how parameters co-vary. We plot a 2D histogram of theta_1 vs. theta_2 below, with the marginal distributions on each axis. ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: GP_2d_posterior)","category":"page"},{"location":"examples/sinusoid_example/#Sample-with-Random-Features","page":"Simple example walkthrough","title":"Sample with Random Features","text":"","category":"section"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"We can repeat the sampling method using the random features emulator instead of the Gaussian process and we find similar results: ","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"parameters mean std\namplitude 3.3210 0.7216\nvert_shift 6.3986 0.5098","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"(Image: RF_2d_posterior)","category":"page"},{"location":"examples/sinusoid_example/","page":"Simple example walkthrough","title":"Simple example walkthrough","text":"It is reassuring to see that our uncertainty quantification methods are robust to the different emulator choices here. This is because our particular GP and RF emulators showed similar accuracy during validation. However, this result is highly sensitive to the choices of GP kernel and RF kernel structure. If you find very different posterior distributions for different emulators, it is likely that the kernel choices need be refined. The kernel choices must be flexible enough to accurately capture the relationships between the inputs and outputs. We recommend trying a variety of different emulator configurations and carefully considering emulator validation on samples that the emulator has not been trained on. ","category":"page"},{"location":"contributing/#Contributing","page":"Contributing","title":"Contributing","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"Thank you for considering contributing to CalibrateEmulateSample! We encourage opening issues and pull requests (PRs).","category":"page"},{"location":"contributing/#What-to-contribute?","page":"Contributing","title":"What to contribute?","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"The easiest way to contribute is by using CalibrateEmulateSample, identifying problems and opening issues;\nYou can try to tackle an existing issue. It is best to outline your proposed solution in the issue thread before implementing it in a PR;\nWrite an example or tutorial. It is likely that other users may find your use of CalibrateEmulateSample insightful;\nImprove documentation or comments if you found something hard to use;\nImplement a new feature if you need it. We strongly encourage opening an issue to make sure the administrators are on board before opening a PR with an unsolicited feature addition. Examples could include implementing new statistical emulators, or implementing new data compression tools (beyond normalization, standardization and truncated SVD)","category":"page"},{"location":"contributing/#Using-git","page":"Contributing","title":"Using git","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"If you are unfamiliar with git and version control, the following guides will be helpful:","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"Atlassian (bitbucket) git tutorials. A set of tips and tricks for getting started with git.\nGitHub's git tutorials. A set of resources from GitHub to learn git.","category":"page"},{"location":"contributing/#Forks-and-branches","page":"Contributing","title":"Forks and branches","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"Create your own fork of CalibrateEmulateSample on GitHub and check out your copy:","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"$ git clone https://github.com//CalibrateEmulateSample.jl.git\n$ cd CalibrateEmulateSample.jl","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"Now you have access to your fork of CalibrateEmulateSample through origin. Create a branch for your feature; this will hold your contribution:","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"$ git checkout -b ","category":"page"},{"location":"contributing/#Some-useful-tips","page":"Contributing","title":"Some useful tips","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"When you start working on a new feature branch, make sure you start from main by running: git checkout main and git pull.\nCreate a new branch from main by using git checkout -b .","category":"page"},{"location":"contributing/#Develop-your-feature","page":"Contributing","title":"Develop your feature","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"Make sure you add tests for your code in test/ and appropriate documentation in the code and/or in docs/. Before committing your changes, you can verify their behavior by running the tests, the examples, and building the documentation locally. In addition, make sure your feature follows the formatting guidelines by running","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"julia --project=.dev .dev/climaformat.jl .","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"from the CalibrateEmulateSample.jl directory.","category":"page"},{"location":"contributing/#Squash-and-rebase","page":"Contributing","title":"Squash and rebase","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"When your PR is ready for review, clean up your commit history by squashing and make sure your code is current with CalibrateEmulateSample.jl main by rebasing. The general rule is that a PR should contain a single commit with a descriptive message.","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"To make sure you are up to date with main, you can use the following workflow:","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"$ git checkout main\n$ git pull\n$ git checkout \n$ git rebase main","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"This may create conflicts with the local branch. The conflicted files will be outlined by git. To resolve conflicts, we have to manually edit the files (e.g. with vim). The conflicts will appear between >>>>, ===== and <<<<<. We need to delete these lines and pick what version we want to keep.","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"To squash your commits, you can use the following command:","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"$ git rebase -i HEAD~n","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"where n is the number of commits you need to squash into one. Then, follow the instructions in the terminal. For example, to squash 4 commits:","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"$ git rebase -i HEAD~4","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"will open the following file in (typically) vim:","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":" pick 01d1124 \n pick 6340aaa \n pick ebfd367 \n pick 30e0ccb \n\n # Rebase 60709da..30e0ccb onto 60709da\n #\n # Commands:\n # p, pick = use commit\n # e, edit = use commit, but stop for amending\n # s, squash = use commit, but meld into previous commit\n #\n # If you remove a line here THAT COMMIT WILL BE LOST.\n # However, if you remove everything, the rebase will be aborted.\n##","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"We want to keep the first commit and squash the last 3. We do so by changing the last three commits to squash and then do :wq on vim.","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":" pick 01d1124 \n squash 6340aaa \n squash ebfd367 \n squash 30e0ccb \n\n # Rebase 60709da..30e0ccb onto 60709da\n #\n # Commands:\n # p, pick = use commit\n # e, edit = use commit, but stop for amending\n # s, squash = use commit, but meld into previous commit\n #\n # If you remove a line here THAT COMMIT WILL BE LOST.\n # However, if you remove everything, the rebase will be aborted.","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"Then in the next screen that appears, we can just delete all messages that we do not want to show in the commit. After this is done and we are back to the console, we have to force push. We need to force push because we rewrote the local commit history.","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"$ git push -u origin --force","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"You can find more information about squashing here.","category":"page"},{"location":"contributing/#Unit-testing","page":"Contributing","title":"Unit testing","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"Currently a number of checks are run per commit for a given PR.","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"JuliaFormatter checks if the PR is formatted with .dev/climaformat.jl.\nDocumentation rebuilds the documentation for the PR and checks if the docs are consistent and generate valid output.\nUnit Tests run subsets of the unit tests defined in tests/, using Pkg.test(). The tests are run in parallel to ensure that they finish in a reasonable time. The tests only run the latest commit for a PR, branch and will kill any stale jobs on push. These tests are only run on linux (Ubuntu LTS).","category":"page"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"Unit tests are run against every new commit for a given PR, the status of the unit-tests are not checked during the merge process but act as a sanity check for developers and reviewers. Depending on the content changed in the PR, some CI checks that are not necessary will be skipped. For example doc only changes do not require the unit tests to be run.","category":"page"},{"location":"contributing/#The-merge-process","page":"Contributing","title":"The merge process","text":"","category":"section"},{"location":"contributing/","page":"Contributing","title":"Contributing","text":"We ensure that all unit tests across several environments, Documentation builds, and integration tests (managed by Buildkite), pass before merging any PR into main. The integration tests currently run some of our example cases in examples/.","category":"page"},{"location":"installation_instructions/#Installation-Instructions","page":"Installation instructions","title":"Installation Instructions","text":"","category":"section"},{"location":"installation_instructions/#Installing-CalibrateEmulateSample.jl","page":"Installation instructions","title":"Installing CalibrateEmulateSample.jl","text":"","category":"section"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"Currently CalibrateEmulateSample (CES) depends on some external python dependencies including scipy (version 1.8.1 works) and scikit-learn (version 1.1.1 works) that are wrapped by ScikitLearn.jl.","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"If you have dependencies installed already, then the code can be used by simply entering","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"julia --project\n> ]\n> add CalibrateEmulateSample","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"One may instead clone the project into a new local repository (using SSH or https link from github), to easily access the CES codebase (e.g. to run our example suite) .","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"If you do not have the dependencies installed, we have found it is easiest to install them via Julia's \"Conda.jl\",","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"julia --project\n> ]\n> add Conda\n> add CalibrateEmulateSample","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"Then install the dependencies by having the project use its own Conda environment variable (set by exporting the ENV variable PYTHON=\"\").","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"> PYTHON=\"\" julia --project -e 'using Pkg; Pkg.instantiate()'","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"This call should build Conda and Pycall. The scikit-learn package (along with scipy) then has to be installed if using a Julia project-specific Conda environment:","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"> PYTHON=\"\" julia --project -e 'using Conda; Conda.add(\"scipy=1.8.1\", channel=\"conda-forge\")'\n> PYTHON=\"\" julia --project -e 'using Conda; Conda.add(\"scikit-learn=1.1.1\")'\n","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"See the PyCall.jl documentation for more information about how to configure the local Julia / Conda / Python environment. ","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"To test that the package is working:","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"> julia --project -e 'using Pkg; Pkg.test()'","category":"page"},{"location":"installation_instructions/#Building-the-documentation-locally","page":"Installation instructions","title":"Building the documentation locally","text":"","category":"section"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"You need to first build the top-level project before building the documentation:","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"cd CalibrateEmulateSample.jl\njulia --project -e 'using Pkg; Pkg.instantiate()'","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"Then you can build the project documentation under the docs/ sub-project:","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"julia --project=docs/ -e 'using Pkg; Pkg.instantiate()'\njulia --project=docs/ docs/make.jl","category":"page"},{"location":"installation_instructions/","page":"Installation instructions","title":"Installation instructions","text":"The locally rendered HTML documentation can be viewed at docs/build/index.html. Occasional figures may only be viewable in the online documentation due to the fancy-url package.","category":"page"},{"location":"API/Utilities/#Utilities","page":"Utilities","title":"Utilities","text":"","category":"section"},{"location":"API/Utilities/","page":"Utilities","title":"Utilities","text":"Modules = [CalibrateEmulateSample.Utilities]\nOrder = [:module, :type, :function]","category":"page"},{"location":"API/Utilities/#CalibrateEmulateSample.Utilities.get_obs_sample-Union{Tuple{IT}, Tuple{Random.AbstractRNG, EnsembleKalmanProcesses.Observations.Observation}} where IT<:Int64","page":"Utilities","title":"CalibrateEmulateSample.Utilities.get_obs_sample","text":"get_obs_sample(\n rng::Random.AbstractRNG,\n obs::EnsembleKalmanProcesses.Observations.Observation;\n rng_seed\n) -> Any\n\n\nReturn a random sample from the observations, for use in the MCMC.\n\nrng - optional RNG object used to pick random sample; defaults to Random.GLOBAL_RNG.\nobs - Observation struct with the observations (extract will pick one of the sample observations to train).\nrng_seed - optional kwarg; if provided, used to re-seed rng before sampling.\n\n\n\n\n\n","category":"method"},{"location":"API/Utilities/#CalibrateEmulateSample.Utilities.get_training_points-Union{Tuple{P}, Tuple{IT}, Tuple{FT}, Tuple{EnsembleKalmanProcesses.EnsembleKalmanProcess{FT, IT, P}, Union{AbstractVector{IT}, IT}}} where {FT, IT, P}","page":"Utilities","title":"CalibrateEmulateSample.Utilities.get_training_points","text":"get_training_points(\n ekp::EnsembleKalmanProcesses.EnsembleKalmanProcess{FT, IT, P},\n train_iterations::Union{AbstractVector{IT}, IT} where IT\n) -> EnsembleKalmanProcesses.DataContainers.PairedDataContainer\n\n\nExtract the training points needed to train the Gaussian process regression.\n\nekp - EnsembleKalmanProcess holding the parameters and the data that were produced during the Ensemble Kalman (EK) process.\ntrain_iterations - Number (or indices) EK layers/iterations to train on.\n\n\n\n\n\n","category":"method"},{"location":"API/RandomFeatures/#RandomFeatures","page":"Random Features","title":"RandomFeatures","text":"","category":"section"},{"location":"API/RandomFeatures/","page":"Random Features","title":"Random Features","text":"CurrentModule = CalibrateEmulateSample.Emulators","category":"page"},{"location":"API/RandomFeatures/#Kernel-and-Covariance-structure","page":"Random Features","title":"Kernel and Covariance structure","text":"","category":"section"},{"location":"API/RandomFeatures/","page":"Random Features","title":"Random Features","text":"OneDimFactor\nDiagonalFactor\nCholeskyFactor\nLowRankFactor\nHierarchicalLowRankFactor\nSeparableKernel\nNonseparableKernel\ncalculate_n_hyperparameters\nhyperparameters_from_flat\nbuild_default_prior","category":"page"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.OneDimFactor","page":"Random Features","title":"CalibrateEmulateSample.Emulators.OneDimFactor","text":"struct OneDimFactor <: CalibrateEmulateSample.Emulators.CovarianceStructureType\n\ncovariance structure for a one-dimensional space\n\n\n\n\n\n","category":"type"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.DiagonalFactor","page":"Random Features","title":"CalibrateEmulateSample.Emulators.DiagonalFactor","text":"struct DiagonalFactor{FT<:AbstractFloat} <: CalibrateEmulateSample.Emulators.CovarianceStructureType\n\nbuilds a diagonal covariance structure\n\n\n\n\n\n","category":"type"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.CholeskyFactor","page":"Random Features","title":"CalibrateEmulateSample.Emulators.CholeskyFactor","text":"struct CholeskyFactor{FT<:AbstractFloat} <: CalibrateEmulateSample.Emulators.CovarianceStructureType\n\nbuilds a general positive-definite covariance structure\n\n\n\n\n\n","category":"type"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.LowRankFactor","page":"Random Features","title":"CalibrateEmulateSample.Emulators.LowRankFactor","text":"struct LowRankFactor{FT<:AbstractFloat} <: CalibrateEmulateSample.Emulators.CovarianceStructureType\n\nbuilds a covariance structure that deviates from the identity with a low-rank perturbation. This perturbation is diagonalized in the low-rank space\n\n\n\n\n\n","category":"type"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.HierarchicalLowRankFactor","page":"Random Features","title":"CalibrateEmulateSample.Emulators.HierarchicalLowRankFactor","text":"struct HierarchicalLowRankFactor{FT<:AbstractFloat} <: CalibrateEmulateSample.Emulators.CovarianceStructureType\n\nbuilds a covariance structure that deviates from the identity with a more general low-rank perturbation\n\n\n\n\n\n","category":"type"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.SeparableKernel","page":"Random Features","title":"CalibrateEmulateSample.Emulators.SeparableKernel","text":"struct SeparableKernel{CST1<:CalibrateEmulateSample.Emulators.CovarianceStructureType, CST2<:CalibrateEmulateSample.Emulators.CovarianceStructureType} <: CalibrateEmulateSample.Emulators.KernelStructureType\n\nBuilds a separable kernel, i.e. one that accounts for input and output covariance structure separately\n\n\n\n\n\n","category":"type"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.NonseparableKernel","page":"Random Features","title":"CalibrateEmulateSample.Emulators.NonseparableKernel","text":"struct NonseparableKernel{CST<:CalibrateEmulateSample.Emulators.CovarianceStructureType} <: CalibrateEmulateSample.Emulators.KernelStructureType\n\nBuilds a nonseparable kernel, i.e. one that accounts for a joint input and output covariance structure\n\n\n\n\n\n","category":"type"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.calculate_n_hyperparameters","page":"Random Features","title":"CalibrateEmulateSample.Emulators.calculate_n_hyperparameters","text":"calculate_n_hyperparameters(\n d::Int64,\n odf::CalibrateEmulateSample.Emulators.OneDimFactor\n) -> Int64\n\n\ncalculates the number of hyperparameters generated by the choice of covariance structure\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.hyperparameters_from_flat","page":"Random Features","title":"CalibrateEmulateSample.Emulators.hyperparameters_from_flat","text":"hyperparameters_from_flat(\n x::AbstractVector,\n odf::CalibrateEmulateSample.Emulators.OneDimFactor\n)\n\n\nreshapes a list of hyperparameters into a covariance matrix based on the selected structure\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.build_default_prior","page":"Random Features","title":"CalibrateEmulateSample.Emulators.build_default_prior","text":"build_default_prior(\n name::AbstractString,\n n_hp::Int64,\n odf::CalibrateEmulateSample.Emulators.OneDimFactor\n)\n\n\nbuilds a prior distribution for the kernel hyperparameters to initialize optimization.\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#Scalar-interface","page":"Random Features","title":"Scalar interface","text":"","category":"section"},{"location":"API/RandomFeatures/","page":"Random Features","title":"Random Features","text":"ScalarRandomFeatureInterface\nScalarRandomFeatureInterface(::Int,::Int)\nbuild_models!(::ScalarRandomFeatureInterface, ::PairedDataContainer{FT}) where {FT <: AbstractFloat}\npredict(::ScalarRandomFeatureInterface, ::M) where {M <: AbstractMatrix}","category":"page"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface","page":"Random Features","title":"CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface","text":"struct ScalarRandomFeatureInterface{S<:AbstractString, RNG<:Random.AbstractRNG, KST<:CalibrateEmulateSample.Emulators.KernelStructureType} <: CalibrateEmulateSample.Emulators.RandomFeatureInterface\n\nStructure holding the Scalar Random Feature models. \n\nFields\n\nrfms::Vector{RandomFeatures.Methods.RandomFeatureMethod}: vector of RandomFeatureMethods, contains the feature structure, batch-sizes and regularization\nfitted_features::Vector{RandomFeatures.Methods.Fit}: vector of Fits, containing the matrix decomposition and coefficients of RF when fitted to data\nbatch_sizes::Union{Nothing, Dict{S, Int64}} where S<:AbstractString: batch sizes\nn_features::Union{Nothing, Int64}: n_features\ninput_dim::Int64: input dimension\nrng::Random.AbstractRNG: choice of random number generator\nkernel_structure::CalibrateEmulateSample.Emulators.KernelStructureType: Kernel structure type (e.g. Separable or Nonseparable)\nfeature_decomposition::AbstractString: Random Feature decomposition, choose from \"svd\" or \"cholesky\" (default)\noptimizer_options::Dict{S} where S<:AbstractString: dictionary of options for hyperparameter optimizer\n\n\n\n\n\n","category":"type"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface-Tuple{Int64, Int64}","page":"Random Features","title":"CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface","text":"ScalarRandomFeatureInterface(\n n_features::Int64,\n input_dim::Int64;\n kernel_structure,\n batch_sizes,\n rng,\n feature_decomposition,\n optimizer_options\n) -> CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface{String, Random._GLOBAL_RNG, CalibrateEmulateSample.Emulators.SeparableKernel{CST1, CalibrateEmulateSample.Emulators.OneDimFactor}} where CST1<:CalibrateEmulateSample.Emulators.CovarianceStructureType\n\n\nConstructs a ScalarRandomFeatureInterface <: MachineLearningTool interface for the RandomFeatures.jl package for multi-input and single- (or decorrelated-)output emulators.\n\nn_features - the number of random features\ninput_dim - the dimension of the input space\nkernel_structure - - a prescribed form of kernel structure\nbatch_sizes = nothing - Dictionary of batch sizes passed RandomFeatures.jl object (see definition there)\nrng = Random.GLOBAL_RNG - random number generator \nfeature_decomposition = \"cholesky\" - choice of how to store decompositions of random features, cholesky or svd available\noptimizer_options = nothing - Dict of options to pass into EKI optimization of hyperparameters (defaults created in ScalarRandomFeatureInterface constructor):\n\"prior\": the prior for the hyperparameter optimization \n\"priorinscale\": use this to tune the input prior scale\n\"n_ensemble\": number of ensemble members\n\"n_iteration\": number of eki iterations\n\"covsamplemultiplier\": increase for more samples to estimate covariance matrix in optimization (default 10.0, minimum 0.0) \n\"scheduler\": Learning rate Scheduler (a.k.a. EKP timestepper) Default: DataMisfitController\n\"tikhonov\": tikhonov regularization parameter if >0\n\"inflation\": additive inflation ∈ [0,1] with 0 being no inflation\n\"train_fraction\": e.g. 0.8 (default) means 80:20 train - test split\n\"nfeaturesopt\": fix the number of features for optimization (default n_features, as used for prediction)\n\"multithread\": how to multithread. \"ensemble\" (default) threads across ensemble members \"tullio\" threads random feature matrix algebra\n\"accelerator\": use EKP accelerators (default is no acceleration)\n\"verbose\" => false, verbose optimizer statements\n\n\n\n\n\n","category":"method"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.build_models!-Union{Tuple{FT}, Tuple{CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface, EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT}}} where FT<:AbstractFloat","page":"Random Features","title":"CalibrateEmulateSample.Emulators.build_models!","text":"build_models!(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface,\n input_output_pairs::EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT<:AbstractFloat}\n)\n\n\nBuilds the random feature method from hyperparameters. We use cosine activation functions and a Multivariate Normal distribution (from Distributions.jl) with mean M=0, and input covariance U built with the CovarianceStructureType.\n\n\n\n\n\n","category":"method"},{"location":"API/RandomFeatures/#GaussianProcesses.predict-Union{Tuple{M}, Tuple{CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface, M}} where M<:(AbstractMatrix)","page":"Random Features","title":"GaussianProcesses.predict","text":"predict(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface,\n new_inputs::AbstractMatrix;\n multithread\n) -> Tuple{Any, Any}\n\n\nPrediction of data observation (not latent function) at new inputs (passed in as columns in a matrix). That is, we add the observational noise into predictions.\n\n\n\n\n\n","category":"method"},{"location":"API/RandomFeatures/#Vector-Interface","page":"Random Features","title":"Vector Interface","text":"","category":"section"},{"location":"API/RandomFeatures/","page":"Random Features","title":"Random Features","text":"VectorRandomFeatureInterface\nVectorRandomFeatureInterface(::Int, ::Int, ::Int)\nbuild_models!(::VectorRandomFeatureInterface, ::PairedDataContainer{FT}) where {FT <: AbstractFloat}\npredict(::VectorRandomFeatureInterface, ::M) where {M <: AbstractMatrix}","category":"page"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface","page":"Random Features","title":"CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface","text":"struct VectorRandomFeatureInterface{S<:AbstractString, RNG<:Random.AbstractRNG, KST<:CalibrateEmulateSample.Emulators.KernelStructureType} <: CalibrateEmulateSample.Emulators.RandomFeatureInterface\n\nStructure holding the Vector Random Feature models. \n\nFields\n\nrfms::Vector{RandomFeatures.Methods.RandomFeatureMethod}: A vector of RandomFeatureMethods, contains the feature structure, batch-sizes and regularization\nfitted_features::Vector{RandomFeatures.Methods.Fit}: vector of Fits, containing the matrix decomposition and coefficients of RF when fitted to data\nbatch_sizes::Union{Nothing, Dict{S, Int64}} where S<:AbstractString: batch sizes\nn_features::Union{Nothing, Int64}: number of features\ninput_dim::Int64: input dimension\noutput_dim::Int64: output_dimension\nrng::Random.AbstractRNG: rng\nregularization::Vector{Union{LinearAlgebra.Diagonal, LinearAlgebra.UniformScaling, Matrix}}: regularization\nkernel_structure::CalibrateEmulateSample.Emulators.KernelStructureType: Kernel structure type (e.g. Separable or Nonseparable)\nfeature_decomposition::AbstractString: Random Feature decomposition, choose from \"svd\" or \"cholesky\" (default)\noptimizer_options::Dict: dictionary of options for hyperparameter optimizer\n\n\n\n\n\n","category":"type"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface-Tuple{Int64, Int64, Int64}","page":"Random Features","title":"CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface","text":"VectorRandomFeatureInterface(\n n_features::Int64,\n input_dim::Int64,\n output_dim::Int64;\n kernel_structure,\n batch_sizes,\n rng,\n feature_decomposition,\n optimizer_options\n) -> CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface{String, Random._GLOBAL_RNG, CalibrateEmulateSample.Emulators.SeparableKernel{CST1, CST2}} where {CST1<:CalibrateEmulateSample.Emulators.CovarianceStructureType, CST2<:CalibrateEmulateSample.Emulators.CovarianceStructureType}\n\n\nConstructs a VectorRandomFeatureInterface <: MachineLearningTool interface for the RandomFeatures.jl package for multi-input and multi-output emulators.\n\nn_features - the number of random features\ninput_dim - the dimension of the input space\noutput_dim - the dimension of the output space\nkernel_structure - - a prescribed form of kernel structure\nbatch_sizes = nothing - Dictionary of batch sizes passed RandomFeatures.jl object (see definition there)\nrng = Random.GLOBAL_RNG - random number generator \nfeature_decomposition = \"cholesky\" - choice of how to store decompositions of random features, cholesky or svd available\noptimizer_options = nothing - Dict of options to pass into EKI optimization of hyperparameters (defaults created in VectorRandomFeatureInterface constructor):\n\"prior\": the prior for the hyperparameter optimization\n\"priorinscale\"/\"prioroutscale\": use these to tune the input/output prior scale.\n\"n_ensemble\": number of ensemble members\n\"n_iteration\": number of eki iterations\n\"scheduler\": Learning rate Scheduler (a.k.a. EKP timestepper) Default: DataMisfitController\n\"covsamplemultiplier\": increase for more samples to estimate covariance matrix in optimization (default 10.0, minimum 0.0) \n\"tikhonov\": tikhonov regularization parameter if > 0\n\"inflation\": additive inflation ∈ [0,1] with 0 being no inflation\n\"train_fraction\": e.g. 0.8 (default) means 80:20 train - test split\n\"nfeaturesopt\": fix the number of features for optimization (default n_features, as used for prediction)\n\"multithread\": how to multithread. \"ensemble\" (default) threads across ensemble members \"tullio\" threads random feature matrix algebra\n\"accelerator\": use EKP accelerators (default is no acceleration)\n\"verbose\" => false, verbose optimizer statements to check convergence, priors and optimal parameters.\n\n\n\n\n\n","category":"method"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.build_models!-Union{Tuple{FT}, Tuple{CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface, EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT}}} where FT<:AbstractFloat","page":"Random Features","title":"CalibrateEmulateSample.Emulators.build_models!","text":"build_models!(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface,\n input_output_pairs::EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT<:AbstractFloat};\n regularization_matrix\n) -> Union{Nothing, Vector{Union{LinearAlgebra.Diagonal, LinearAlgebra.UniformScaling, Matrix}}}\n\n\nBuild Vector Random Feature model for the input-output pairs subject to regularization, and optimizes the hyperparameters with EKP. \n\n\n\n\n\n","category":"method"},{"location":"API/RandomFeatures/#GaussianProcesses.predict-Union{Tuple{M}, Tuple{CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface, M}} where M<:(AbstractMatrix)","page":"Random Features","title":"GaussianProcesses.predict","text":"predict(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface,\n new_inputs::AbstractMatrix\n) -> Tuple{Any, Any}\n\n\nPrediction of data observation (not latent function) at new inputs (passed in as columns in a matrix). That is, we add the observational noise into predictions.\n\n\n\n\n\n","category":"method"},{"location":"API/RandomFeatures/#Other-utilities","page":"Random Features","title":"Other utilities","text":"","category":"section"},{"location":"API/RandomFeatures/","page":"Random Features","title":"Random Features","text":"get_rfms\nget_fitted_features\nget_batch_sizes\nget_n_features\nget_input_dim\nget_output_dim\nget_rng\nget_kernel_structure\nget_feature_decomposition\nget_optimizer_options\noptimize_hyperparameters!(::ScalarRandomFeatureInterface) \noptimize_hyperparameters!(::VectorRandomFeatureInterface) \nshrinkage_cov","category":"page"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_rfms","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_rfms","text":"get_rfms(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface\n) -> Vector{RandomFeatures.Methods.RandomFeatureMethod}\n\n\ngets the rfms field\n\n\n\n\n\nget_rfms(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> Vector{RandomFeatures.Methods.RandomFeatureMethod}\n\n\nGets the rfms field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_fitted_features","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_fitted_features","text":"get_fitted_features(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface\n) -> Vector{RandomFeatures.Methods.Fit}\n\n\ngets the fitted_features field\n\n\n\n\n\nget_fitted_features(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> Vector{RandomFeatures.Methods.Fit}\n\n\nGets the fitted_features field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_batch_sizes","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_batch_sizes","text":"get_batch_sizes(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface\n) -> Union{Nothing, Dict{S, Int64}} where S<:AbstractString\n\n\ngets batch_sizes the field\n\n\n\n\n\nget_batch_sizes(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> Union{Nothing, Dict{S, Int64}} where S<:AbstractString\n\n\nGets the batch_sizes field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_n_features","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_n_features","text":"get_n_features(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface\n) -> Union{Nothing, Int64}\n\n\ngets the n_features field\n\n\n\n\n\nget_n_features(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> Union{Nothing, Int64}\n\n\nGets the n_features field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_input_dim","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_input_dim","text":"get_input_dim(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface\n) -> Int64\n\n\ngets the input_dim field\n\n\n\n\n\nget_input_dim(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> Int64\n\n\nGets the input_dim field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_output_dim","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_output_dim","text":"get_output_dim(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> Int64\n\n\nGets the output_dim field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_rng","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_rng","text":"get_rng(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface\n) -> Random.AbstractRNG\n\n\ngets the rng field\n\n\n\n\n\nget_rng(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> Random.AbstractRNG\n\n\nGets the rng field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_kernel_structure","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_kernel_structure","text":"get_kernel_structure(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface\n) -> CalibrateEmulateSample.Emulators.KernelStructureType\n\n\nGets the kernel_structure field\n\n\n\n\n\nget_kernel_structure(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> CalibrateEmulateSample.Emulators.KernelStructureType\n\n\nGets the kernel_structure field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_feature_decomposition","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_feature_decomposition","text":"get_feature_decomposition(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface\n) -> AbstractString\n\n\ngets the feature_decomposition field\n\n\n\n\n\nget_feature_decomposition(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> AbstractString\n\n\nGets the feature_decomposition field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.get_optimizer_options","page":"Random Features","title":"CalibrateEmulateSample.Emulators.get_optimizer_options","text":"get_optimizer_options(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface\n) -> Dict{S} where S<:AbstractString\n\n\ngets the optimizer_options field\n\n\n\n\n\nget_optimizer_options(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface\n) -> Dict\n\n\nGets the optimizer_options field\n\n\n\n\n\n","category":"function"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.optimize_hyperparameters!-Tuple{CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface}","page":"Random Features","title":"CalibrateEmulateSample.Emulators.optimize_hyperparameters!","text":"optimize_hyperparameters!(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface,\n args...;\n kwargs...\n)\n\n\nEmpty method, as optimization takes place within the build_models stage\n\n\n\n\n\n","category":"method"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.optimize_hyperparameters!-Tuple{CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface}","page":"Random Features","title":"CalibrateEmulateSample.Emulators.optimize_hyperparameters!","text":"optimize_hyperparameters!(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface,\n args...;\n kwargs...\n)\n\n\nEmpty method, as optimization takes place within the build_models stage\n\n\n\n\n\n","category":"method"},{"location":"API/RandomFeatures/#CalibrateEmulateSample.Emulators.shrinkage_cov","page":"Random Features","title":"CalibrateEmulateSample.Emulators.shrinkage_cov","text":"shrinkage_cov(sample_mat::AbstractMatrix) -> Any\n\n\nCalculate the empirical covariance, additionally applying a shrinkage operator (here the Ledoit Wolf 2004 shrinkage operation). Known to have better stability properties than Monte-Carlo for low sample sizes\n\n\n\n\n\n","category":"function"},{"location":"glossary/#Glossary","page":"Glossary","title":"Glossary","text":"","category":"section"},{"location":"glossary/","page":"Glossary","title":"Glossary","text":"The following list includes the names and symbols of recurring concepts in CalibrateEmulateSample.jl. Some of these variables do not appear in the codebase, which relies on array programming for performance. Contributions to the codebase require following this notational convention. Similarly, if you find inconsistencies in the documentation or codebase, please report an issue on GitHub.","category":"page"},{"location":"glossary/","page":"Glossary","title":"Glossary","text":"Name Symbol (Theory/Docs) Symbol (Code)\nParameter vector, Parameters (unconstrained space) theta θ\nParameter vector size, Number of parameters p N_par\nEnsemble size J N_ens\nEnsemble particles, members theta^(j) \nNumber of iterations N_rm it N_iter\nObservation vector, Observations, Data vector y y\nObservation vector size, Data vector size d N_obs\nObservational noise eta obs_noise\nObservational noise covariance Gamma_y obs_noise_cov\nHilbert space inner product langle phi Gamma^-1 psi rangle \nForward map mathcalG G\nDynamical model Psi Ψ\nTransform map (constrained to unconstrained) mathcalT T\nObservation map mathcalH H\nPrior covariance (unconstrained space) Gamma_theta prior_cov\nPrior mean (unconstrained space) m_theta prior_mean","category":"page"},{"location":"examples/lorenz_example/#Lorenz-96-example","page":"Lorenz example","title":"Lorenz 96 example","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"info: How do I run this code?\nThe full code is found in the examples/ directory of the github repository","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The Lorenz 96 (hereafter L96) example is a toy-problem for the application of the CalibrateEmulateSample.jl optimization and approximate uncertainty quantification methodologies. Here is L96 with additional periodic-in-time forcing, we try to determine parameters (sinusoidal amplitude and stationary component of the forcing) from some output statistics. The standard L96 equations are implemented with an additional forcing term with time dependence. The output statistics which are used for learning are the finite time-averaged variances.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The standard single-scale L96 equations are implemented. The Lorenz 96 system (Lorenz, 1996) is given by ","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"fracd x_id t = (x_i+1 - x_i-2) x_i-1 - x_i + F","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"with i indicating the index of the given longitude. The number of longitudes is given by N. The boundary conditions are given by","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"x_-1 = x_N-1 x_0 = x_N x_N+1 = x_1","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The time scaling is such that the characteristic time is 5 days (Lorenz, 1996). For very small values of F, the solutions x_i decay to F after the initial transient feature. For moderate values of F, the solutions are periodic, and for larger values of F, the system is chaotic. The solution variance is a function of the forcing magnitude. Variations in the base state as a function of time can be imposed through a time-dependent forcing term F(t).","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"A temporal forcing term is defined","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"F = F_s + A sin(omega t)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"with steady-state forcing F_s, transient forcing amplitude A, and transient forcing frequency omega. The total forcing F must be within the chaotic regime of L96 for all time given the prescribed N.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The L96 dynamics are solved with RK4 integration.","category":"page"},{"location":"examples/lorenz_example/#Structure","page":"Lorenz example","title":"Structure","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The example is structured with two distinct components: 1) L96 dynamical system solver; 2) calibrate-emulate sample code. Each of these are described below.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The forward mapping from input parameters to output statistics of the L96 system is solved using the GModel.jl code, which runs the L96 model across different input parameters theta. The source code for the L96 system solution is within the GModel_common.jl code. ","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The Calibrate code is located in calibrate.jl which provides the functionality to run the L96 dynamical system (within the GModel.jl code), extract time-averaged statistics from the L96 states, and use the time-average statistics for calibration. While this example description is self-contained, there is an additional description of the use of EnsembleKalmanProcesses.jl for the L96 example that is accessible here.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The Emulate-Sample code is located in emulate_sample.jl which provides the functionality to use the input-output pairs from the Calibrate stage for emulation and sampling (uncertainty quantification). The emulate_sample.jl code relies on outputs from the calibrate.jl code","category":"page"},{"location":"examples/lorenz_example/#Walkthrough-of-the-code","page":"Lorenz example","title":"Walkthrough of the code","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"This walkthrough covers calibrate-emulate-sample for the L96 problem defined above. The goal is to learn parameters F_s and A based on the time averaged statistics in a perfect model setting. This document focuses on the emulate-sample (emulate_sample.jl) stages, but discussion of the calibration stage calibrate.jl are made when necessary. This code relies on data generated by first running calibrate.jl. A detailed walkthrough of the calibration stage of CES for the L96 example is available here. ","category":"page"},{"location":"examples/lorenz_example/#Inputs","page":"Lorenz example","title":"Inputs","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"First, we load standard packages","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"# Import modules\nusing Distributions # probability distributions and associated functions\nusing LinearAlgebra\nusing StatsPlots\nusing Plots\nusing Random\nusing JLD2","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"Then, we load CalibrateEmulateSample.jl packages","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"# CES \nusing CalibrateEmulateSample.Emulators\nusing CalibrateEmulateSample.MarkovChainMonteCarlo\nusing CalibrateEmulateSample.Utilities\nusing CalibrateEmulateSample.EnsembleKalmanProcesses\nusing CalibrateEmulateSample.ParameterDistributions\nusing CalibrateEmulateSample.DataContainers\nusing CalibrateEmulateSample.Observations","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The first input settings define which input-output pairs to use for training the emulator. The Calibrate stage (run using calibrate.jl) generates parameter-to-data pairs by running the L96 system using an iterative optimization approach (EnsembleKalmanProcess.jl). So we first define which iterations we would like to use data from for our emulator training","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"min_iter = 1\nmax_iter = 5 # number of EKP iterations to use data from is at most this","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The second input settings define the Lorenz dynamics. The emulate_sample.jl code does not actually run the L96 system, it only uses L96 system runs from the calibrate.jl stage to train an emulator and to perform sampling. Therefore, the settings governing the L96 dynamics are fully defined in calibrate.jl and can be modified as necessary. The rest of the input settings in this section are defined in calibrate.jl. ","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"F_true = 8.0 # Mean F\nA_true = 2.5 # Transient F amplitude\nω_true = 2.0 * π / (360.0 / τc) # Frequency of the transient F (non-dim)\nparams_true = [F_true, A_true]\nparam_names = [\"F\", \"A\"]","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The use of the transient forcing term is with the flag, dynamics. Stationary forcing is dynamics=1 (A=0) and transient forcing is used with dynamics=2 (Aneq0). The system with N longitudes is solved over time horizon t_start to Tfit at fixed time step dt.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"N = 36\ndt = 1/64\nt_start = 100\n# Characteristic time scale\nτc = 5.0 # days, prescribed by the L96 problem\n# This has to be less than 360 and 360 must be divisible by Ts_days\nTs_days = 30.0 # Integration length in days (will be made non-dimensional later)\n# Integration length\nTfit = Ts_days / τc","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The states are integrated over time Ts_days to construct the time averaged statistics for use by the Ensemble Kalman Process calibration. The specification of the statistics to be gathered from the states are provided by stats_type.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"We implement (biased) priors as follows","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"prior_means = [F_true + 1.0, A_true + 0.5]\nprior_stds = [2.0, 0.5 * A_true]\n# constrained_gaussian(\"name\", desired_mean, desired_std, lower_bd, upper_bd)\nprior_F = constrained_gaussian(param_names[1], prior_means[1], prior_stds[1], 0, Inf)\nprior_A = constrained_gaussian(param_names[2], prior_means[2], prior_stds[2], 0, Inf)\npriors = combine_distributions([prior_F, prior_A])","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"We use the recommended [constrained_gaussian] to add the desired scale and bounds to the prior distribution, in particular we place lower bounds to preserve positivity. ","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The priors can be plotted directly using plot(priors), as seen below in the example code from calibrate.jl","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"# Plot the prior distribution\np = plot(priors, title = \"prior\")\nplot!(p.subplots[1], [F_true], seriestype = \"vline\", w = 1.5, c = :steelblue, ls = :dash, xlabel = \"F\") # vline on top histogram\nplot!(p.subplots[2], [A_true], seriestype = \"vline\", w = 1.5, c = :steelblue, ls = :dash, xlabel = \"A\") # vline on top histogram","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The observational noise can be generated using the L96 system or prescribed, as specified by var_prescribe. var_prescribe==false The observational noise is constructed by generating independent instantiations of the L96 statistics of interest at the true parameters for different initial conditions. The empirical covariance matrix is constructed.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"var_prescribe==true The observational noise is prescribed as a Gaussian distribution with prescribed mean and variance.","category":"page"},{"location":"examples/lorenz_example/#Calibrate","page":"Lorenz example","title":"Calibrate","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The calibration stage must be run before the emulate-sample stages. The calibration stage is run using calibrate.jl. This code will generate parameter-data pairs that will be used to train the emulator. The parameter-data pairs are visualized below","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"","category":"page"},{"location":"examples/lorenz_example/#Emulate","page":"Lorenz example","title":"Emulate","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"Having run the calibrate.jl code to generate input-output pairs from parameters to data using EnsembleKalmanProcesses.jl, we will now run the Emulate and Sample stages (emulate_sample.jl). First, we need to define which machine learning model we will use for the emulation. We have 8 cases that the user can toggle or customize","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"cases = [\n \"GP\", # diagonalize, train scalar GP, assume diag inputs\n \"RF-scalar-diagin\", # diagonalize, train scalar RF, assume diag inputs (most comparable to GP)\n \"RF-scalar\", # diagonalize, train scalar RF, do not asume diag inputs\n \"RF-vector-svd-diag\",\n \"RF-vector-svd-nondiag\",\n \"RF-vector-nosvd-diag\",\n \"RF-vector-nosvd-nondiag\",\n \"RF-vector-svd-nonsep\",\n]","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The first is for GP with GaussianProcesses.jl interface. The next two are for the scalar RF interface, which most closely follows exactly replacing a GP. The rest are examples of vector RF with different types of data processing, (svd = same processing as scalar RF, nosvd = unprocessed) and different RF kernel structures in the output space of increasing complexity/flexibility (diag = Separable diagonal, nondiag = Separable nondiagonal, nonsep = nonseparable nondiagonal).","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The example then loads the relevant training data that was constructed in the calibrate.jl call. ","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"# loading relevant data\nhomedir = pwd()\nprintln(homedir)\nfigure_save_directory = joinpath(homedir, \"output/\")\ndata_save_directory = joinpath(homedir, \"output/\")\ndata_save_file = joinpath(data_save_directory, \"calibrate_results.jld2\")\nekiobj = load(data_save_file)[\"eki\"]\npriors = load(data_save_file)[\"priors\"]\ntruth_sample_mean = load(data_save_file)[\"truth_sample_mean\"]\ntruth_sample = load(data_save_file)[\"truth_sample\"]\ntruth_params_constrained = load(data_save_file)[\"truth_input_constrained\"] #true parameters in constrained space\ntruth_params = transform_constrained_to_unconstrained(priors, truth_params_constrained)\nΓy = ekiobj.obs_noise_cov","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"We then set up the structure of the emulator. An example for GP (GP)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"gppackage = Emulators.GPJL()\npred_type = Emulators.YType()\nmlt = GaussianProcess(\n gppackage;\n kernel = nothing, # use default squared exponential kernel\n prediction_type = pred_type,\n noise_learn = false,\n)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"which calls GaussianProcess.jl. In this L96 example, since we focus on learning F_s and A, we do not need to explicitly learn the noise, so noise_learn = false.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"An example for scalar RF (RF-scalar)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"n_features = 100\nkernel_structure = SeparableKernel(LowRankFactor(2, nugget), OneDimFactor())\nmlt = ScalarRandomFeatureInterface(\n n_features,\n n_params,\n rng = rng,\n kernel_structure = kernel_structure,\n optimizer_options = overrides,\n)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"Optimizer options for ScalarRandomFeature.jl are provided throough overrides","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"overrides = Dict(\n \"verbose\" => true,\n \"scheduler\" => DataMisfitController(terminate_at = 100.0),\n \"cov_sample_multiplier\" => 1.0,\n \"n_iteration\" => 20,\n )\n# we do not want termination, as our priors have relatively little interpretation","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"We then build the emulator with the parameters as defined above","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"emulator = Emulator(\n mlt,\n input_output_pairs;\n obs_noise_cov = Γy,\n normalize_inputs = normalized,\n standardize_outputs = standardize,\n standardize_outputs_factors = norm_factor,\n retained_svd_frac = retained_svd_frac,\n decorrelate = decorrelate,\n )","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"For RF and some GP packages, the training occurs during construction of the Emulator, however sometimes one must call an optimize step afterwards","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"optimize_hyperparameters!(emulator)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The emulator is checked for accuracy by evaluating its predictions on the true parameters","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"# Check how well the Gaussian Process regression predicts on the\n# true parameters\ny_mean, y_var = Emulators.predict(emulator, reshape(truth_params, :, 1), transform_to_real = true)\ny_mean_test, y_var_test = Emulators.predict(emulator, get_inputs(input_output_pairs_test), transform_to_real = true)\n\nprintln(\"ML prediction on true parameters: \")\nprintln(vec(y_mean))\nprintln(\"true data: \")\nprintln(truth_sample) # what was used as truth\nprintln(\" ML predicted standard deviation\")\nprintln(sqrt.(diag(y_var[1], 0)))\nprintln(\"ML MSE (truth): \")\nprintln(mean((truth_sample - vec(y_mean)) .^ 2))\nprintln(\"ML MSE (next ensemble): \")\nprintln(mean((get_outputs(input_output_pairs_test) - y_mean_test) .^ 2))","category":"page"},{"location":"examples/lorenz_example/#Sample","page":"Lorenz example","title":"Sample","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"Now the emulator is constructed and validated, so we next focus on the MCMC sampling. First, we run a short chain (2000 steps) to determine the step size","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"# First lets run a short chain to determine a good step size\nmcmc = MCMCWrapper(RWMHSampling(), truth_sample, priors, emulator; init_params = u0)\nnew_step = optimize_stepsize(mcmc; init_stepsize = 0.1, N = 2000, discard_initial = 0)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The step size has been determined, so now we run the full MCMC (100000 steps where the first 2000 are discarded)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"# Now begin the actual MCMC\nprintln(\"Begin MCMC - with step size \", new_step)\nchain = MarkovChainMonteCarlo.sample(mcmc, 100_000; stepsize = new_step, discard_initial = 2_000)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"And we finish by extracting the posterior samples","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"posterior = MarkovChainMonteCarlo.get_posterior(mcmc, chain)","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"And evaluate the results with these printed statements","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"post_mean = mean(posterior)\npost_cov = cov(posterior)\nprintln(\"post_mean\")\nprintln(post_mean)\nprintln(\"post_cov\")\nprintln(post_cov)\nprintln(\"D util\")\nprintln(det(inv(post_cov)))\nprintln(\" \")","category":"page"},{"location":"examples/lorenz_example/#Running-the-Example-and-Postprocessing","page":"Lorenz example","title":"Running the Example and Postprocessing","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"First, the calibrate code must be executed, which will perform the calibration step and, generating input-output pairs of the parameter to data mapping. Then, the emulate-sample code is run, which will load the input-ouput pairs that were generated in the calibration step.","category":"page"},{"location":"examples/lorenz_example/#Calibrate-2","page":"Lorenz example","title":"Calibrate","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The L96 parameter calibration can be run using julia --project calibrate.jl","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The output will provide the estimated parameters in the constrained ϕ-space. The priors are required in the get-method to apply these constraints.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"Printed output:","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"# EKI results: Has the ensemble collapsed toward the truth?\nprintln(\"True parameters: \")\nprintln(params_true)\nprintln(\"\\nEKI results:\")\nprintln(get_ϕ_mean_final(priors, ekiobj))","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The parameters and forward model outputs will be saved in parameter_storage.jld2 and data_storage.jld2, respectively. The data will be saved in the directory output. A scatter plot animation of the ensemble convergence to the true parameters is saved in the directory output. These points represent the training points that are used for the emulator.","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"","category":"page"},{"location":"examples/lorenz_example/#Emulate-sample","page":"Lorenz example","title":"Emulate-sample","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The L96 parameter estimation can be run using julia --project emulate_sample.jl","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The output will provide the estimated posterior distribution over the parameters. The emulate-sample code will run for several choices in the machine learning model that is used for the emulation stage, inclding Gaussian Process regression and RF, and using singular value data decorrelation or not. ","category":"page"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"The sampling results from two emulators are shown below. We can see that the posterior is relatively insensitive to the choice of the machine learning emulation tool in this L96 example.","category":"page"},{"location":"examples/lorenz_example/#L96-CES-example-case:-GP-regression-emulator-(case\"GP\")","page":"Lorenz example","title":"L96 CES example case: GP regression emulator (case=\"GP\")","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"","category":"page"},{"location":"examples/lorenz_example/#L96-CES-example-case:-RF-scalar-emulator-(case\"RF-scalar\")","page":"Lorenz example","title":"L96 CES example case: RF scalar emulator (case=\"RF-scalar\")","text":"","category":"section"},{"location":"examples/lorenz_example/","page":"Lorenz example","title":"Lorenz example","text":"","category":"page"},{"location":"examples/emulators/regression_2d_2d/#Regression-of-\\mathbb{R}2-\\to-\\mathbb{R}2-smooth-function","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"","category":"section"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"info: How do I run this code?\nThe full code is found in the examples/Emulator/ directory of the github repository","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"In this example, we assess directly the performance of our machine learning emulators. The task is to learn the function:","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"Gcolon 02pi^2 to mathbbR^2 G(x_1x_2) = (sin(x_1) + cos(x_2) sin(x_1) - cos(x_2)) ","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"observed at 150 points, subject to additive (and possibly correlated) Gaussian noise N(0Sigma).","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We have several different emulator configurations in this example that the user can play around with. The goal of this example is to predict the function (i.e. posterior mean) and uncertainty (i.e posterior pointwise variance) on a 200times200 grid providing a mean square error between emulated and true function and with plot_flag = true we also save several plots.","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We will term scalar-output Gaussin process emulator as \"GP\", scalar-output random feature emulator as \"scalar RF\", and vector-output random feature emulator as \"vector RF\" henceforth.","category":"page"},{"location":"examples/emulators/regression_2d_2d/#Walkthrough-of-the-code","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Walkthrough of the code","text":"","category":"section"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We first import some standard packages","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"using Random\nusing StableRNGs\nusing Distributions\nusing Statistics\nusing LinearAlgebra","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"and relevant CES packages needed to define the emulators, packages and kernel structures","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"using CalibrateEmulateSample.Emulators\n# Contains `Emulator`, `GaussianProcess`, `ScalarRandomFeatureInterface`, `VectorRandomFeatureInterface`\n# `GPJL`, `SKLJL`, `SeparablKernel`, `NonSeparableKernel`, `OneDimFactor`, `LowRankFactor`, `DiagonalFactor`\nusing CalibrateEmulateSample.DataContainers # Contains `PairedDataContainer`","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"To play with the hyperparameter optimization of RF, the optimizer options sometimes require EnsembleKalmanProcesses.jl structures, so we load this too","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"using CalibrateEmulateSample.EnsembleKalmanProcesses # Contains `DataMisfitController`","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We have 9 cases that the user can toggle or customize","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"cases = [\n \"gp-skljl\",\n \"gp-gpjl\", # Very slow prediction...\n \"rf-scalar\",\n \"rf-svd-diag\",\n \"rf-svd-nondiag\",\n \"rf-nosvd-diag\",\n \"rf-nosvd-nondiag\",\n \"rf-svd-nonsep\",\n \"rf-nosvd-nonsep\",\n]","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"The first two are for GP with either ScikitLearn.jl or GaussianProcesses.jl interface. The third is for the scalar RF interface, which most closely follows exactly replacing a GP. The rest are examples of vector RF with different types of data processing, (svd = same processing as scalar RF, nosvd = unprocessed) and different RF kernel structures in the output space of increasing complexity/flexibility (diag = Separable diagonal, nondiag = Separable nondiagonal, nonsep = nonseparable nondiagonal).","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We set up the learning problem specification, defining input and output dimensions, and number of data to train on, and the function g and the perturbed samples y with correlated additive noise","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"n = 150 # number of training points\np = 2 # input dim \nd = 2 # output dim\nX = 2.0 * π * rand(p, n)\n# G(x1, x2)\ng1x = sin.(X[1, :]) .+ cos.(X[2, :])\ng2x = sin.(X[1, :]) .- cos.(X[2, :])\ngx = zeros(2, n)\ngx[1, :] = g1x\ngx[2, :] = g2x\n# Add noise η\nμ = zeros(d)\nΣ = 0.1 * [[0.8, 0.1] [0.1, 0.5]] # d x d\nnoise_samples = rand(MvNormal(μ, Σ), n)\n# y = G(x) + η\nY = gx .+ noise_samples","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We then enter this in a paired data container, which gives a standard of how the data will be read","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"iopairs = PairedDataContainer(X, Y, data_are_columns = true)","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We define some common settings for all emulators, e.g. the number of random features to use, and some hyperparameter optimizer options","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"# common Gaussian feature setup\npred_type = YType()\n\n# common random feature setup\nn_features = 150\noptimizer_options = Dict(\"n_iteration\" => 10, \"scheduler\" => DataMisfitController(on_terminate = \"continue\"))\nnugget = 1e-12","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We then build the emulators. An example for GP (gp-skljl)","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"# use scikit learn\ngppackage = SKLJL()\n# build a GP that learns an additional white noise kernel (along with the default RBF kernel)\ngaussian_process = GaussianProcess(gppackage, noise_learn = true)\n# the data processing normalizes input data, and decorrelates output data with information from Σ\nemulator = Emulator(gaussian_process, iopairs, obs_noise_cov = Σ, normalize_inputs = true) ","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"An example for scalar RF (rf-scalar)","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"# build a scalar RF with a rank-2 kernel in input space (placeholder 1D kernel in output space) and use the optimizer options during training\nsrfi = ScalarRandomFeatureInterface(\n n_features, \n p, \n kernel_structure = SeparableKernel(LowRankFactor(2, nugget), OneDimFactor()), \n optimizer_options = optimizer_options,\n)\n# the data processing normalizes input data, and decorrelates output data with information from Σ\nemulator = Emulator(srfi, iopairs, obs_noise_cov = Σ, normalize_inputs = true)","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"An example for vector RF (rf-nosvd-nonsep)","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"# build a vector RF with a rank-4 nonseparable kernel and use the optimizer options during training\nvrfi = VectorRandomFeatureInterface(\n n_features,\n p,\n d, # additionally provide the output dimensions size\n kernel_structure = NonseparableKernel(LowRankFactor(4, nugget)),\n optimizer_options = optimizer_options,\n)\n# the data processing normalizes input data, and does not decorrelate outputs\nemulator = Emulator(vrfi, iopairs, obs_noise_cov = Σ, normalize_inputs = true, decorrelate = false)","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"For RF and some GP packages, the training occurs during construction of the Emulator, however sometimes one must call an optimize step afterwards","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"optimize_hyperparameters!(emulator)","category":"page"},{"location":"examples/emulators/regression_2d_2d/#Validation-and-Plots","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Validation and Plots","text":"","category":"section"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We create an evaluation grid for our models, in the right shape:","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"n_pts = 200\nx1 = range(0.0, stop = 2 * π, length = n_pts)\nx2 = range(0.0, stop = 2 * π, length = n_pts)\nX1, X2 = meshgrid(x1, x2)\ninputs = permutedims(hcat(X1[:], X2[:]), (2, 1))","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We predict using the emulators at the new inputs, and transform_to_real inverts the data processing back to physical values","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"em_mean, em_cov = predict(emulator, inputs, transform_to_real = true)","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"We then plot the predicted mean and pointwise variances, and calculate the errors from the three highlighted cases:","category":"page"},{"location":"examples/emulators/regression_2d_2d/#Gaussian-Process-Emulator-(Sci-kit-learn:-gp-skljl)","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Gaussian Process Emulator (Sci-kit learn: gp-skljl)","text":"","category":"section"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"L^2 error of mean and latent truth:0.0008042391077774167","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"\n","category":"page"},{"location":"examples/emulators/regression_2d_2d/#Random-Feature-Emulator-(rf-scalar)","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Random Feature Emulator (rf-scalar)","text":"","category":"section"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"L^2 error of mean and latent truth:0.0012253119679379056","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"\n","category":"page"},{"location":"examples/emulators/regression_2d_2d/#Random-Feature-Emulator-(vector:-rf-nosvd-nonsep)","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Random Feature Emulator (vector: rf-nosvd-nonsep)","text":"","category":"section"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"L^2 error of mean and latent truth:0.0011094292509180393","category":"page"},{"location":"examples/emulators/regression_2d_2d/","page":"Regression of mathbbR^2 to mathbbR^2 smooth function","title":"Regression of mathbbR^2 to mathbbR^2 smooth function","text":"\n","category":"page"},{"location":"GaussianProcessEmulator/#Gaussian-Process-Emulator","page":"Gaussian Process","title":"Gaussian Process Emulator","text":"","category":"section"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"One type of MachineLearningTool we provide for emulation is a Gaussian process. Gaussian processes are a generalization of the Gaussian probability distribution, extended to functions rather than random variables. They can be used for statistical emulation, as they provide both mean and covariances. To build a Gaussian process, we first define a prior over all possible functions, by choosing the covariance function or kernel. The kernel describes how similar two outputs (y_i, y_j) are, given the similarities between their input values (x_i, x_j). Kernels encode the functional form of these relationships and are defined by hyperparameters, which are usually initially unknown to the user. To learn the posterior Gaussian process, we condition on data using Bayes theorem and optimize the hyperparameters of the kernel. Then, we can make predictions to predict a mean function and covariance for new data points.","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"A useful resource to learn about Gaussian processes is Rasmussen and Williams (2006).","category":"page"},{"location":"GaussianProcessEmulator/#User-Interface","page":"Gaussian Process","title":"User Interface","text":"","category":"section"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"CalibrateEmulateSample.jl allows the Gaussian process emulator to be built using either GaussianProcesses.jl or ScikitLearn.jl. Different packages may be optimized for different settings, we recommend users give both a try, and checkout the individual package documentation to make a choice for their problem setting. ","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"To use GaussianProcesses.jl, define the package type as","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"gppackage = Emulators.GPJL()","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"To use ScikitLearn.jl, define the package type as","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"gppackage = Emulators.SKLJL()","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"Initialize a basic Gaussian Process with","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"gauss_proc = GaussianProcess(gppackage)","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"This initializes the prior Gaussian process. We train the Gaussian process by feeding the gauss_proc alongside the data into the Emulator struct and optimizing the hyperparameters, described here.","category":"page"},{"location":"GaussianProcessEmulator/#Prediction-Type","page":"Gaussian Process","title":"Prediction Type","text":"","category":"section"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"You can specify the type of prediction when initializing the Gaussian Process emulator. The default type of prediction is to predict data, YType(). You can create a latent function type prediction with","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"gauss_proc = GaussianProcess(\n gppackage,\n prediction_type = FType())\n","category":"page"},{"location":"GaussianProcessEmulator/#Kernels","page":"Gaussian Process","title":"Kernels","text":"","category":"section"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"The Gaussian process above assumes the default kernel: the Squared Exponential kernel, also called the Radial Basis Function (RBF). A different type of kernel can be specified when the Gaussian process is initialized. Read more about kernel options here.","category":"page"},{"location":"GaussianProcessEmulator/#GPJL","page":"Gaussian Process","title":"GPJL","text":"","category":"section"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"For the GaussianProcess.jl package, there are a range of kernels to choose from. For example, ","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"using GaussianProcesses\nmy_kernel = GaussianProcesses.Mat32Iso(0., 0.) # Create a Matern 3/2 kernel with lengthscale=0 and sd=0\ngauss_proc = GaussianProcess(\n gppackage;\n kernel = my_kernel )","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"You do not need to provide useful hyperparameter values when you define the kernel, as these are learned in optimize_hyperparameters!(emulator).","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"You can also combine kernels together through linear operations, for example,","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"using GaussianProcesses\nkernel_1 = GaussianProcesses.Mat32Iso(0., 0.) # Create a Matern 3/2 kernel with lengthscale=0 and sd=0\nkernel_2 = GaussianProcesses.Lin(0.) # Create a linear kernel with lengthscale=0\nmy_kernel = kernel_1 + kernel_2 # Create a new additive kernel\ngauss_proc = GaussianProcess(\n gppackage;\n kernel = my_kernel )","category":"page"},{"location":"GaussianProcessEmulator/#SKLJL","page":"Gaussian Process","title":"SKLJL","text":"","category":"section"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"Alternatively if you are using the ScikitLearn.jl package, you can find the list of kernels here. These need this preamble:","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"using PyCall\nusing ScikitLearn\nconst pykernels = PyNULL()\nfunction __init__()\n copy!(pykernels, pyimport(\"sklearn.gaussian_process.kernels\"))\nend","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"Then they are accessible, for example, as","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"my_kernel = pykernels.RBF(length_scale = 1)\ngauss_proc = GaussianProcess(\n gppackage;\n kernel = my_kernel )","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"You can also combine multiple ScikitLearn kernels via linear operations in the same way as above.","category":"page"},{"location":"GaussianProcessEmulator/#Learning-additional-white-noise","page":"Gaussian Process","title":"Learning additional white noise","text":"","category":"section"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"Often it is useful to learn the discrepancy between the Gaussian process prediction and the data, by learning additional white noise. Though one often knows, and provides, the discrepancy between the true model and data with an observational noise covariance; the additional white kernel can help account for approximation error from the selected Gaussian process kernel and the true model. This is added with the Boolean keyword noise_learn when initializing the Gaussian process. The default is true. ","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"gauss_proc = GaussianProcess(\n gppackage;\n noise_learn = true )","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"When noise_learn is true, an additional white noise kernel is added to the kernel. This white noise is present across all parameter values, including the training data. The scale parameters of the white noise kernel are learned in optimize_hyperparameters!(emulator). ","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"You may not need to learn the noise if you already have a good estimate of the noise from your training data, and if the Gaussian process kernel is well specified. When noise_learn is false, a small additional regularization is added for stability. The default value is 1e-3 but this can be chosen through the optional argument alg_reg_noise:","category":"page"},{"location":"GaussianProcessEmulator/","page":"Gaussian Process","title":"Gaussian Process","text":"gauss_proc = GaussianProcess(\n gppackage;\n noise_learn = false,\n alg_reg_noise = 1e-3 )","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/#Integrating-Lorenz-63-with-an-emulated-integrator","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"","category":"section"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"info: How do I run this code?\nThe full code is found in the examples/Emulator/ directory of the github repository","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"In this example, we assess directly the performance of our machine learning emulators. The task is to learn the forward Euler integrator of a Lorenz 63 system. The model parameters are set to their classical settings (sigma rho beta) = (1028frac83) to exhibit chaotic behavior. The discrete system is given as:","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"beginaligned\nx(t_n+1) = x(t_n) + Delta t(y(t_n) - x(t_n))\ny(t_n+1) = y(t_n) + Delta t(x(t_n)(28 - z(t_n)) - y(t_n))\nz(t_n+1) = z(t_n) + Delta t(x(t_n)y(t_n) - frac83z(t_n))\nendaligned","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"where t_n = nDelta t. The data consists of pairs (x(t_k)y(t_k)z(t_k)) (x(t_k+1)y(t_k+1)z(t_k+1)+eta_k for 600 values of k, with each output subjected to independent, additive Gaussian noise eta_ksim N(0Gamma_y).","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"We have several different emulator configurations in this example that the user can play around with. The goal of the emulator is that the posterior mean will approximate this discrete update map, or integrator, for any point on the Lorenz attractor from the sparse noisy data. To validate this, we recursively apply the trained emulator to the state, plotting the evolution of the trajectory and marginal statistics of the states over short and long timescales. We include a repeats option (n_repeats) to run the randomized training for multiple trials and illustrate robustness of marginal statistics by plotting long time marginal cdfs of the state. ","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"We will term scalar-output Gaussin process emulator as \"GP\", and scalar- or vector-output random feature emulator as \"RF\".","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/#Walkthrough-of-the-code","page":"Integrating Lorenz 63 with an emulated integrator","title":"Walkthrough of the code","text":"","category":"section"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"We first import some standard packages","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"using Random, Distributions, LinearAlgebra # utilities\nusing CairoMakie, ColorSchemes # for plots\nusing JLD2 # for saved data","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"For the true integrator of the Lorenz system we import","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"using OrdinaryDiffEq ","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"For relevant CES packages needed to define the emulators, packages and kernel structures","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"using CalibrateEmulateSample.Emulators\n# Contains `Emulator`, `GaussianProcess`, `ScalarRandomFeatureInterface`, `VectorRandomFeatureInterface`\n# `GPJL`, `SeparablKernel`, `NonSeparableKernel`, `OneDimFactor`, `LowRankFactor`, `DiagonalFactor`\nusing CalibrateEmulateSample.DataContainers # Contains `PairedDataContainer`","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"and if one wants to play with optimizer options for the random feature emulators we import","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"using CalibrateEmulateSample.EnsembleKalmanProcesses # Contains `DataMisfitController`","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"We generate the truth data using OrdinaryDiffEq: the time series sol is used for training data, sol_test is used for plotting short time trajectories, and sol_hist for plotting histograms of the state over long times:","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"# Run L63 from 0 -> tmax\nu0 = [1.0; 0.0; 0.0]\ntmax = 20\ndt = 0.01\ntspan = (0.0, tmax)\nprob = ODEProblem(lorenz, u0, tspan)\nsol = solve(prob, Euler(), dt = dt)\n\n# Run L63 from end for test trajectory data\ntmax_test = 100\ntspan_test = (0.0, tmax_test)\nu0_test = sol.u[end]\nprob_test = ODEProblem(lorenz, u0_test, tspan_test)\nsol_test = solve(prob_test, Euler(), dt = dt)\n\n# Run L63 from end for histogram matching data\ntmax_hist = 1000\ntspan_hist = (0.0, tmax_hist)\nu0_hist = sol_test.u[end]\nprob_hist = ODEProblem(lorenz, u0_hist, tspan_hist)\nsol_hist = solve(prob_hist, Euler(), dt = dt)","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"We generate the training data from sol within [tburn, tmax]. The user has the option of how many training points to take n_train_pts and whether these are selected randomly or sequentially (sample_rand). The true outputs are perturbed by noise of variance 1e-4 and pairs are stored in the compatible data format PairedDataContainer","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"tburn = 1 # NB works better with no spin-up!\nburnin = Int(floor(tburn / dt))\nn_train_pts = 600 \nsample_rand = true\nif sample_rand\n ind = Int.(shuffle!(rng, Vector(burnin:(tmax / dt - 1)))[1:n_train_pts])\nelse\n ind = burnin:(n_train_pts + burnin)\nend\nn_tp = length(ind)\ninput = zeros(3, n_tp)\noutput = zeros(3, n_tp)\nΓy = 1e-4 * I(3)\nnoise = rand(rng, MvNormal(zeros(3), Γy), n_tp)\nfor i in 1:n_tp\n input[:, i] = sol.u[ind[i]]\n output[:, i] = sol.u[ind[i] + 1] + noise[:, i]\nend\niopairs = PairedDataContainer(input, output)","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"We have several cases the user can play with,","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"cases = [\"GP\", \"RF-scalar\", \"RF-scalar-diagin\", \"RF-svd-nonsep\", \"RF-nosvd-nonsep\", \"RF-nosvd-sep\"]","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"Then, looping over the repeats, we first define some common hyperparamter optimization options for the \"RF-\" cases. In this case, the options are used primarily for diagnostics and acceleration (not required in general to solve this problem) ","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"rf_optimizer_overrides = Dict(\n \"verbose\" => true, # output diagnostics from the hyperparameter optimizer\n \"scheduler\" => DataMisfitController(terminate_at = 1e4), # timestepping method for the optimizer\n \"cov_sample_multiplier\" => 0.5, # 0.5*default number of samples to estimate covariances in optimizer\n \"n_features_opt\" => 200, # number of features during hyperparameter optimization\n \"n_iteration\" => 20, # iterations of the optimizer solver\n)","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"Then we build the machine learning tools. Here we highlight scalar-output Gaussian process (GP), where we use the default squared-exponential kernel, and learn a lengthscale hyperparameter in each input dimension. To handle multiple outputs, we will use a decorrelation in the output space, and so will actually train three of these models.","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"gppackage = Emulators.GPJL() # use GaussianProcesses.jl\npred_type = Emulators.YType() # predicted variances are for data not latent function\nmlt = GaussianProcess(\n gppackage;\n prediction_type = pred_type,\n noise_learn = false, # do not additionally learn a white kernel\n)","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"we also highlight the Vector Random Feature with nonseparable kernel (RF-nosvd-nonsep), this can natively handle multiple outputs without decorrelation of the output space. This kernel is a rank-3 representation with small nugget term.","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"nugget = 1e-12\nkernel_structure = NonseparableKernel(LowRankFactor(3, nugget))\nn_features = 500 # number of features for prediction\nmlt = VectorRandomFeatureInterface(\n n_features,\n 3, # input dimension\n 3, # output dimension\n rng = rng, # pin random number generator\n kernel_structure = kernel_structure,\n optimizer_options = rf_optimizer_overrides, \n) ","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"With machine learning tools specified, we build the emulator object","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"# decorrelate = true for `GP`\n# decorrelate = false for `RF-nosvd-nonsep`\nemulator = Emulator(mlt, iopairs; obs_noise_cov = Γy, decorrelate = decorrelate) \noptimize_hyperparameters!(emulator) # some GP packages require this additional call ","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/#Plots","page":"Integrating Lorenz 63 with an emulated integrator","title":"Plots","text":"","category":"section"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"We predict the trained emulator mean, over the short-timescale validation trajectory","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"u_test_tmp = zeros(3, length(xspan_test))\nu_test_tmp[:, 1] = sol_test.u[1] # initialize at the final-time solution of the training period\n\nfor i in 1:(length(xspan_test) - 1)\n rf_mean, _ = predict(emulator, u_test_tmp[:, i:i], transform_to_real = true) # 3x1 matrix\n u_test_tmp[:, i + 1] = rf_mean\nend","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"The other trajectories are similar. We then produce the following plots. In all figures, the results from evolving the state with the true integrator is orange, and with the emulated integrators are blue.","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/#Gaussian-Process-Emulator-(Sci-kit-learn:-GP)","page":"Integrating Lorenz 63 with an emulated integrator","title":"Gaussian Process Emulator (Sci-kit learn: GP)","text":"","category":"section"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"For one example fit","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"\n","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/#Random-Feature-Emulator-(RF-nosvd-nonsep)","page":"Integrating Lorenz 63 with an emulated integrator","title":"Random Feature Emulator (RF-nosvd-nonsep)","text":"","category":"section"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"For one example fit","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"\n","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"and here are CDFs over 20 randomized trials of the random feature hyperparameter optimization","category":"page"},{"location":"examples/emulators/lorenz_integrator_3d_3d/","page":"Integrating Lorenz 63 with an emulated integrator","title":"Integrating Lorenz 63 with an emulated integrator","text":"","category":"page"},{"location":"API/GaussianProcess/#GaussianProcess","page":"Gaussian Process","title":"GaussianProcess","text":"","category":"section"},{"location":"API/GaussianProcess/","page":"Gaussian Process","title":"Gaussian Process","text":"CurrentModule = CalibrateEmulateSample.Emulators","category":"page"},{"location":"API/GaussianProcess/","page":"Gaussian Process","title":"Gaussian Process","text":"GaussianProcessesPackage\nPredictionType\nGaussianProcess\nGaussianProcess(\n ::GPPkg;\n ::Union{K, KPy, Nothing},\n ::Any,\n ::FT,\n ::PredictionType,\n) where {GPPkg <: GaussianProcessesPackage, K <: Kernel, KPy <: PyObject, FT <: AbstractFloat}\nbuild_models!(::GaussianProcess{GPJL}, ::PairedDataContainer{FT}) where {FT <: AbstractFloat}\noptimize_hyperparameters!(::GaussianProcess{GPJL})\npredict(::GaussianProcess{GPJL}, ::AbstractMatrix{FT}) where {FT <: AbstractFloat}","category":"page"},{"location":"API/GaussianProcess/#CalibrateEmulateSample.Emulators.GaussianProcessesPackage","page":"Gaussian Process","title":"CalibrateEmulateSample.Emulators.GaussianProcessesPackage","text":"abstract type GaussianProcessesPackage\n\nType to dispatch which GP package to use:\n\nGPJL for GaussianProcesses.jl,\nSKLJL for the ScikitLearn GaussianProcessRegressor.\n\n\n\n\n\n","category":"type"},{"location":"API/GaussianProcess/#CalibrateEmulateSample.Emulators.PredictionType","page":"Gaussian Process","title":"CalibrateEmulateSample.Emulators.PredictionType","text":"abstract type PredictionType\n\nPredict type for GPJL in GaussianProcesses.jl:\n\nYType\nFType latent function.\n\n\n\n\n\n","category":"type"},{"location":"API/GaussianProcess/#CalibrateEmulateSample.Emulators.GaussianProcess","page":"Gaussian Process","title":"CalibrateEmulateSample.Emulators.GaussianProcess","text":"struct GaussianProcess{GPPackage, FT} <: CalibrateEmulateSample.Emulators.MachineLearningTool\n\nStructure holding training input and the fitted Gaussian process regression models.\n\nFields\n\nmodels::Vector{Union{Nothing, PyCall.PyObject, GaussianProcesses.GPE}}: The Gaussian Process (GP) Regression model(s) that are fitted to the given input-data pairs.\nkernel::Union{Nothing, var\"#s17\", var\"#s18\"} where {var\"#s17\"<:GaussianProcesses.Kernel, var\"#s18\"<:PyCall.PyObject}: Kernel object.\nnoise_learn::Bool: Learn the noise with the White Noise kernel explicitly?\nalg_reg_noise::Any: Additional observational or regularization noise in used in GP algorithms\nprediction_type::CalibrateEmulateSample.Emulators.PredictionType: Prediction type (y to predict the data, f to predict the latent function).\n\n\n\n\n\n","category":"type"},{"location":"API/GaussianProcess/#CalibrateEmulateSample.Emulators.GaussianProcess-Union{Tuple{FT}, Tuple{KPy}, Tuple{K}, Tuple{GPPkg}} where {GPPkg<:CalibrateEmulateSample.Emulators.GaussianProcessesPackage, K<:GaussianProcesses.Kernel, KPy<:PyCall.PyObject, FT<:AbstractFloat}","page":"Gaussian Process","title":"CalibrateEmulateSample.Emulators.GaussianProcess","text":"GaussianProcess(\n package::AbstractFloat;\n kernel,\n noise_learn,\n alg_reg_noise,\n prediction_type\n)\n\n\npackage - GaussianProcessPackage object.\nkernel - GaussianProcesses kernel object. Default is a Squared Exponential kernel.\nnoise_learn - Boolean to additionally learn white noise in decorrelated space. Default is true.\nalg_reg_noise - Float to fix the (small) regularization parameter of algorithms when noise_learn = true\nprediction_type - PredictionType object. Default predicts data, not latent function (FType()).\n\n\n\n\n\n","category":"method"},{"location":"API/GaussianProcess/#CalibrateEmulateSample.Emulators.build_models!-Union{Tuple{FT}, Tuple{CalibrateEmulateSample.Emulators.GaussianProcess{CalibrateEmulateSample.Emulators.GPJL}, EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT}}} where FT<:AbstractFloat","page":"Gaussian Process","title":"CalibrateEmulateSample.Emulators.build_models!","text":"build_models!(\n gp::CalibrateEmulateSample.Emulators.GaussianProcess{CalibrateEmulateSample.Emulators.GPJL},\n input_output_pairs::EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT<:AbstractFloat}\n)\n\n\nMethod to build Gaussian process models based on the package.\n\n\n\n\n\n","category":"method"},{"location":"API/GaussianProcess/#CalibrateEmulateSample.Emulators.optimize_hyperparameters!-Tuple{CalibrateEmulateSample.Emulators.GaussianProcess{CalibrateEmulateSample.Emulators.GPJL}}","page":"Gaussian Process","title":"CalibrateEmulateSample.Emulators.optimize_hyperparameters!","text":"optimize_hyperparameters!(\n gp::CalibrateEmulateSample.Emulators.GaussianProcess{CalibrateEmulateSample.Emulators.GPJL},\n args...;\n kwargs...\n)\n\n\nOptimize Gaussian process hyperparameters using in-build package method.\n\nWarning: if one uses GPJL() and wishes to modify positional arguments. The first positional argument must be the Optim method (default LBGFS()).\n\n\n\n\n\n","category":"method"},{"location":"API/GaussianProcess/#GaussianProcesses.predict-Union{Tuple{FT}, Tuple{CalibrateEmulateSample.Emulators.GaussianProcess{CalibrateEmulateSample.Emulators.GPJL}, AbstractMatrix{FT}}} where FT<:AbstractFloat","page":"Gaussian Process","title":"GaussianProcesses.predict","text":"predict(\n gp::CalibrateEmulateSample.Emulators.GaussianProcess{CalibrateEmulateSample.Emulators.GPJL},\n new_inputs::AbstractArray{FT<:AbstractFloat, 2}\n) -> Tuple{Any, Any}\n\n\nPredict means and covariances in decorrelated output space using Gaussian process models.\n\n\n\n\n\n","category":"method"},{"location":"sample/#The-Sample-stage","page":"Sample","title":"The Sample stage","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"CurrentModule = CalibrateEmulateSample.MarkovChainMonteCarlo","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"The \"sample\" part of CES refers to exact sampling from the emulated posterior, in our current framework this is achieved with a Markov chain Monte Carlo algorithm (MCMC). Within this paradigm, we want to provide the flexibility to use multiple sampling algorithms; the approach we take is to use the general-purpose AbstractMCMC.jl API, provided by the Turing.jl probabilistic programming framework.","category":"page"},{"location":"sample/#User-interface","page":"Sample","title":"User interface","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"We briefly outline an instance of how one sets up and uses MCMC within the CES package. The user first loads the MCMC module, and provides one of the Protocols (i.e. how one wishes to generate sampling proposals)","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"using CalibrateEmulateSample.MarkovChainMonteCarlo\nprotocol = RWMHSampling() # Random-Walk algorithm\n# protocol = pCNMHSampling() # preconditioned-Crank-Nicholson algorithm","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"Then one builds the MCMC by providing the standard Bayesian ingredients (prior and data) from the calibrate stage, alongside the trained statistical emulator from the emulate stage:","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"mcmc = MCMCWrapper(\n protocol,\n truth_sample, \n prior,\n emulator;\n init_params=mean_u_final,\n burnin=10_000,\n)","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"The keyword arguments init_params give a starting step of the chain (often taken to be the mean of the final iteration of calibrate stage), and a burnin gives a number of initial steps to be discarded when drawing statistics from the sampling method.","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"For good efficiency, one often needs to run MCMC with a problem-dependent step size. We provide a simple utility to help choose this. Here the optimizer runs short chains (of length N), and adjusts the step-size until the MCMC acceptance rate falls within an acceptable range, returning this step size.","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"new_step = optimize_stepsize(\nmcmc;\ninit_stepsize = 1,\nN = 2000\n)","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"To generate 10^5 samples with a given step size (and optional random number generator rng), one calls","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"chain = sample(rng, mcmc, 100_000; stepsize = new_step)\ndisplay(chain) # gives diagnostics","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"The return argument is stored in an MCMCChains.Chains object. To convert this back into a ParameterDistribution type (which contains e.g. the transformation maps) one can call","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"posterior = get_posterior(mcmc, chain)\nconstrained_posterior = transform_unconstrained_to_constrained(prior, get_distribution(posterior))","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"One can quickly plot the marginals of the prior and posterior distribution with","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"using Plots\nplot(prior)\nplot!(posterior)","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"or extract statistics of the (unconstrained) distribution with","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"mean_posterior = mean(posterior)\ncov_posterior = cov(posterior)","category":"page"},{"location":"sample/#AbstractMCMC-sampling-API","page":"Sample","title":"Further details on the implementation","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"This page provides a summary of AbstractMCMC which augments the existing documentation ([1], [2]) and highlights how it's used by the CES package in MarkovChainMonteCarlo. It's not meant to be a complete description of the AbstractMCMC package.","category":"page"},{"location":"sample/#Use-in-MarkovChainMonteCarlo","page":"Sample","title":"Use in MarkovChainMonteCarlo","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"At present, Turing has limited support for derivative-free optimization, so we only use this abstract API and not Turing itself. We also use two related dependencies, AdvancedMH and MCMCChains. ","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"Julia's philosophy is to use small, composable packages rather than monoliths, but this can make it difficult to remember where methods are defined! Below we describe the relevant parts of ","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"The AbstractMCMC API,\nExtended to the case of Metropolis-Hastings (MH) sampling by AdvancedMH,\nFurther extended for the needs of CES in Markov chain Monte Carlo.","category":"page"},{"location":"sample/#Sampler","page":"Sample","title":"Sampler","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"A Sampler is AbstractMCMC's term for an implementation of a MCMC sampling algorithm, along with all its configuration parameters. All samplers are a subtype of AbstractMCMC's AbstractSampler. ","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"Currently CES only implements the Metropolis-Hastings (MH) algorithm. Because it's so straightforward, much of AbstractMCMC isn't needed. We implement two variants of MH with two different Samplers: RWMetropolisHastings and pCNMetropolisHastings, both of which are subtypes of AdvancedMH.MHSampler. The constructor for both Samplers is MetropolisHastingsSampler; the different Samplers are specified by passing a MCMCProtocol object to this constructor.","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"The MHSampler has only one field, proposal, the distribution used to generate new MH proposals via additive stochastic perturbations to the current parameter values. This is done by AdvancedMH.propose(), which gets called for each MCMC step(). The difference between Samplers comes from how the proposal is generated:","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"RWMHSampling does vanilla random-walk proposal generation with a constant, user-specified step size (this differs from the AdvancedMH implementation, which doesn't provide for a step size.)\npCNMHSampling for preconditioned Crank-Nicholson proposals. Vanilla random walk sampling doesn't have a well-defined limit for high-dimensional parameter spaces; pCN replaces the random walk with an Ornstein–Uhlenbeck [AR(1)] process so that the Metropolis acceptance probability remains non-zero in this limit. See Beskos et. al. (2008) and Cotter et. al. (2013).","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"Generated proposals are then either accepted or rejected according to the same MH criterion (in step(), below.)","category":"page"},{"location":"sample/#Models","page":"Sample","title":"Models","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"In Turing, the Model is the distribution one performs inference on, which may involve observed and hidden variables and parameters. For CES, we simply want to sample from the posterior, so our Model distribution is simply the emulated likelihood (see Emulators) together with the prior. This is constructed by EmulatorPosteriorModel.","category":"page"},{"location":"sample/#Sampling-with-the-MCMC-Wrapper-object","page":"Sample","title":"Sampling with the MCMC Wrapper object","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"At a high level, a Sampler and Model is all that's needed to do MCMC sampling. This is done by the sample method provided by AbstractMCMC (extending the method from BaseStats). ","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"To be more user-friendly, in CES we wrap the Sampler, Model and other necessary configuration into a MCMCWrapper object. The constructor for this object ensures that all its components are created consistently, and performs necessary bookkeeping, such as converting coordinates to the decorrelated basis. We extend sample with methods to use this object (that simply unpack its fields and call the appropriate method from AbstractMCMC.)","category":"page"},{"location":"sample/#Chain","page":"Sample","title":"Chain","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"The MCMCChain package provides the Chains container to store the results of the MCMC sampling; the package provides methods to for quick diagnostics and plot utilities of the the Chains objects. For example,","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"using MCMCChains\nusing StatsPlots\n\n# ... from our MCMC example above ...\n# chain = sample(rng, mcmc, 100_000; stepsize = new_step)\n\ndisplay(chain) # diagnostics\nplot(chain) # plots samples over iteration and PDFs for each parameter","category":"page"},{"location":"sample/#Internals:-Transitions","page":"Sample","title":"Internals: Transitions","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"Implementing MCMC involves defining states and transitions of a Markov process (whose stationary distribution is what we seek to sample from). AbstractMCMC's terminology is a bit confusing for the MH case; states of the chain are described by Transition objects, which contain the current sample (and other information like its log-probability). ","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"AdvancedMH defines an AbstractTransition base class for use with its methods; we implement our own child class, MCMCState, in order to record statistics on the MH acceptance ratio.","category":"page"},{"location":"sample/#Internals:-Markov-steps","page":"Sample","title":"Internals: Markov steps","text":"","category":"section"},{"location":"sample/","page":"Sample","title":"Sample","text":"Markov transitions of the chain are defined by overloading AbstractMCMC's step method, which takes the Sampler and current Transition and implements the Sampler's logic to returns an updated Transition representing the chain's new state (actually, a pair of Transitions, for cases where the Sampler doesn't obey detailed balance; this isn't relevant for us). ","category":"page"},{"location":"sample/","page":"Sample","title":"Sample","text":"For example, in Metropolis-Hastings sampling this is where we draw a proposal sample and accept or reject it according to the MH criterion. AdvancedMH implements this here; we re-implement this method because 1) we need to record whether a proposal was accepted or rejected, and 2) our calls to propose() are stepsize-dependent.","category":"page"},{"location":"API/MarkovChainMonteCarlo/#MarkovChainMonteCarlo","page":"MarkovChainMonteCarlo","title":"MarkovChainMonteCarlo","text":"","category":"section"},{"location":"API/MarkovChainMonteCarlo/","page":"MarkovChainMonteCarlo","title":"MarkovChainMonteCarlo","text":"CurrentModule = CalibrateEmulateSample.MarkovChainMonteCarlo","category":"page"},{"location":"API/MarkovChainMonteCarlo/#Top-level-class-and-methods","page":"MarkovChainMonteCarlo","title":"Top-level class and methods","text":"","category":"section"},{"location":"API/MarkovChainMonteCarlo/","page":"MarkovChainMonteCarlo","title":"MarkovChainMonteCarlo","text":"MCMCWrapper\nMCMCWrapper(mcmc_alg::MCMCProtocol, obs_sample::AbstractVector{FT}, prior::ParameterDistribution, em::Emulator;init_params::AbstractVector{FT}, burnin::IT, kwargs...) where {FT<:AbstractFloat, IT<:Integer}\nsample\nget_posterior\noptimize_stepsize","category":"page"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCWrapper","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCWrapper","text":"struct MCMCWrapper\n\nTop-level class holding all configuration information needed for MCMC sampling: the prior, emulated likelihood and sampling algorithm (DensityModel and Sampler, respectively, in AbstractMCMC's terminology).\n\nFields\n\nprior::EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution: ParameterDistribution object describing the prior distribution on parameter values.\nlog_posterior_map::AbstractMCMC.AbstractModel: AdvancedMH.DensityModel object, used to evaluate the posterior density being sampled from.\nmh_proposal_sampler::AbstractMCMC.AbstractSampler: Object describing a MCMC sampling algorithm and its settings.\nsample_kwargs::NamedTuple: NamedTuple of other arguments to be passed to AbstractMCMC.sample().\n\n\n\n\n\n","category":"type"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCWrapper-Union{Tuple{IT}, Tuple{FT}, Tuple{CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCProtocol, AbstractVector{FT}, EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution, CalibrateEmulateSample.Emulators.Emulator}} where {FT<:AbstractFloat, IT<:Integer}","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCWrapper","text":"MCMCWrapper(\n mcmc_alg::CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCProtocol,\n obs_sample::AbstractArray{FT<:AbstractFloat, 1},\n prior::EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution,\n em::CalibrateEmulateSample.Emulators.Emulator;\n init_params,\n burnin,\n kwargs...\n)\n\n\nConstructor for MCMCWrapper which performs the same standardization (SVD decorrelation) that was applied in the Emulator. It creates and wraps an instance of EmulatorPosteriorModel, for sampling from the Emulator, and MetropolisHastingsSampler, for generating the MC proposals.\n\nmcmc_alg: MCMCProtocol describing the MCMC sampling algorithm to use. Currently implemented algorithms are:\nRWMHSampling: Metropolis-Hastings sampling from a vanilla random walk with fixed stepsize.\npCNMHSampling: Metropolis-Hastings sampling using the preconditioned Crank-Nicholson algorithm, which has a well-behaved small-stepsize limit.\nobs_sample: A single sample from the observations. Can, e.g., be picked from an Observation struct using get_obs_sample.\nprior: ParameterDistribution object containing the parameters' prior distributions.\nem: Emulator to sample from. \nstepsize: MCMC step size, applied as a scaling to the prior covariance.\ninit_params: Starting parameter values for MCMC sampling.\nburnin: Initial number of MCMC steps to discard from output (pre-convergence).\n\n\n\n\n\n","category":"method"},{"location":"API/MarkovChainMonteCarlo/#StatsBase.sample","page":"MarkovChainMonteCarlo","title":"StatsBase.sample","text":"sample([rng,] mcmc::MCMCWrapper, args...; kwargs...)\n\nExtends the sample methods of AbstractMCMC (which extends StatsBase) to sample from the emulated posterior, using the MCMC sampling algorithm and Emulator configured in MCMCWrapper. Returns a MCMCChains.Chains object containing the samples. \n\nSupported methods are:\n\nsample([rng, ]mcmc, N; kwargs...)\nReturn a MCMCChains.Chains object containing N samples from the emulated posterior.\nsample([rng, ]mcmc, isdone; kwargs...)\nSample from the model with the Markov chain Monte Carlo sampler until a convergence criterion isdone returns true, and return the samples. The function isdone has the signature\n isdone(rng, model, sampler, samples, state, iteration; kwargs...)\nwhere state and iteration are the current state and iteration of the sampler, respectively. It should return true when sampling should end, and false otherwise.\nsample([rng, ]mcmc, parallel_type, N, nchains; kwargs...)\nSample nchains Monte Carlo Markov chains in parallel according to parallel_type, which may be MCMCThreads() or MCMCDistributed() for thread and parallel sampling, respectively.\n\n\n\n\n\n","category":"function"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.get_posterior","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.get_posterior","text":"get_posterior(\n mcmc::CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCWrapper,\n chain::MCMCChains.Chains\n) -> EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution\n\n\nReturns a ParameterDistribution object corresponding to the empirical distribution of the samples in chain.\n\nnote: Note\nThis method does not currently support combining samples from multiple Chains.\n\n\n\n\n\n","category":"function"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.optimize_stepsize","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.optimize_stepsize","text":"optimize_stepsize(\n rng::Random.AbstractRNG,\n mcmc::CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCWrapper;\n init_stepsize,\n N,\n max_iter,\n sample_kwargs...\n) -> Float64\n\n\nUses a heuristic to return a stepsize for the mh_proposal_sampler element of MCMCWrapper which yields fast convergence of the Markov chain.\n\nThe criterion used is that Metropolis-Hastings proposals should be accepted between 15% and 35% of the time.\n\n\n\n\n\n","category":"function"},{"location":"API/MarkovChainMonteCarlo/","page":"MarkovChainMonteCarlo","title":"MarkovChainMonteCarlo","text":"See AbstractMCMC sampling API for background on our use of Turing.jl's AbstractMCMC API for MCMC sampling.","category":"page"},{"location":"API/MarkovChainMonteCarlo/#Sampler-algorithms","page":"MarkovChainMonteCarlo","title":"Sampler algorithms","text":"","category":"section"},{"location":"API/MarkovChainMonteCarlo/","page":"MarkovChainMonteCarlo","title":"MarkovChainMonteCarlo","text":"MCMCProtocol\nRWMHSampling\npCNMHSampling\nMetropolisHastingsSampler","category":"page"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCProtocol","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCProtocol","text":"abstract type MCMCProtocol\n\nType used to dispatch different methods of the MetropolisHastingsSampler constructor, corresponding to different sampling algorithms.\n\n\n\n\n\n","category":"type"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.RWMHSampling","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.RWMHSampling","text":"struct RWMHSampling <: CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCProtocol\n\nMCMCProtocol which uses Metropolis-Hastings sampling that generates proposals for new parameters as as vanilla random walk, based on the covariance of prior.\n\n\n\n\n\n","category":"type"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.pCNMHSampling","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.pCNMHSampling","text":"struct pCNMHSampling <: CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCProtocol\n\nMCMCProtocol which uses Metropolis-Hastings sampling that generates proposals for new parameters according to the preconditioned Crank-Nicholson (pCN) algorithm, which is usable for MCMC in the stepsize → 0 limit, unlike the vanilla random walk. Steps are based on the covariance of prior.\n\n\n\n\n\n","category":"type"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.MetropolisHastingsSampler","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.MetropolisHastingsSampler","text":"MetropolisHastingsSampler(\n _::CalibrateEmulateSample.MarkovChainMonteCarlo.RWMHSampling,\n prior::EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution\n) -> CalibrateEmulateSample.MarkovChainMonteCarlo.RWMetropolisHastings{D} where D<:(AdvancedMH.RandomWalkProposal{false})\n\n\nConstructor for all Sampler objects, with one method for each supported MCMC algorithm.\n\nwarning: Warning\nBoth currently implemented Samplers use a Gaussian approximation to the prior: specifically, new Metropolis-Hastings proposals are a scaled combination of the old parameter values and a random shift distributed as a Gaussian with the same covariance as the prior. This suffices for our current use case, in which our priors are Gaussian (possibly in a transformed space) and we assume enough fidelity in the Emulator that inference isn't prior-dominated.\n\n\n\n\n\n","category":"function"},{"location":"API/MarkovChainMonteCarlo/#Emulated-posterior-(Model)","page":"MarkovChainMonteCarlo","title":"Emulated posterior (Model)","text":"","category":"section"},{"location":"API/MarkovChainMonteCarlo/","page":"MarkovChainMonteCarlo","title":"MarkovChainMonteCarlo","text":"EmulatorPosteriorModel","category":"page"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.EmulatorPosteriorModel","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.EmulatorPosteriorModel","text":"EmulatorPosteriorModel(\n prior::EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution,\n em::CalibrateEmulateSample.Emulators.Emulator{FT<:AbstractFloat},\n obs_sample::AbstractArray{FT<:AbstractFloat, 1}\n) -> AdvancedMH.DensityModel{F} where F<:(CalibrateEmulateSample.MarkovChainMonteCarlo.var\"#1#2\"{EnsembleKalmanProcesses.ParameterDistributions.ParameterDistribution{PDType, CType, ST}, CalibrateEmulateSample.Emulators.Emulator{FT}, <:AbstractVector{FT1}} where {PDType<:EnsembleKalmanProcesses.ParameterDistributions.ParameterDistributionType, CType<:EnsembleKalmanProcesses.ParameterDistributions.ConstraintType, ST<:AbstractString, FT<:AbstractFloat, FT1<:AbstractFloat})\n\n\nFactory which constructs AdvancedMH.DensityModel objects given a prior on the model parameters (prior) and an Emulator of the log-likelihood of the data given parameters. Together these yield the log posterior density we're attempting to sample from with the MCMC, which is the role of the DensityModel class in the AbstractMCMC interface.\n\n\n\n\n\n","category":"function"},{"location":"API/MarkovChainMonteCarlo/#Internals-MCMC-State","page":"MarkovChainMonteCarlo","title":"Internals - MCMC State","text":"","category":"section"},{"location":"API/MarkovChainMonteCarlo/","page":"MarkovChainMonteCarlo","title":"MarkovChainMonteCarlo","text":"MCMCState\naccept_ratio","category":"page"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCState","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.MCMCState","text":"struct MCMCState{T, L<:Real} <: AdvancedMH.AbstractTransition\n\nExtends the AdvancedMH.Transition (which encodes the current state of the MC during sampling) with a boolean flag to record whether this state is new (arising from accepting a Metropolis-Hastings proposal) or old (from rejecting a proposal).\n\nFields\n\nparams::Any: Sampled value of the parameters at the current state of the MCMC chain.\nlog_density::Real: Log probability of params, as computed by the model using the prior.\naccepted::Bool: Whether this state resulted from accepting a new MH proposal.\n\n\n\n\n\n","category":"type"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.accept_ratio","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.accept_ratio","text":"accept_ratio(chain::MCMCChains.Chains) -> Any\n\n\nFraction of MC proposals in chain which were accepted (according to Metropolis-Hastings.)\n\n\n\n\n\n","category":"function"},{"location":"API/MarkovChainMonteCarlo/#Internals-Other","page":"MarkovChainMonteCarlo","title":"Internals - Other","text":"","category":"section"},{"location":"API/MarkovChainMonteCarlo/","page":"MarkovChainMonteCarlo","title":"MarkovChainMonteCarlo","text":"to_decorrelated","category":"page"},{"location":"API/MarkovChainMonteCarlo/#CalibrateEmulateSample.MarkovChainMonteCarlo.to_decorrelated","page":"MarkovChainMonteCarlo","title":"CalibrateEmulateSample.MarkovChainMonteCarlo.to_decorrelated","text":"to_decorrelated(\n data::AbstractArray{FT<:AbstractFloat, 2},\n em::CalibrateEmulateSample.Emulators.Emulator{FT<:AbstractFloat}\n) -> Any\n\n\nTransform samples from the original (correlated) coordinate system to the SVD-decorrelated coordinate system used by Emulator. Used in the constructor for MCMCWrapper.\n\n\n\n\n\n","category":"function"},{"location":"random_feature_emulator/#Random-Feature-Emulator","page":"Random Features","title":"Random Feature Emulator","text":"","category":"section"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"note: Have a go with Gaussian processes first\nWe recommend that users first try GaussianProcess for their problems. As random features are a more recent tool, the training procedures and interfaces are still experimental and in development. ","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Random features provide a flexible framework to approximates a Gaussian process. Using random sampling of features, the method is a low-rank approximation leading to advantageous scaling properties (with the number of training points, input, and output dimensions). In the infinite sample limit, there are often (known) explicit Gaussian process kernels that the random feature representation converges to.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"We provide two types of MachineLearningTool for random feature emulation, the ScalarRandomFeatureInterface and the VectorRandomFeatureInterface.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"The ScalarRandomFeatureInterface closely mimics the role of a GaussianProcess package, by training a scalar-output function distribution. It can be applied to multidimensional output problems (as with GaussianProcess) by relying on data processing tools, such as performed when the decorrelate=true keyword argument is provided to the Emulator.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"The VectorRandomFeatureInterface, when applied to multidimensional problems, directly trains a function distribution between multi-dimensional spaces. This approach is not restricted to the data processing of the scalar method (though this can still be helpful). It can be cheaper to evaluate, but on the other hand the training can be more challenging/computationally expensive.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Building a random feature interface is similar to building a Gaussian process: one defines a kernel to encode similarities between outputs (y_iy_j) based on inputs (x_ix_j). Additionally, one must specify the number of random feature samples to be taken to build the emulator.","category":"page"},{"location":"random_feature_emulator/#Recommended-configuration","page":"Random Features","title":"Recommended configuration","text":"","category":"section"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Below is listed a recommended configuration that is flexible and requires learning relatively few parameters. Users can increase r to balance flexibility against having more kernel hyperparameters to learn.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"using CalibrateEmulateSample.Emulators\n# given input_dim, output_dim, and a PairedDataContainer\n\n# define number of features for prediction\nn_features = 400 # number of features for prediction \n\n# define kernel \nnugget = 1e8*eps() # small nugget term\nr = 1 # start with smallest rank \nlr_perturbation = LowRankFactor(r, nugget) \nnonsep_lrp_kernel = NonseparableKernel(lr_perturbation) \n\n# configure optimizer\noptimizer_options = Dict(\n \"verbose\" => true, # print diagnostics for optimizer\n \"n_features_opt\" => 100, # use less features during hyperparameter optimization/kernel learning\n \"cov_sample_multiplier\" => 1.0, # use to reduce/increase number of samples in initial cov estimation stage\n)\n\nmachine_learning_tool = VectorRandomFeatureInterface(\n n_features,\n input_dim,\n output_dim,\n kernel_structure = nonsep_lrp_kernel,\n optimizer_options = optimizer_options\n)","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Users can change the kernel complexity with r, and the number of features for prediciton with n_features and optimization with n_features_opt. ","category":"page"},{"location":"random_feature_emulator/#User-Interface","page":"Random Features","title":"User Interface","text":"","category":"section"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"CalibrateEmulateSample.jl allows the random feature emulator to be built using the external package RandomFeatures.jl. In the notation of this package's documentation, our interface allows for families of RandomFourierFeature objects to be constructed with different Gaussian distributions of the \"xi\" a.k.a weight distribution, and with a learnable \"sigma\", a.k.a scaling parameter.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"note: Relating features and kernels\nThe parallels of random features and gaussian processes can be quite strong. For example:The restriction to RandomFourierFeature objects is a restriction to the approximation of shift-invariant kernels (i.e. K(xy) = K(x-y))\nThe restriction of the weight (\"xi\") distribution to Gaussians is a restriction of approximating squared-exponential kernels. Other distributions (e.g. student-t) leads to other kernels (e.g. Matern)","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"The interfaces are defined minimally with","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"srfi = ScalarRandomFeatureInterface(n_features, input_dim; ...)\nvrfi = VectorRandomFeatureInterface(n_features, input_dim, output_dim; ...)","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"This will build an interface around a random feature family based on n_features features and mapping between spaces of dimenstion input_dim to 1 (scalar), or output_dim (vector).","category":"page"},{"location":"random_feature_emulator/#The-kernel_structure-keyword-for-flexibility","page":"Random Features","title":"The kernel_structure keyword - for flexibility","text":"","category":"section"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"To adjust the expressivity of the random feature family one can define the keyword argument kernel_structure. The more expressive the kernel, the more hyperparameters are learnt in the optimization. ","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"We have two types,","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"separable_kernel = SeparableKernel(input_cov_structure, output_cov_structure)\nnonseparable_kernel = NonseparableKernel(cov_structure)","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"where the cov_structure implies some imposed user structure on the covariance structure. The basic covariance structures are given by ","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"oned_cov_structure = OneDimFactor() # the problem dimension is 1\ndiagonal_structure = DiagonalFactor() # impose diagonal structure (e.g. ARD kernel)\ncholesky_structure = CholeskyFactor() # general positive definite matrix\nlr_perturbation = LowRankFactor(r) # assume structure is a rank-r perturbation from identity","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"All covariance structures (except OneDimFactor) have their final positional argument being a \"nugget\" term adding +epsilon I to the covariance structure. Set to 1 by default.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"The current default kernels are as follows:","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"scalar_default_kernel = SeparableKernel(LowRankFactor(Int(ceil(sqrt(input_dim)))), OneDimFactor())\nvector_default_kernel = SeparableKernel(LowRankFactor(Int(ceil(sqrt(output_dim)))), LowRankFactor(Int(ceil(sqrt(output_dim)))))","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"note: Relating covariance structure and training\nThe parallels between random feature and Gaussian process also extends to the hyperparameter learning. For example,A ScalarRandomFeatureInterface with a DiagonalFactor input covariance structure approximates a Gaussian process with automatic relevance determination (ARD) kernel, where one learns a lengthscale in each dimension of the input space","category":"page"},{"location":"random_feature_emulator/#The-optimizer_options-keyword-for-performance","page":"Random Features","title":"The optimizer_options keyword - for performance","text":"","category":"section"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Passed as a dictionary, this keyword allows the user to configure many options from their defaults in the hyperparameter optimization. The optimizer itself relies on the EnsembleKalmanProcesses package.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"We recommend users experiment with a subset of these flags. At first enable","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Dict(\"verbose\" => true)","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"If the covariance sampling takes too long, run with multithreading (e.g. julia --project -t n_threads script.jl). Sampling is embarassingly parallel so this acheives near linear scaling,","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"If sampling still takes too long, try setting","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Dict(\n \"cov_sample_multiplier\" => csm,\n \"train_fraction\" => tf,\n)","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Decreasing csm (default 10.0) towards 0.0 directly reduces the number of samples to estimate a covariance matrix in the optimizer, by using a shrinkage estimator to improve matrix conditioning. Guide: more samples implies less shrinkage for good conditioning and less approximation error. The amount of shrinkage is returned to user as a value between 0 (no shrinkage) and 1 (shrink to diagonal matrix), it is suggested that users choose csm to keep the shrinkage amount below 0.2.\nIncreasing tf towards 1 changes the train-validate split, reducing samples but increasing cost-per-sample and reducing the available validation data (default 0.8, suggested range (0.5,0.95)).","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"If optimizer convergence stagnates or is too slow, or if it terminates before producing good results, try:","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Dict(\n \"n_ensemble\" => n_e, \n \"n_iteration\" => n_i,\n \"localization\" => loc,\n \"scheduler\" => sch,\n)","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"We suggest looking at the EnsembleKalmanProcesses documentation for more details; but to summarize","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Reducing optimizer samples n_e and iterations n_i reduces computation time but may limit convergence progress, see here.\nIf n_e becomes less than the number of hyperparameters, the updates may fail and a localizer must be specified in loc, see here. \nIf the algorithm terminates at T=1 and resulting emulators looks unacceptable one can change or add arguments in sch e.g. DataMisfitController(\"on_terminate\"=continue), see here","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"note: Note\nWidely robust defaults here are a work in progress","category":"page"},{"location":"random_feature_emulator/#Key-methods","page":"Random Features","title":"Key methods","text":"","category":"section"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"To interact with the kernel/covariance structures we have standard get_* methods along with some useful functions","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"cov_structure_from_string(string,dim) creates a basic covariance structure from a predefined string: onedim, diagonal, cholesky, lowrank etc. and a dimension\ncalculate_n_hyperparameters(in_dim, out_dim, kernel_structure) calculates the number of hyperparameters created by using the given kernel structure (can be applied to the covariance structure individually too)\nbuild_default_priors(in_dim, out_dim, kernel_structure) creates a ParameterDistribution for the hyperparameters based on the kernel structure. This serves as the initialization of the training procedure.","category":"page"},{"location":"random_feature_emulator/#Example-families-and-their-hyperparameters","page":"Random Features","title":"Example families and their hyperparameters","text":"","category":"section"},{"location":"random_feature_emulator/#Scalar:-\\mathbb{R}5-\\to-\\mathbb{R}-at-defaults","page":"Random Features","title":"Scalar: mathbbR^5 to mathbbR at defaults","text":"","category":"section"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"using CalibrateEmulateSample.Emulators\ninput_dim = 5\n# build the default scalar kernel directly (here it will be a rank-3 perturbation from the identity)\nscalar_default_kernel = SeparableKernel(\n cov_structure_from_string(\"lowrank\", input_dim),\n cov_structure_from_string(\"onedim\", 1)\n) \n\ncalculate_n_hyperparameters(input_dim, scalar_default_kernel) \n# answer = 19, 18 for the covariance structure, and one scaling parameter\n\nbuild_default_prior(input_dim, scalar_default_kernel)\n# builds a 3-entry distribution\n# 3-dim positive distribution 'input_lowrank_diagonal'\n# 15-dim unbounded distribution 'input_lowrank_U'\n# 1-dim positive distribution `sigma`","category":"page"},{"location":"random_feature_emulator/#Vector,-separable:-\\mathbb{R}{25}-\\to-\\mathbb{R}{50}-at-defaults","page":"Random Features","title":"Vector, separable: mathbbR^25 to mathbbR^50 at defaults","text":"","category":"section"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"Or take a diagonalized 8-dimensional input, and assume full 6-dimensional output","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"using CalibrateEmulateSample.Emulators\ninput_dim = 25\noutput_dim = 50\n# build the default vector kernel directly (here it will be a rank-5 input and rank-8 output)\nvector_default_kernel = SeparableKernel(\n cov_structure_from_string(\"lowrank\", input_dim),\n cov_structure_from_string(\"lowrank\", output_dim)\n)\n\ncalculate_n_hyperparameters(input_dim, output_dim, vector_default_kernel) \n# answer = 539; 130 for input, 408 for the output, and 1 scaling\n\nbuild_default_prior(input_dim, output_dim, vector_default_kernel)\n# builds a 5-entry distribution\n# 5-dim positive distribution 'input_lowrank_diagonal'\n# 125-dim unbounded distribution 'input_lowrank_U'\n# 8-dim positive distribution 'output_lowrank_diagonal'\n# 400-dim unbounded distribution 'output_lowrank_U'\n# 1-dim postive distribution `sigma`","category":"page"},{"location":"random_feature_emulator/#Vector,-nonseparable:-\\mathbb{R}{25}-\\to-\\mathbb{R}{50}","page":"Random Features","title":"Vector, nonseparable: mathbbR^25 to mathbbR^50","text":"","category":"section"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"The following represents the most general kernel case.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"note: Note\nUse low-rank/diagonls representations where possible to control the number of hyperparameters.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"using CalibrateEmulateSample.Emulators\ninput_dim = 25\noutput_dim = 50\neps = 1e-8\nrank=5\n# build a full-rank nonseparable vector kernel\nvector_lowrank_kernel = NonseparableKernel(LowRankFactor(rank, eps))\n\ncalculate_n_hyperparameters(input_dim, output_dim, vector_lowrank_kernel)\n# answer = 6256; 6255 for the joint input-output space, and 1 scaling\n\nbuild_default_prior(input_dim, output_dim, vector_lowrank_kernel)\n# builds a 2-entry distribution\n# 5-dim positive distribution 'full_lowrank_diagonal'\n# 6250-dim unbounded distribution 'full_lowrank_U'\n# 1-dim positive distribution `sigma`","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"warning: Warning\nNaive representations lead to very large numbers of hyperparameters.","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"using CalibrateEmulateSample.Emulators\ninput_dim = 25\noutput_dim = 50\neps = 1e-8\n# build a full-rank nonseparable vector kernel\nvector_general_kernel = NonseparableKernel(CholeskyFactor(eps))\n\ncalculate_n_hyperparameters(input_dim, output_dim, vector_general_kernel)\n# answer = 781876; 781875 for the joint input-output space, and 1 scaling\n\nbuild_default_prior(input_dim, output_dim, vector_general_kernel)\n# builds a 2-entry distribution\n# 781875-dim unbounded distribution 'full_cholesky'\n# 1-dim positive distribution `sigma`","category":"page"},{"location":"random_feature_emulator/","page":"Random Features","title":"Random Features","text":"See the API for more details.","category":"page"},{"location":"calibrate/#The-Calibrate-stage","page":"Calibrate","title":"The Calibrate stage","text":"","category":"section"},{"location":"calibrate/","page":"Calibrate","title":"Calibrate","text":"Calibration of the computer model entails finding an optimal parameter theta^* that maximizes the posterior probability","category":"page"},{"location":"calibrate/","page":"Calibrate","title":"Calibrate","text":"rho(thetavert y Gamma_y) = dfrace^-mathcalL(theta y)Z(yvertGamma_y)rho_mathrmprior(theta) qquad mathcalL(theta y) = langle mathcalG(theta) - y Gamma_y^-1 left ( mathcalG(theta) - y right ) rangle","category":"page"},{"location":"calibrate/","page":"Calibrate","title":"Calibrate","text":"where mathcalL is the loss or negative log-likelihood, Z(yvertGamma) is a normalizing constant, y represents the data, Gamma_y is the noise covariance matrix and rho_mathrmprior(theta) is the prior density. Calibration is performed using ensemble Kalman processes, which generate input-output pairs theta mathcalG(theta) in high density from the prior initial guess to the found optimal parameter theta^*. These input-output pairs are then used as the data to train an emulator of the forward model mathcalG.","category":"page"},{"location":"calibrate/#Ensemble-Kalman-Processes","page":"Calibrate","title":"Ensemble Kalman Processes","text":"","category":"section"},{"location":"calibrate/","page":"Calibrate","title":"Calibrate","text":"Calibration can be performed using different ensemble Kalman processes: ensemble Kalman inversion (Iglesias et al, 2013), ensemble Kalman sampler (Garbuno-Inigo et al, 2020), and unscented Kalman inversion (Huang et al, 2022). All algorithms are implemented in EnsembleKalmanProcesses.jl. Documentation of each algorithm is available in the EnsembleKalmanProcesses docs.","category":"page"},{"location":"calibrate/#Typical-construction-of-the-EnsembleKalmanProcess","page":"Calibrate","title":"Typical construction of the EnsembleKalmanProcess","text":"","category":"section"},{"location":"calibrate/","page":"Calibrate","title":"Calibrate","text":"Documentation on how to construct an EnsembleKalmanProcess from the computer model and the data can be found in the EnsembleKalmanProcesses docs.","category":"page"},{"location":"calibrate/#Julia-free-forward-model","page":"Calibrate","title":"Julia-free forward model","text":"","category":"section"},{"location":"calibrate/","page":"Calibrate","title":"Calibrate","text":"One draw of our approach is that it does not require the forward map to be written in Julia. To aid construction of such a workflow, EnsembleKalmanProcesses.jl provides a documented example of a BASH workflow for the sinusoid problem, with source code here. The forward map interacts with the calibration tools (EKP) only though TOML file reading an writing, and thus can be written in any language; for example, to be used with slurm HPC scripts, with source code here.","category":"page"},{"location":"examples/Cloudy_example/#Cloudy-example","page":"Cloudy example","title":"Learning the initial parameters of a droplet mass distribution in Cloudy","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"info: How do I run this code?\nThe full code is found in the examples/ directory of the github repository","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"This example is based on Cloudy, a microphysics model that simulates how cloud droplets collide and coalesce into larger drops. Collision-coalescence is a crucial process for the formation of rain. ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"Cloudy is initialized with a mass distribution of the cloud droplets; this distribution is then stepped forward in time, with more and more droplets colliding and combining into bigger drops according to the droplet-droplet interactions specified by a collision-coalescence kernel. The evolution of the droplet distribution is completely determined by the shape of the initial distribution and the form of the kernel.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We will show how Calibrate-Emulate-Sample (CES) can be used to learn the parameters of the initial cloud droplet mass distribution from observations of the moments of that mass distribution at a later time. ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"Cloudy is used here in a \"perfect model\" (aka \"known truth\") setting, which means that the \"observations\" are generated by Cloudy itself, by running it with the true parameter values–-in more realistic applications, one would use actual measurements of cloud properties.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The following schematic gives an overview of the example:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"(Image: cloudy_schematic)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The input to the CES algorithm consists of data y, the observational covariance Γ, and prior parameter distributions. The data, a vector of moments of the droplet mass distribution, are obtained by running Cloudy with the parameters set to their true values. The covariance is obtained from model output. The calibration stage is performed by an ensemble Kalman inversion (EKI), in which Cloudy has to be run once per iteration and for each ensemble member. The resulting input-output pairs theta_i mathcalG(theta_i)_i are used to train an emulator model. This emulator widetildemathcalG(theta) is cheap to evaluate; it replaces the original parameter-to-data map in the Markov chain Monte Carlo (MCMC) sampling, which produces (approximate) samples of the posterior parameter distribution. These samples are the final output of the CES algorithm. ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"This paper describes Cloudy in much more detail and shows results of experiments using CES to learn model parameters.","category":"page"},{"location":"examples/Cloudy_example/#Running-the-example","page":"Cloudy example","title":"Running the example","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"Cloudy_calibrate.jl performs the calibration using ensemble Kalman inversion; Cloudy_emulate_sample.jl fits an emulator and uses it to sample the posterior distributions of the parameters. Once Cloudy is installed, the example can be run from the julia REPL:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"include(\"Cloudy_calibrate.jl\")\ninclude(\"Cloudy_emulate_sample.jl\")","category":"page"},{"location":"examples/Cloudy_example/#Walkthrough-of-the-code:-Cloudy_calibrate.jl","page":"Cloudy example","title":"Walkthrough of the code: Cloudy_calibrate.jl","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"This file performs the calibration stage of CES.","category":"page"},{"location":"examples/Cloudy_example/#Import-packagages-and-modules","page":"Cloudy example","title":"Import packagages and modules","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"First we load standard packages,","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"using Distributions\nusing StatsBase\nusing LinearAlgebra\nusing StatsPlots\nusing Plots\nusing Plots.PlotMeasures\nusing Random\nusing JLD2","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"the Cloudy modules,","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"using Cloudy\nusing Cloudy.ParticleDistributions\nusing Cloudy.KernelTensors\n\n# Import the module that runs Cloudy\ninclude(joinpath(@__DIR__, \"DynamicalModel.jl\"))","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"and finally the EKP packages.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"using EnsembleKalmanProcesses\nusing EnsembleKalmanProcesses.Observations\nusing EnsembleKalmanProcesses.ParameterDistributions\nusing EnsembleKalmanProcesses.DataContainers\nusing EnsembleKalmanProcesses.PlotRecipes","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The module DynamicalModel.jl is the forward solver; it provides a function that runs Cloudy with a given instance of the parameter vector we want to learn.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"include(\"DynamicalModel.jl\")","category":"page"},{"location":"examples/Cloudy_example/#Define-the-true-parameters","page":"Cloudy example","title":"Define the true parameters","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We define the true parameters–-they are known here because this is a known truth example. Knowing the true parameters will allow us to assess how well Calibrate-Emulate-Sample has managed to solve the inverse problem.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We will assume that the true particle mass distribution is a Gamma distribution, which at time t = 0 has parameters phi_0 = N_0 0 k_0 theta_0. We will then try to learn these parameters from observations y = M_0(t_end) M_1(t_end) M_2(t_end) of the zeroth-, first-, and second-order moments of the distribution at time t_end 0 (where t_end = 1.0 in this example). The true parameters phi_0 texttrue are defined as follows:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"param_names = [\"N0\", \"θ\", \"k\"]\nn_params = length(param_names)\nN0_true = 300.0 # number of particles (scaling factor for Gamma distribution)\nθ_true = 1.5597 # scale parameter of Gamma distribution\nk_true = 0.0817 # shape parameter of Gamma distribution\nϕ_true = [N0_true, θ_true, k_true] # true parameters in constrained space\ndist_true = ParticleDistributions.GammaPrimitiveParticleDistribution(ϕ_true...)","category":"page"},{"location":"examples/Cloudy_example/#Define-priors-for-the-parameters","page":"Cloudy example","title":"Define priors for the parameters","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"As we are working with Bayesian methods, we treat the parameters we want to learn as random variables whose prior distributions we specify here. The prior distributions will behave like an \"initial guess\" for the likely region of parameter space where we expect the solution to be located. We use constrained_gaussian to add the desired scale and bounds to the prior distribution, in particular we place lower bounds to preserve positivity (and numerical stability). ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"# We choose to use normal distributions to represent the prior distributions of\n# the parameters in the transformed (unconstrained) space.\nprior_N0 = constrained_gaussian(param_names[1], 400, 300, 0.4 * N0_true, Inf)\nprior_θ = constrained_gaussian(param_names[2], 1.0, 5.0, 1e-1, Inf)\nprior_k = constrained_gaussian(param_names[3], 0.2, 1.0, 1e-4, Inf)\npriors = combine_distributions([prior_N0, prior_θ, prior_k])","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The plot recipe for ParameterDistribution types allows for quick visualization of the priors:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"# Plot the priors\np = plot(priors, constrained=false)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"(Image: priors)","category":"page"},{"location":"examples/Cloudy_example/#Generate-(synthetic)-observations","page":"Cloudy example","title":"Generate (synthetic) observations","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We generate synthetic observations by running Cloudy 100 times with the true parameters (i.e., with the true initial Gamma distribution of droplet masses) and then adding noise to simulate measurement error.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"dyn_model_settings_true = DynamicalModel.ModelSettings(\n kernel, dist_true, moments, tspan)\n\nG_t = DynamicalModel.run_dyn_model(ϕ_true, dyn_model_settings_true)\nn_samples = 100\ny_t = zeros(length(G_t), n_samples)\n# In a perfect model setting, the \"observational noise\" represents the \n# internal model variability. Since Cloudy is a purely deterministic model, \n# there is no straightforward way of coming up with a covariance structure \n# for this internal model variability. We decide to use a diagonal \n# covariance, with entries (variances) largely proportional to their \n# corresponding data values, G_t\nΓy = convert(Array, Diagonal([100.0, 5.0, 30.0]))\nμ = zeros(length(G_t))\n\n# Add noise\nfor i in 1:n_samples\n y_t[:, i] = G_t .+ rand(MvNormal(μ, Γy))\nend\n\ntruth = Observations.Observation(y_t, Γy, data_names)\ntruth_sample = truth.mean ","category":"page"},{"location":"examples/Cloudy_example/#Perform-ensemble-Kalman-inversion","page":"Cloudy example","title":"Perform ensemble Kalman inversion","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We sample the initial ensemble from the prior and create the EnsembleKalmanProcess object as an ensemble Kalman inversion (EKI) algorithm using the Inversion() keyword. We also use the DataMisfitController() learning rate scheduler. The number of ensemble members must be larger than the dimension of the parameter space to ensure a full rank ensemble covariance.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"N_ens = 50 # number of ensemble members\nN_iter = 8 # number of EKI iterations\n# initial parameters: n_params x N_ens\ninitial_params = construct_initial_ensemble(rng, priors, N_ens)\nekiobj = EnsembleKalmanProcess(\n initial_params,\n truth_sample,\n truth.obs_noise_cov,\n Inversion(),\n scheduler=DataMisfitController()\n)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We perform the inversion loop. Remember that within calls to get_ϕ_final the EKP transformations are applied, thus the ensemble that is returned will be the gamma distribution parameters that can be used directly to run the forward model, rather than their corresponding values in the unconstrained space where the EKI takes place. Each ensemble member is stored as a column and therefore for uses such as plotting one needs to reshape to the desired dimension.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"# Initialize a ParticleDistribution with dummy parameters. The parameters \n# will then be set within `run_dyn_model`\ndummy = ones(n_params)\ndist_type = ParticleDistributions.GammaPrimitiveParticleDistribution(dummy...)\nmodel_settings = DynamicalModel.ModelSettings(kernel, dist_type, moments, tspan)\n# EKI iterations\nfor n in 1:N_iter\n # Return transformed parameters in physical/constrained space\n ϕ_n = get_ϕ_final(priors, ekiobj)\n # Evaluate forward map\n G_n = [DynamicalModel.run_dyn_model(ϕ_n[:, i], model_settings) for i in 1:N_ens]\n G_ens = hcat(G_n...) # reformat\n EnsembleKalmanProcesses.update_ensemble!(ekiobj, G_ens)\nend","category":"page"},{"location":"examples/Cloudy_example/#Visualize-and-store-the-results-of-the-calibration","page":"Cloudy example","title":"Visualize and store the results of the calibration","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The optimal parameter vector determined by the ensemble Kalman inversion is the ensemble mean of the particles after the last iteration, which is printed to standard output. An output directory is created, where a file cloudy_calibrate_results.jld2 is stored, which contains all parameters and model output from the ensemble Kalman iterations (both as DataContainers.DataContainer objects), the mean and one sample of the synthetic observations, as well as the true prameters and their priors. In addition, an animation is produced that shows the evolution of the ensemble of particles over subsequent iterations of the optimization, both in the computational (unconstrained) and physical (constrained) spaces.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"(Image: eki_iterations_animation)","category":"page"},{"location":"examples/Cloudy_example/#Walkthrough-of-the-code:-Cloudy_emulate_sample.jl","page":"Cloudy example","title":"Walkthrough of the code: Cloudy_emulate_sample.jl","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"This file performs the emulation and sampling stages of the CES algorithm.","category":"page"},{"location":"examples/Cloudy_example/#Import-packages-and-modules","page":"Cloudy example","title":"Import packages and modules","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"First, we import some standard packages","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"using Distributions\nusing StatsBase\nusing GaussianProcesses\nusing LinearAlgebra\nusing Random\nusing JLD2\nENV[\"GKSwstype\"] = \"100\"\nusing CairoMakie, PairPlots","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"as well as the relevant CES packages needed to construct the emulators and perform the Markov chain Monte Carlo (MCMC) sampling. We also need some functionality of EnsembleKalmanProcesses.jl.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"using CalibrateEmulateSample.Emulators\nusing CalibrateEmulateSample.MarkovChainMonteCarlo\nusing CalibrateEmulateSample.Utilities\nusing EnsembleKalmanProcesses\nusing EnsembleKalmanProcesses.ParameterDistributions\nusing EnsembleKalmanProcesses.DataContainers","category":"page"},{"location":"examples/Cloudy_example/#Load-the-calibration-results","page":"Cloudy example","title":"Load the calibration results","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We will train the emulator on the input-output pairs we obtained during the calibration. They are stored within the EnsembleKalmanProcess object (ekiobj), which is loaded here together with the other information that was saved in the calibration step.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"ekiobj = load(data_save_file)[\"eki\"]\npriors = load(data_save_file)[\"priors\"]\ntruth_sample_mean = load(data_save_file)[\"truth_sample_mean\"]\ntruth_sample = load(data_save_file)[\"truth_sample\"]\n# True parameters:\n# - ϕ: in constrained space\n# - θ: in unconstrained space\nϕ_true = load(data_save_file)[\"truth_input_constrained\"]\nθ_true = transform_constrained_to_unconstrained(priors, ϕ_true)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The user can choose one or more of the following three emulators: a Gaussian Process (GP) emulator with GaussianProcesses.jl interface (gp-gpjl), a scalar Random Feature (RF) interface (rf-scalar), and vector RF with a nonseparable, nondiagonal kernel structure in the output space (rf-nosvd-nonsep). See here for a complete overview of the available emulators. ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"cases = [\n \"rf-scalar\",\n \"gp-gpjl\", # Veeeery slow predictions\n \"rf-nosvd-nonsep\"\n]","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We first define some settings for the two emulators, e.g., the prediction type for the GP emulator, or the number of features and hyperparameter optimizer options for the RF emulator. The docs for GPs and RFs explain the different options in more detail and provide some useful heuristics for how to customize the settings depending on the problem at hand.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"# These settings are the same for all Gaussian Process cases\npred_type = YType() # we want to predict data\n\n# These settings are the same for all Random Feature cases\nn_features = 400 \nnugget = 1e-8\noptimizer_options = Dict(\n \"verbose\" => true,\n \"scheduler\" => DataMisfitController(terminate_at = 100.0),\n \"cov_sample_multiplier\" => 1.0,\n \"n_iteration\" => 20,\n)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"Emulation is performed through the construction of an Emulator object from the following components:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"a wrapper for the machine learning tool (mlt) to be used as emulator\nthe input-output pairs on which the emulator will be trained\noptional arguments specifying data processing and dimensionality reduction functionality ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"For gp-gpjl, this looks as follows:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"gppackage = GPJL()\n# Kernel is the sum of a squared exponential (SE), Matérn 5/2, and white noise\ngp_kernel = SE(1.0, 1.0) + Mat52Ard(zeros(3), 0.0) + Noise(log(2.0))\n\n# Wrapper for GP\nmlt = GaussianProcess(\n gppackage;\n kernel = gp_kernel,\n prediction_type = pred_type,\n noise_learn = false,\n)\n\ndecorrelate = true\nstandardize_outputs = true","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"And similarly for rf-scalar","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"kernel_rank = 3\nkernel_structure = SeparableKernel(\n LowRankFactor(kernel_rank, nugget),\n OneDimFactor()\n)\n\nmlt = ScalarRandomFeatureInterface(\n n_features,\n n_params,\n kernel_structure = kernel_structure,\n optimizer_options = optimizer_options,\n)\n\ndecorrelate = true\nstandardize_outputs = true","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"and for rf-nosvd-nonsep:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"kernel_rank = 4\nmlt = VectorRandomFeatureInterface(\n n_features,\n n_params,\n n_outputs,\n kernel_structure = NonseparableKernel(LowRankFactor(kernel_rank, nugget)),\n optimizer_options = optimizer_options\n)\n\n# Vector RF does not require decorrelation of outputs\ndecorrelate = false\nstandardize_outputs = false","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We construct the emulator using the input-output pairs obtained in the calibration stage (note that we're not using all available input-output pairs–-using all of them may not give the best results, especially if the EKI parameter converges rapidly and then \"stays in the same place\" during the remaining iterations). For the gp-gpjl and rf-scalar cases, we want the output data to be decorrelated with information from Γy, but for the vector RF case decorrelation is not required.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"input_output_pairs = get_training_points(ekiobj,\n length(get_u(ekiobj))-2)\n\n# Use the medians of the outputs as standardizing factors\nnorm_factors = get_standardizing_factors(\n get_outputs(input_output_pairs)\n)\n\n# The data processing normalizes input data, and decorrelates\n# output data with information from Γy, if required\n# Note: The `standardize_outputs_factors` are only used under the\n# condition that `standardize_outputs` is true.\nemulator = Emulator(\n mlt,\n input_output_pairs,\n decorrelate = decorrelate,\n obs_noise_cov = Γy,\n standardize_outputs = true,\n standardize_outputs_factors = vcat(norm_factors...),\n)","category":"page"},{"location":"examples/Cloudy_example/#Train-the-emulator","page":"Cloudy example","title":"Train the emulator","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The emulator is trained when we combine the machine learning tool and the data into the Emulator above. We must also optimize the hyperparameters:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"optimize_hyperparameters!(emulator)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"To test the predictive skill of the emulator, we can e.g. compare its prediction on the true parameters to the true data. (One could also hold out a subset of the input-output pairs from the training and evaluate the emulator's predictions on them).","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"# Check how well the emulator predicts on the true parameters\ny_mean, y_var = Emulators.predict(\n emulator,\n reshape(θ_true, :, 1);\n transform_to_real = true\n)\n\nprintln(\"Emulator ($(case)) prediction on true parameters: \")\nprintln(vec(y_mean))\nprintln(\"true data: \")\nprintln(truth_sample) # what was used as truth","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The emulator predicts both a mean value and a covariance.","category":"page"},{"location":"examples/Cloudy_example/#Sample-the-posterior-distributions-of-the-parameters","page":"Cloudy example","title":"Sample the posterior distributions of the parameters","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The last step is to plug the emulator into an MCMC algorithm, which is then used to produce samples from the posterior distribution of the parameters. Essentially, the emulator acts as a stand-in for the original forward model (which in most cases of interest is computationally expensive to run) during the MCMC sampling process.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We use the mean across all parameter ensembles from the EKI as the initial parameters for the MCMC. Before running the actual MCMC chain, we determine a good step size by running chains of length N = 2000:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"# initial values\nu0 = vec(mean(get_inputs(input_output_pairs), dims = 2))\nprintln(\"initial parameters: \", u0)\n\n# First let's run a short chain to determine a good step size\nyt_sample = truth_sample\nmcmc = MCMCWrapper(\n RWMHSampling(),\n truth_sample,\n priors,\n emulator;\n init_params = u0\n)\n\nnew_step = optimize_stepsize(\n mcmc;\n init_stepsize = 0.1,\n N = 2000,\n discard_initial = 0\n)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We choose a sample size of 100,000 for the actual MCMC, discarding the first 1,000 samples as burn-in:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"# Now begin the actual MCMC\nprintln(\"Begin MCMC - with step size \", new_step)\nchain = MarkovChainMonteCarlo.sample(\n mcmc,\n 100_000;\n stepsize = new_step,\n discard_initial = 1_000\n)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"After running the MCMC, we can extract the posterior samples as follows:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"posterior = MarkovChainMonteCarlo.get_posterior(mcmc, chain)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The samples of the posterior distributions represent the ultimate output of the CES process. By constructing histograms of these samples and comparing them with the known true parameter values, we can evaluate the results' accuracy. Ideally, the peak of the posterior distribution should be located near the true values, indicating a high-quality estimation. Additionally, visualizing the prior distributions alongside the posteriors shows the distributional change effected by the Bayesian learning process.","category":"page"},{"location":"examples/Cloudy_example/#Results","page":"Cloudy example","title":"Results","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We first produce pair plots (also known as corner plots or scatter plot matrices) to visualize the posterior parameter distributions as a grid of histograms. Recall that the task was to solve the inverse problem of finding the parameters N_0 0, k_0, and theta_0, which define a gamma distribution of droplet masses in Cloudy at time t = 0.","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"# Make pair plots of the posterior distributions in the unconstrained\n# and in the constrained space (this uses `PairPlots.jl`)\nfigpath_unconstr = joinpath(output_directory,\n \"joint_posterior_unconstr.png\")\nfigpath_constr = joinpath(output_directory,\n \"joint_posterior_constr.png\")\nlabels = get_name(posterior)\n\ndata_unconstr = (; [(Symbol(labels[i]),\n posterior_samples_unconstr[i, :]) for i in 1:length(labels)]...)\ndata_constr = (; [(Symbol(labels[i]),\n posterior_samples_constr[i, :]) for i in 1:length(labels)]...)\n\np_unconstr = pairplot(data_unconstr => (PairPlots.Scatter(),))\np_constr = pairplot(data_constr => (PairPlots.Scatter(),))","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"For the GP emulator, the results (shown in the constrained/physical space) look as follows:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"(Image: pairplot_posterior_gpjl)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"And we can plot the same for the scalar RF emulator...","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"(Image: pairplot_posterior_rf-scalar)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"...and for the vector RF emulator:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"(Image: pairplot_posterior_rf-vec)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"In addition, we plot the marginals of the posterior distributions–-we are showing them here for the GP emulator case:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"for idx in 1:n_params\n\n # Find the range of the posterior samples\n xmin = minimum(posterior_samples_constr[idx, :])\n xmax = maximum(posterior_samples_constr[idx, :])\n\n # Create a figure and axis for plotting\n fig = Figure(; size = (800, 600))\n ax = Axis(fig[1, 1])\n\n # Histogram for posterior samples\n hist!(ax, posterior_samples_constr[idx, :], bins = 100,\n color = :darkorange, label = \"posterior\")\n\n # Plotting the prior distribution\n hist!(ax, prior_samples_constr[idx, :], bins = 10000,\n color = :slategray)\n\n # Adding a vertical line for the true value\n vlines!(ax, [ϕ_true[idx]], color = :indigo, linewidth = 2.6,\n label = \"true \" * param_names[idx])\n\n xlims!(ax, xmin, xmax)\n ylims!(ax, 0, Inf)\n\n # Setting title and labels\n ax.title = param_names[idx]\n ax.xlabel = \"Value\"\n ax.ylabel = \"Density\"","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"This is what the marginal distributions of the three parameters look like, for the case of the GP emulator, and in the constrained/physical space:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"(Image: posterior_N0_gpjl)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"(Image: posterior_theta_gpjl)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"(Image: posterior_k_gpjl)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"Here, the posterior distributions are shown as orange histograms, the prior distribution are shown as grey histograms (though with the exception of the parmaeter k, they are barely visible), and the true parameter values are marked as vertical purple lines.","category":"page"},{"location":"examples/Cloudy_example/#Appendix:-What-Does-Cloudy-Do?","page":"Cloudy example","title":"Appendix: What Does Cloudy Do?","text":"","category":"section"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"For the purpose of Bayesian parameter learning, the forward model can be treated as a black box that processes input parameters to yield specific outputs. However, for those who wish to learn more about the inner workings of Cloudy, we refer to his paper and offer a brief outline below:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The mathematical starting point of Cloudy is the stochastic collection equation (SCE; sometimes also called Smoluchowski equation after Marian Smoluchowski), which describes the time rate of change of f = f(m t), the mass distribution function of liquid water droplets, due to the process of collision and coalescence. The distribution function f depends on droplet mass m and time t and is defined such that f(m) text dm denotes the number of droplets with masses in the interval m m + dm per unit volume. ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The stochastic collection equation is an integro-differential equation that can be written as ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":" fracpartial f(m t)partial t = frac12 int_m=0^infty f(m t) f(m-m t) mathcalC(m m-m)textdm - f(m t) int_m=0^infty f(m t)mathcalC(m m) textdm ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"where mathcalC(m m) is the collision-coalescence kernel, which encapsulates the physics of droplet-droplet interactions – it describes the rate at which two drops of masses m and m come into contact and coalesce into a drop of mass m + m. The first term on the right-hand side of the SCE describes the rate of increase of the number of drops having a mass m due to collision and coalescence of drops of masses m and m-m (where the factor frac12 avoids double counting), while the second term describes the rate of reduction of drops of mass m due to collision and coalescence of drops having a mass m with other drops. ","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"We can rewrite the SCE in terms of the moments M_k of f, which are the prognostic variables in Cloudy. They are defined by","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":" M_k = int_0^infty m^k f(m t) textdm","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The time rate of change of the k-th moment of f is obtained by multiplying the SCE by m^k and integrating over the entire range of droplet masses (from m=0 to infty), which yields","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":" fracpartial M_k(t)partial t = frac12int_0^infty left((m+m)^k - m^k - m^kright) mathcalC(m m)f(m t)f(m t) textdm textdm (1)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"In this example, the kernel is set to be constant – mathcalC(m m) = B = textconst – and the cloud droplet mass distribution is assumed to be a textGamma(k_t theta_t) distribution, scaled by a factor N_0t which denotes the droplet number concentration:","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"f(m t) = fracN_0tGamma(k_t)theta_t^k m^k_t-1 exp(-mtheta_t)","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"The parameter vector phi_t= N_0t k_t theta_t changes over time (as indicated by the subscript t), as the shape of the distribution evolves. In fact, there is a priori no reason to assume that the distribution would retain its Gamma shape over time, but this is a common assumption that is made in order to solve the closure problem (without this assumption, one would have to keep track of infinitely many moments of the mass distribution in order to uniquely identify the distribution f at each time step, which is obviously not practicable).","category":"page"},{"location":"examples/Cloudy_example/","page":"Cloudy example","title":"Cloudy example","text":"For Gamma mass distribution functions, specifying the first three moments (M_0, M_1, and M_2) is sufficient to uniquely determine the parameter vector phi_t, hence Cloudy solves equation (1) for k = 0 1 2. This mapping of the parameters of the initial cloud droplet mass distribution to the (zeroth-, first-, and second-order) moments of the distribution at a specified end time is done by DynamicalModel.jl.","category":"page"},{"location":"API/Emulators/#Emulators","page":"General Interface","title":"Emulators","text":"","category":"section"},{"location":"API/Emulators/","page":"General Interface","title":"General Interface","text":"CurrentModule = CalibrateEmulateSample.Emulators","category":"page"},{"location":"API/Emulators/","page":"General Interface","title":"General Interface","text":"Emulator\noptimize_hyperparameters!(::Emulator)\nEmulator(::MachineLearningTool, ::PairedDataContainer{FT}) where {FT <: AbstractFloat}\npredict\nnormalize\nstandardize\nreverse_standardize\nsvd_transform\nsvd_reverse_transform_mean_cov","category":"page"},{"location":"API/Emulators/#CalibrateEmulateSample.Emulators.Emulator","page":"General Interface","title":"CalibrateEmulateSample.Emulators.Emulator","text":"struct Emulator{FT<:AbstractFloat}\n\nStructure used to represent a general emulator, independently of the algorithm used.\n\nFields\n\nmachine_learning_tool::CalibrateEmulateSample.Emulators.MachineLearningTool: Machine learning tool, defined as a struct of type MachineLearningTool.\ntraining_pairs::EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT} where FT<:AbstractFloat: Normalized, standardized, transformed pairs given the Booleans normalize_inputs, standardize_outputs, retained_svd_frac.\ninput_mean::AbstractVector{FT} where FT<:AbstractFloat: Mean of input; length input_dim.\nnormalize_inputs::Bool: If normalizing: whether to fit models on normalized inputs ((inputs - input_mean) * sqrt_inv_input_cov).\nnormalization::Union{Nothing, LinearAlgebra.UniformScaling{FT}, AbstractMatrix{FT}} where FT<:AbstractFloat: (Linear) normalization transformation; size input_dim × input_dim.\nstandardize_outputs::Bool: Whether to fit models on normalized outputs: outputs / standardize_outputs_factor.\nstandardize_outputs_factors::Union{Nothing, AbstractVector{FT}} where FT<:AbstractFloat: If standardizing: Standardization factors (characteristic values of the problem).\ndecomposition::Union{Nothing, LinearAlgebra.SVD}: The singular value decomposition of obs_noise_cov, such that obs_noise_cov = decomposition.U * Diagonal(decomposition.S) * decomposition.Vt. NB: the SVD may be reduced in dimensions.\nretained_svd_frac::AbstractFloat: Fraction of singular values kept in decomposition. A value of 1 implies full SVD spectrum information.\n\n\n\n\n\n","category":"type"},{"location":"API/Emulators/#CalibrateEmulateSample.Emulators.optimize_hyperparameters!-Tuple{CalibrateEmulateSample.Emulators.Emulator}","page":"General Interface","title":"CalibrateEmulateSample.Emulators.optimize_hyperparameters!","text":"optimize_hyperparameters!(\n emulator::CalibrateEmulateSample.Emulators.Emulator{FT<:AbstractFloat},\n args...;\n kwargs...\n) -> Any\n\n\nOptimizes the hyperparameters in the machine learning tool.\n\n\n\n\n\n","category":"method"},{"location":"API/Emulators/#CalibrateEmulateSample.Emulators.Emulator-Union{Tuple{FT}, Tuple{CalibrateEmulateSample.Emulators.MachineLearningTool, EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT}}} where FT<:AbstractFloat","page":"General Interface","title":"CalibrateEmulateSample.Emulators.Emulator","text":"Emulator(\n machine_learning_tool::CalibrateEmulateSample.Emulators.MachineLearningTool,\n input_output_pairs::EnsembleKalmanProcesses.DataContainers.PairedDataContainer{FT<:AbstractFloat};\n obs_noise_cov,\n normalize_inputs,\n standardize_outputs,\n standardize_outputs_factors,\n decorrelate,\n retained_svd_frac\n) -> CalibrateEmulateSample.Emulators.Emulator{FT} where Float64<:FT<:AbstractFloat\n\n\nPositional Arguments\n\nmachine_learning_tool ::MachineLearningTool,\ninput_output_pairs ::PairedDataContainer\n\nKeyword Arguments \n\nobs_noise_cov: A matrix/uniform scaling to provide the observational noise covariance of the data - used for data processing (default nothing),\nnormalize_inputs: Normalize the inputs to be unit Gaussian, in the smallest full-rank space of the data (default true),\nstandardize_outputs: Standardize outputs with by dividing by a vector of provided factors (default false),\nstandardize_outputs_factors: If standardizing, the provided dim_output-length vector of factors,\ndecorrelate: Apply (truncated) SVD to the outputs. Predictions are returned in the decorrelated space, (default true)\nretained_svd_frac: The cumulative sum of singular values retained after output SVD truncation (default 1.0 - no truncation)\n\n\n\n\n\n","category":"method"},{"location":"API/Emulators/#GaussianProcesses.predict","page":"General Interface","title":"GaussianProcesses.predict","text":"predict(\n gp::CalibrateEmulateSample.Emulators.GaussianProcess{CalibrateEmulateSample.Emulators.GPJL},\n new_inputs::AbstractArray{FT<:AbstractFloat, 2}\n) -> Tuple{Any, Any}\n\n\nPredict means and covariances in decorrelated output space using Gaussian process models.\n\n\n\n\n\npredict(\n srfi::CalibrateEmulateSample.Emulators.ScalarRandomFeatureInterface,\n new_inputs::AbstractMatrix;\n multithread\n) -> Tuple{Any, Any}\n\n\nPrediction of data observation (not latent function) at new inputs (passed in as columns in a matrix). That is, we add the observational noise into predictions.\n\n\n\n\n\npredict(\n vrfi::CalibrateEmulateSample.Emulators.VectorRandomFeatureInterface,\n new_inputs::AbstractMatrix\n) -> Tuple{Any, Any}\n\n\nPrediction of data observation (not latent function) at new inputs (passed in as columns in a matrix). That is, we add the observational noise into predictions.\n\n\n\n\n\npredict(\n emulator::CalibrateEmulateSample.Emulators.Emulator{FT<:AbstractFloat},\n new_inputs::AbstractArray{FT<:AbstractFloat, 2};\n transform_to_real,\n vector_rf_unstandardize,\n mlt_kwargs...\n) -> Tuple{Any, Any}\n\n\nMakes a prediction using the emulator on new inputs (each new inputs given as data columns). Default is to predict in the decorrelated space.\n\n\n\n\n\n","category":"function"},{"location":"API/Emulators/#CalibrateEmulateSample.Emulators.normalize","page":"General Interface","title":"CalibrateEmulateSample.Emulators.normalize","text":"normalize(\n emulator::CalibrateEmulateSample.Emulators.Emulator,\n inputs::AbstractVecOrMat\n) -> Any\n\n\nNormalize the input data, with a normalizing function.\n\n\n\n\n\n","category":"function"},{"location":"API/Emulators/#CalibrateEmulateSample.Emulators.standardize","page":"General Interface","title":"CalibrateEmulateSample.Emulators.standardize","text":"standardize(\n outputs::AbstractVecOrMat,\n output_covs::Union{AbstractVector{<:AbstractMatrix}, AbstractVector{<:LinearAlgebra.UniformScaling}},\n factors::AbstractVector\n) -> Tuple{Any, Union{AbstractVector{<:AbstractMatrix}, AbstractVector{<:LinearAlgebra.UniformScaling}}}\n\n\nStandardize with a vector of factors (size equal to output dimension).\n\n\n\n\n\n","category":"function"},{"location":"API/Emulators/#CalibrateEmulateSample.Emulators.reverse_standardize","page":"General Interface","title":"CalibrateEmulateSample.Emulators.reverse_standardize","text":"reverse_standardize(\n emulator::CalibrateEmulateSample.Emulators.Emulator{FT<:AbstractFloat},\n outputs::AbstractVecOrMat,\n output_covs::AbstractVecOrMat\n) -> Tuple{Any, Any}\n\n\nReverse a previous standardization with the stored vector of factors (size equal to output dimension). output_cov is a Vector of covariance matrices, such as is returned by svd_reverse_transform_mean_cov.\n\n\n\n\n\n","category":"function"},{"location":"API/Emulators/#CalibrateEmulateSample.Emulators.svd_transform","page":"General Interface","title":"CalibrateEmulateSample.Emulators.svd_transform","text":"svd_transform(\n data::AbstractArray{FT<:AbstractFloat, 2},\n obs_noise_cov::Union{Nothing, AbstractArray{FT<:AbstractFloat, 2}};\n retained_svd_frac\n) -> Tuple{Any, Any}\n\n\nApply a singular value decomposition (SVD) to the data\n\ndata - GP training data/targets; size output_dim × N_samples\nobs_noise_cov - covariance of observational noise\ntruncate_svd - Project onto this fraction of the largest principal components. Defaults to 1.0 (no truncation).\n\nReturns the transformed data and the decomposition, which is a matrix factorization of type LinearAlgebra.SVD. \n\nNote: If F::SVD is the factorization object, U, S, V and Vt can be obtained via F.U, F.S, F.V and F.Vt, such that A = U * Diagonal(S) * Vt. The singular values in S are sorted in descending order.\n\n\n\n\n\n","category":"function"},{"location":"API/Emulators/#CalibrateEmulateSample.Emulators.svd_reverse_transform_mean_cov","page":"General Interface","title":"CalibrateEmulateSample.Emulators.svd_reverse_transform_mean_cov","text":"svd_reverse_transform_mean_cov(\n μ::AbstractArray{FT<:AbstractFloat, 2},\n σ2::AbstractVector,\n decomposition::LinearAlgebra.SVD\n) -> Tuple{Any, Any}\n\n\nTransform the mean and covariance back to the original (correlated) coordinate system\n\nμ - predicted mean; size output_dim × N_predicted_points.\nσ2 - predicted variance; size output_dim × N_predicted_points. - predicted covariance; size N_predicted_points array of size output_dim × output_dim.\ndecomposition - SVD decomposition of obs_noise_cov.\n\nReturns the transformed mean (size output_dim × N_predicted_points) and variance. Note that transforming the variance back to the original coordinate system results in non-zero off-diagonal elements, so instead of just returning the elements on the main diagonal (i.e., the variances), we return the full covariance at each point, as a vector of length N_predicted_points, where each element is a matrix of size output_dim × output_dim.\n\n\n\n\n\n","category":"function"},{"location":"emulate/#The-Emulate-stage","page":"Emulator","title":"The Emulate stage","text":"","category":"section"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"Emulation is performed through the construction of an Emulator object, which has two components","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"A wrapper for any statistical emulator,\nData-processing and dimensionality reduction functionality.","category":"page"},{"location":"emulate/#Typical-construction-from-Lorenz_example.jl","page":"Emulator","title":"Typical construction from Lorenz_example.jl","text":"","category":"section"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"First, obtain data in a PairedDataContainer, for example, get this from an EnsembleKalmanProcess ekpobj generated during the Calibrate stage, or see the constructor here","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"using CalibrateEmulateSample.Utilities\ninput_output_pairs = Utilities.get_training_points(ekpobj, 5) # use first 5 iterations as data","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"Wrapping a predefined machine learning tool, e.g. a Gaussian process gauss_proc, the Emulator can then be built:","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"emulator = Emulator(\n gauss_proc, \n input_output_pairs; # optional arguments after this\n obs_noise_cov = Γy,\n normalize_inputs = true,\n standardize_outputs = true,\n standardize_outputs_factors = factor_vector,\n retained_svd_frac = 0.95,\n)","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"The optional arguments above relate to the data processing.","category":"page"},{"location":"emulate/#Emulator-Training","page":"Emulator","title":"Emulator Training","text":"","category":"section"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"The emulator is trained when we combine the machine learning tool and the data into the Emulator above. For any machine learning tool, hyperparameters are optimized.","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"optimize_hyperparameters!(emulator)","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"For some machine learning packages however, this may be completed during construction automatically, and for others this will not. If automatic construction took place, the optimize_hyperparameters! line does not perform any new task, so may be safely called. In the Lorenz example, this line learns the hyperparameters of the Gaussian process, which depend on the choice of kernel, and the choice of GP package. Predictions at new inputs can then be made using","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"y, cov = Emulator.predict(emulator, new_inputs)","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"This returns both a mean value and a covariance.","category":"page"},{"location":"emulate/#Data-processing","page":"Emulator","title":"Data processing","text":"","category":"section"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"Some effects of the following are outlined in a practical setting in the results and appendices of Howland, Dunbar, Schneider, (2022).","category":"page"},{"location":"emulate/#Diagonalization-and-output-dimension-reduction","page":"Emulator","title":"Diagonalization and output dimension reduction","text":"","category":"section"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"This arises from the optional arguments","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"obs_noise_cov = Γy (default: nothing)","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"We always use singular value decomposition to diagonalize the output space, requiring output covariance Γy. Why? If we need to train a mathbbR^10 to mathbbR^100 emulator, diagonalization allows us to instead train 100 mathbbR^10 to mathbbR^1 emulators (far cheaper).","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"retained_svd_frac = 0.95 (default 1.0)","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"Performance is increased further by throwing away less informative output dimensions, if 95% of the information (i.e., variance) is in the first 40 diagonalized output dimensions then setting retained_svd_frac=0.95 will train only 40 emulators.","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"note: Note\nDiagonalization is an approximation. It is however a good approximation when the observational covariance varies slowly in the parameter space.","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"warn: Warn\nSevere approximation errors can occur if obs_noise_cov is not provided.","category":"page"},{"location":"emulate/#Normalization-and-standardization","page":"Emulator","title":"Normalization and standardization","text":"","category":"section"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"This arises from the optional arguments","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"normalize_inputs = true (default: true)","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"We normalize the input data in a standard way by centering, and scaling with the empirical covariance","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"standardize_outputs = true (default: false)\nstandardize_outputs_factors = factor_vector (default: nothing)","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"To help with poor conditioning of the covariance matrix, users can also standardize each output dimension with by a multiplicative factor given by the elements of factor_vector.","category":"page"},{"location":"emulate/#modular-interface","page":"Emulator","title":"Modular interface","text":"","category":"section"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"Developers may contribute new tools by performing the following","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"Create MyMLToolName.jl, and include \"MyMLToolName.jl\" in Emulators.jl\nCreate a struct MyMLTool <: MachineLearningTool, containing any arguments or optimizer options \nCreate the following three methods to build, train, and predict with your tool (use GaussianProcess.jl as a guide)","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"build_models!(mlt::MyMLTool, iopairs::PairedDataContainer) -> Nothing\noptimize_hyperparameters!(mlt::MyMLTool, args...; kwargs...) -> Nothing\nfunction predict(mlt::MyMLTool, new_inputs::Matrix; kwargs...) -> Matrix, Union{Matrix, Array{,3}","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"note: on dimensions of the predict inputs and outputs\nThe predict method takes as input, an input_dim-by-N_new matrix. It return both a predicted mean and a predicted (co)variance at new inputs. (i) for scalar-output methods relying on diagonalization, return output_dim-by-N_new matrices for mean and variance, (ii) For vector-output methods, return output_dim-by-N_new for mean and output_dim-by-output_dim-by-N_new for covariances.","category":"page"},{"location":"emulate/","page":"Emulator","title":"Emulator","text":"Please get in touch with our development team when contributing new statistical emulators, to help us ensure the smoothest interface with any new tools.","category":"page"},{"location":"#CalibrateEmulateSample.jl","page":"Home","title":"CalibrateEmulateSample.jl","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"CalibrateEmulateSample.jl solves parameter estimation problems using accelerated (and approximate) Bayesian inversion.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The framework can be applied currently to learn:","category":"page"},{"location":"","page":"Home","title":"Home","text":"the joint distribution for a moderate numbers of parameters (<40),\nit is not inherently restricted to unimodal distributions.","category":"page"},{"location":"","page":"Home","title":"Home","text":"It can be used with computer models that:","category":"page"},{"location":"","page":"Home","title":"Home","text":"can be noisy or chaotic,\nare non-differentiable,\ncan only be treated as black-box (interfaced only with parameter files).","category":"page"},{"location":"","page":"Home","title":"Home","text":"The computer model is supplied by the user, as a parameter-to-data map mathcalG(theta) mathbbR^p rightarrow mathbbR^d. For example, mathcalG could be a map from any given parameter configuration theta to a collection of statistics of a dynamical system trajectory. mathcalG is referred to as the forward model in the Bayesian inverse problem setting.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The data produced by the forward model are compared to observations y, which are assumed to be corrupted by additive noise eta, such that","category":"page"},{"location":"","page":"Home","title":"Home","text":"y = mathcalG(theta) + eta","category":"page"},{"location":"","page":"Home","title":"Home","text":"where the noise eta is drawn from a d-dimensional Gaussian with distribution mathcalN(0 Gamma_y).","category":"page"},{"location":"#The-inverse-problem","page":"Home","title":"The inverse problem","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Given an observation y, the computer model mathcalG, the observational noise Gamma_y, and some broad prior information on theta, we return the joint distribution of a data-informed distribution for \"theta given y\".","category":"page"},{"location":"","page":"Home","title":"Home","text":"As the name suggests, CalibrateEmulateSample.jl breaks this problem into a sequence of three steps: calibration, emulation, and sampling. A comprehensive treatment of the calibrate-emulate-sample approach to Bayesian inverse problems can be found in Cleary et al. (2020).","category":"page"},{"location":"#The-three-steps-of-the-algorithm:-see-our-walkthrough-of-the-[Sinusoid-Example](@ref)","page":"Home","title":"The three steps of the algorithm: see our walkthrough of the Sinusoid Example","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Learn the vertical shift and amplitude of the signal given the noisy observation","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"","page":"Home","title":"Home","text":"The calibrate step of the algorithm consists of an application of Ensemble Kalman Processes, which generates input-output pairs theta mathcalG(theta) in high density around an optimal parameter theta^*. Here, theta are amplitude and vertical shift pairs, and mathcalG(theta) are the resulting signal mean and range. This theta^* will be near a mode of the posterior distribution (Note: This is the only time we interface with the forward model mathcalG).","category":"page"},{"location":"","page":"Home","title":"Home","text":"calibrate with EKP to generate data pairs...","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"","page":"Home","title":"Home","text":"The emulate step takes these pairs theta mathcalG(theta) and trains a statistical surrogate model (e.g., a Gaussian process), emulating the forward map mathcalG.","category":"page"},{"location":"","page":"Home","title":"Home","text":"emulate the map statistically from EKP pairs... ","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"","page":"Home","title":"Home","text":"The sample step uses this surrogate in place of mathcalG in a sampling method (Markov chain Monte Carlo) to sample the posterior distribution of theta.","category":"page"},{"location":"","page":"Home","title":"Home","text":"sample the emulated map with MCMC...","category":"page"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"#Code-Components","page":"Home","title":"Code Components","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"CalibrateEmulateSample.jl contains the following modules:","category":"page"},{"location":"","page":"Home","title":"Home","text":"Module Purpose\nCalibrateEmulateSample.jl A wrapper for the pipeline\nEmulator.jl Modular template for the emulators\nGaussianProcess.jl A Gaussian process emulator\nScalar/VectorRandomFeatureInterface.jl A Scalar/Vector-output Random Feature emulator\nMarkovChainMonteCarlo.jl Modular template for Markov Chain Monte Carlo samplers\nUtilities.jl Helper functions","category":"page"},{"location":"#Authors","page":"Home","title":"Authors","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"CalibrateEmulateSample.jl is being developed by the Climate Modeling Alliance.","category":"page"},{"location":"examples/edmf_example/#Extended-Eddy-Diffusivity-Mass-Flux-(EDMF)-Scheme","page":"Turbulence example","title":"Extended Eddy-Diffusivity Mass-Flux (EDMF) Scheme","text":"","category":"section"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"info: How do I run this code?\nThe full code is found in the examples/ directory of the github repository","category":"page"},{"location":"examples/edmf_example/#Background","page":"Turbulence example","title":"Background","text":"","category":"section"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"The extended EDMF scheme is a unified model of turbulence and convection. More information about the model can be found here. This example builds an emulator of the extended EDMF scheme from input-output pairs obtained during a calibration process, and runs emulator-based MCMC to obtain an estimate of the joint parameter distribution.","category":"page"},{"location":"examples/edmf_example/#What-is-being-solved-here","page":"Turbulence example","title":"What is being solved here","text":"","category":"section"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"This example reads calibration data containing input-output pairs obtained during calibration of the EDMF scheme. The calibration is performed using ensemble Kalman inversion, an ensemble-based algorithm that updates the location of the input parameters from the prior to the posterior, thus ensuring an optimal placement of the data used to train the emulator. In this example, the input is formed by either two or five EDMF parameters, and the output is the time-averaged liquid water path (LWP) at 40 locations in the eastern Pacific Ocean. The calibration data also contains the prior distribution of EDMF parameters and the variance of the observed variables (LWP in this case), which is used as a proxy for the magnitude of observational noise.","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"More information about EDMF calibration can be found here. The calibration data is used to train the emulator.","category":"page"},{"location":"examples/edmf_example/#Running-the-examples","page":"Turbulence example","title":"Running the examples","text":"","category":"section"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"We have two example scenario data (output from a (C)alibration run) that must be simply unzipped before calibration:","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"ent-det-calibration.zip # two-parameter calibration\nent-det-tked-tkee-stab-calibration.zip # five-parameter calibration","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"To perform uncertainty quantification use the file uq_for_EDMF.jl. Set the experiment name, and date (for outputs), e.g.","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"exp_name = \"ent-det-tked-tkee-stab-calibration\" \ndate_of_run = Date(year, month, day)","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"and call,","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"> julia --project uq_for_EDMF.jl","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"info: Info\nThese runs take currently take ~1-3 hours to complete with Gaussian process emulator. Random feature training currently requires significant multithreading for performance and takes a similar amount of time.","category":"page"},{"location":"examples/edmf_example/#Solution-and-output","page":"Turbulence example","title":"Solution and output","text":"","category":"section"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"The solution is the posterior distribution, stored in the file posterior.jld2.","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"The posterior is visualized by using plot_posterior.jl, which produces corner-type scatter plots of posterior distribution, which show pairwise correlations. Again, set the exp_name and date_of_run values, then call","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"julia --project plot_posterior.jl","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"For example, using Random features for case exp_name = \"ent-det-calibration\" one obtains","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"and exp_name = \"ent-det-tked-tkee-stab-calibration\" or one obtains","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"The posterior samples can also be investigated directly. They are stored as a ParameterDistribution-type Samples object. One can load this and extract an array of parameters with:","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"# input:\n# path to posterior.jld2: posterior_filepath (string)\n\nusing CalibrateEmulateSample.ParameterDistribution\nposterior = load(posterior_filepath)[\"posterior\"]\nposterior_samples = vcat([get_distribution(posterior)[name] for name in get_name(posterior)]...) # samples are columns","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"To transform these samples into physical parameter space use the following:","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"transformed_posterior_samples =\nmapslices(x -> transform_unconstrained_to_constrained(posterior, x), posterior_samples, dims = 1)","category":"page"},{"location":"examples/edmf_example/","page":"Turbulence example","title":"Turbulence example","text":"info: Computational vs Physical space\nThe computational theta-space are the parameters on which the algorithms act. Statistics (e.g. mean/covariance) are most meaningful when taken in this space. The physical phi-space is a (nonlinear) transformation of the computational space to apply parameter constraints. To pass parameter values back into the forward model, one must transform them. Full details and examples can be found here","category":"page"}] }