text:
"A type storing the status at the end of a call to `ssa`:

- **termination_status** : whether the simulation stops at the final time (`finaltime`) or early due to zero propensity function (`zeroprop`)
- **nsteps** : the number of steps taken during the simulation.

"
struct SSAStats
    termination_status::String
    nsteps::Int64
end

"A type storing the call to `ssa`:

- **x0** : a `Vector` of `Int64`, representing the initial states of the system.
- **F** : a `Function` or a callable type, which itself takes two arguments; x, a `Vector` of `Int64` representing the states, and parms, a `Vector` of `Float64` representing the parameters of the system.
- **nu** : a `Matrix` of `Int64`, representing the transitions of the system, organised by row.
- **parms** : a `Vector` of `Float64` representing the parameters of the system.
- **tf** : the final simulation time (`Float64`).
- **alg** : the algorithm used (`Symbol`, either `:gillespie`, `jensen`, or `tjc`).
- **tvc** : whether rates are time varying.
"
struct SSAArgs
    x0::Vector{Int64}
    F::Any
    nu::Matrix{Int64}
    parms::Vector{Float64}
    tf::Float64
    alg::Symbol
    tvc::Bool
end

"
This type stores the output of `ssa`, and comprises of:

- **time** : a `Vector` of `Float64`, containing the times of simulated events.
- **data** : a `Matrix` of `Int64`, containing the simulated states.
- **stats** : an instance of `SSAStats`.
- **args** : arguments passed to `ssa`.

"
struct SSAResult
    time::Vector{Float64}
    data::Matrix{Int64}
    stats::SSAStats
    args::SSAArgs
end

"
This function is a substitute for `StatsBase.sample(wv::WeightVec)`, which avoids recomputing the sum and size of the weight vector, as well as a type conversion of the propensity vector. It takes the following arguments:

- **w** : an `Array{Float64,1}`, representing propensity function weights.
- **s** : the sum of `w`.
- **n** : the length of `w`.

"
function pfsample(w::Array{Float64,1},s::Float64,n::Int64)
    t = rand() * s
    i = 1
    cw = w[1]
    while cw < t && i < n
        i += 1
        @inbounds cw += w[i]
    end
    return i
end

"
This function performs Gillespie's stochastic simulation algorithm. It takes the following arguments:

- **x0** : a `Vector` of `Int64`, representing the initial states of the system.
- **F** : a `Function` or a callable type, which itself takes two arguments; x, a `Vector` of `Int64` representing the states, and parms, a `Vector` of `Float64` representing the parameters of the system.
- **nu** : a `Matrix` of `Int64`, representing the transitions of the system, organised by row.
- **parms** : a `Vector` of `Float64` representing the parameters of the system.
- **tf** : the final simulation time (`Float64`).
"
function gillespie(x0::Vector{Int64},F::Base.Callable,nu::Matrix{Int64},parms::Vector{Float64},tf::Float64)
    # Args
    args = SSAArgs(x0,F,nu,parms,tf,:gillespie,false)
    # Set up time array
    ta = Vector{Float64}()
    t = 0.0
    push!(ta,t)
    # Set up initial x
    nstates = length(x0)
    x = copy(x0')
    xa = copy(x0)
    # Number of propensity functions
    numpf = size(nu,1)
    # Main loop
    termination_status = "finaltime"
    nsteps = 0
    while t <= tf
        pf = F(x,parms)
        # Update time
        sumpf = sum(pf)
        if sumpf == 0.0
            termination_status = "zeroprop"
            break
        end
        dt = rand(Exponential(1/sumpf))
        t += dt
        push!(ta,t)
        # Update event
        ev = pfsample(pf,sumpf,numpf)
        deltax = view(nu,ev,:)
        for i in 1:nstates
            @inbounds x[1,i] += deltax[i]
        end
        for xx in x
            push!(xa,xx)
        end
        # update nsteps
        nsteps += 1
    end
    stats = SSAStats(termination_status,nsteps)
    xar = transpose(reshape(xa,length(x),nsteps+1))
    return SSAResult(ta,xar,stats,args)
end

"
This function performs the true jump method for piecewise deterministic Markov processes. It takes the following arguments:

- **x0** : a `Vector` of `Int64`, representing the initial states of the system.
- **F** : a `Function` or a callable type, which itself takes three arguments; x, a `Vector` of `Int64` representing the states, parms, a `Vector` of `Float64` representing the parameters of the system, and t, a `Float64` representing the time of the system.
- **nu** : a `Matrix` of `Int64`, representing the transitions of the system, organised by row.
- **parms** : a `Vector` of `Float64` representing the parameters of the system.
- **tf** : the final simulation time (`Float64`).
"
function truejump(x0::Vector{Int64},F::Base.Callable,nu::Matrix{Int64},parms::Vector{Float64},tf::Float64)
    # Args
    args = SSAArgs(x0,F,nu,parms,tf,:tjm,true)
    # Set up time array
    ta = Vector{Float64}()
    t = 0.0
    push!(ta,t)
    # Set up initial x
    nstates = length(x0)
    x = x0'
    xa = copy(x0)
    # Number of propensity functions
    numpf = size(nu,1)
    # Main loop
    termination_status = "finaltime"
    nsteps = 0
    while t <= tf
        ds = rand(Exponential(1.0))
        f = (u)->(quadgk((u)->sum(F(x,parms,u)),t,u)[1]-ds)
        newt = fzero(f,t)
        if newt>tf
          break
        end
        t=newt
        pf = F(x,parms,t)
        # Update time
        sumpf = sum(pf)
        if sumpf == 0.0
            termination_status = "zeroprop"
            break
        end
        push!(ta,t)
        # Update event
        ev = pfsample(pf,sumpf,numpf)
        deltax = view(nu,ev,:)
        for i in 1:nstates
            @inbounds x[1,i] += deltax[i]
        end
        for xx in x
            push!(xa,xx)
        end
        # update nsteps
        nsteps += 1
    end
    stats = SSAStats(termination_status,nsteps)
    xar = transpose(reshape(xa,length(x),nsteps+1))
    return SSAResult(ta,xar,stats,args)
end

"
This function performs stochastic simulation using thinning/uniformization/Jensen's method, returning only the thinned jumps. It takes the following arguments:

- **x0** : a `Vector` of `Int64`, representing the initial states of the system.
- **F** : a `Function` or a callable type, which itself takes two arguments; x, a `Vector` of `Int64` representing the states, and parms, a `Vector` of `Float64` representing the parameters of the system. In the case of time-varying systems, a third argument, a `Float64` representing the time of the system should be added
- **nu** : a `Matrix` of `Int64`, representing the transitions of the system, organised by row.
- **parms** : a `Vector` of `Float64` representing the parameters of the system.
- **tf** : the final simulation time (`Float64`).
- **max_rate**: the maximum rate (`Float64`).
"
function jensen(x0::Vector{Int64},F::Base.Callable,nu::Matrix{Int64},parms::Vector{Float64},tf::Float64,max_rate::Float64,thin::Bool=true)
    if thin==false
      return jensen_alljumps(x0::Vector{Int64},F::Base.Callable,nu::Matrix{Int64},parms::Vector{Float64},tf::Float64,max_rate::Float64)
    end
    tvc=true
    try
      F(x0,parms,0.0)
    catch
      tvc=false
    end
    # Args
    args = SSAArgs(x0,F,nu,parms,tf,:jensen,tvc)
    # Set up time array
    ta = Vector{Float64}()
    t = 0.0
    push!(ta,t)
    # Set up initial x
    nstates = length(x0)
    x = copy(x0')
    xa = copy(x0)
    # Number of propensity functions; one for no event
    numpf = size(nu,1)+1
    # Main loop
    termination_status = "finaltime"
    nsteps = 0
    while t <= tf
        dt = rand(Exponential(1/max_rate))
        t += dt
        if tvc
          pf = F(x,parms,t)
        else
          pf = F(x,parms)
        end
        # Update time
        sumpf = sum(pf)
        if sumpf == 0.0
            termination_status = "zeroprop"
            break
        end
        if sumpf > max_rate
            termination_status = "upper_bound_exceeded"
            break
        end
        # Update event
        ev = pfsample([pf; max_rate-sumpf],max_rate,numpf+1)
        if ev < numpf
          deltax = view(nu,ev,:)
          for i in 1:nstates
              @inbounds x[1,i] += deltax[i]
          end
          for xx in x
            push!(xa,xx)
          end
          push!(ta,t)
          # update nsteps
          nsteps += 1
        end
    end
    stats = SSAStats(termination_status,nsteps)
    xar = transpose(reshape(xa,length(x),nsteps+1))
    return SSAResult(ta,xar,stats,args)
end

"
This function performs stochastic simulation using thinning/uniformization/Jensen's method, returning all the jumps, both real and 'virtual'. It takes the following arguments:

- **x0** : a `Vector` of `Int64`, representing the initial states of the system.
- **F** : a `Function` or a callable type, which itself takes two arguments; x, a `Vector` of `Int64` representing the states, and parms, a `Vector` of `Float64` representing the parameters of the system. In the case of time-varying systems, a third argument, a `Float64` representing the time of the system should be added
- **nu** : a `Matrix` of `Int64`, representing the transitions of the system, organised by row.
- **parms** : a `Vector` of `Float64` representing the parameters of the system.
- **tf** : the final simulation time (`Float64`).
- **max_rate**: the maximum rate (`Float64`).
"
function jensen_alljumps(x0::Vector{Int64},F::Base.Callable,nu::Matrix{Int64},parms::Vector{Float64},tf::Float64,max_rate::Float64)
    # Args
    tvc=true
    try
      F(x0,parms,0.0)
    catch
      tvc=false
    end
    # Args
    args = SSAArgs(x0,F,nu,parms,tf,:jensen,tvc)
    # Set up time array
    ta = Vector{Float64}()
    t = 0.0
    push!(ta,t)
    while t < tf
      dt = rand(Exponential(1/max_rate))
      t += dt
      push!(ta,t)
    end
    nsteps=length(ta)-1
    # Set up initial x
    nstates = length(x0)
    x = copy(x0')
    xa = Array{Int64,1}(undef, (nsteps+1)*nstates)
    xa[1:nstates] = x
    # Number of propensity functions; one for no event
    numpf = size(nu,1)+1
    # Main loop
    termination_status = "finaltime"
    k=1 # step counter
    while k <= nsteps
        if tvc
          t=ta[k]
          pf=F(x,parms,t)
        else
          pf = F(x,parms)
        end
        sumpf = sum(pf)
        if sumpf == 0.0
            termination_status = "zeroprop"
            break
        end
        if sumpf > max_rate
            termination_status = "upper_bound_exceeded"
            break
        end
        # Update event
        ev = pfsample([pf; max_rate-sumpf],max_rate,numpf+1)
        if ev < numpf # true jump
          deltax = view(nu,ev,:)
          for i in 1:nstates
              @inbounds xa[k*nstates+i] = xa[(k-1)*nstates+i]+deltax[i]
          end
        else
          for i in 1:nstates
              @inbounds xa[k*nstates+i] = xa[(k-1)*nstates+i]
          end
        end
        k +=1
    end
    stats = SSAStats(termination_status,nsteps)
    xar = transpose(reshape(xa,length(x),nsteps+1))
    return SSAResult(ta,xar,stats,args)
end

"This takes a single argument of type `SSAResult` and returns a `DataFrame`."
function ssa_data(s::SSAResult)
    hcat(DataFrame(time=s.time),convert(DataFrame,s.data))
end


text:
using Oceananigans.Utils: prettysummary

struct FunctionField{LX, LY, LZ, C, P, F, G, T} <: AbstractField{LX, LY, LZ, G, T, 3}
          func :: F
          grid :: G
         clock :: C
    parameters :: P

    @doc """
        FunctionField{LX, LY, LZ}(func, grid; clock=nothing, parameters=nothing) where {LX, LY, LZ}

    Returns a `FunctionField` on `grid` and at location `LX, LY, LZ`.

    If `clock` is not specified, then `func` must be a function with signature
    `func(x, y, z)`. If clock is specified, `func` must be a function with signature
    `func(x, y, z, t)`, where `t` is internally determined from `clock.time`.

    A `FunctionField` will return the result of `func(x, y, z [, t])` at `LX, LY, LZ` on
    `grid` when indexed at `i, j, k`.
    """
    function FunctionField{LX, LY, LZ}(func::F, grid::G; clock::C=nothing, parameters::P=nothing) where {LX, LY, LZ, F, G, C, P}
        T = eltype(grid)
        return new{LX, LY, LZ, C, P, F, G, T}(func, grid, clock, parameters)
    end

    @doc """
        FunctionField{LX, LY, LZ}(func::FunctionField, grid; clock) where {LX, LY, LZ}

    Adds `clock` to an existing `FunctionField` and relocates it to `(LX, LY, LZ)` on `grid`.
    """
    function FunctionField{LX, LY, LZ}(f::FunctionField, grid::G; clock::C=nothing) where {LX, LY, LZ, G, C}
        P = typeof(f.parameters)
        T = eltype(grid)
        F = typeof(f.func)
        return new{LX, LY, LZ, C, P, F, G, T}(f.func, grid, clock, f.parameters)
    end
end

"""Return `a`, or convert `a` to `FunctionField` if `a::Function`"""
fieldify_function(L, a, grid) = a
fieldify_function(L, a::Function, grid) = FunctionField(L, a, grid)

"""
    FunctionField(L::Tuple, func, grid)

Returns a stationary `FunctionField` on `grid` and at location `L = (LX, LY, LZ)`,
where `func` is callable with signature `func(x, y, z)`.
"""
FunctionField(L::Tuple, func, grid) = FunctionField{L[1], L[2], L[3]}(func, grid)

# Various possibilities for calling FunctionField.func:
@inline call_func(clock, parameters, func, x, y, z)     = func(x, y, z, clock.time, parameters)
@inline call_func(::Nothing, parameters, func, x, y, z) = func(x, y, z, parameters)
@inline call_func(clock, ::Nothing, func, x, y, z)      = func(x, y, z, clock.time)
@inline call_func(::Nothing, ::Nothing, func, x, y, z)  = func(x, y, z)

# For setting ReducedField
@inline call_func(::Nothing, ::Nothing, func, x, y)     = func(x, y)
@inline call_func(::Nothing, ::Nothing, func, x)        = func(x)

@inline Base.getindex(f::FunctionField{LX, LY, LZ}, i, j, k) where {LX, LY, LZ} =
    call_func(f.clock, f.parameters, f.func, node(LX(), LY(), LZ(), i, j, k, f.grid)...)

@inline (f::FunctionField)(x...) = call_func(f.clock, f.parameters, f.func, x...)

Adapt.adapt_structure(to, f::FunctionField{LX, LY, LZ}) where {LX, LY, LZ} =
    FunctionField{LX, LY, LZ}(Adapt.adapt(to, f.func),
                           Adapt.adapt(to, f.grid),
                           clock = Adapt.adapt(to, f.clock),
                           parameters = Adapt.adapt(to, f.parameters))

Base.show(io::IO, field::FunctionField) =
    print(io, "FunctionField located at ", show_location(field), '\n',
          "├── func: $(prettysummary(field.func))", '\n',
          "├── grid: $(summary(field.grid))\n",
          "├── clock: $(summary(field.clock))\n",
          "└── parameters: $(field.parameters)")

ext: jl


text:
function DormandPrince54Integrator(arg0::jdouble, arg1::jdouble, arg2::Vector{jdouble}, arg3::Vector{jdouble})
    return DormandPrince54Integrator((jdouble, jdouble, Vector{jdouble}, Vector{jdouble}), arg0, arg1, arg2, arg3)
end

function DormandPrince54Integrator(arg0::jdouble, arg1::jdouble, arg2::jdouble, arg3::jdouble)
    return DormandPrince54Integrator((jdouble, jdouble, jdouble, jdouble), arg0, arg1, arg2, arg3)
end

function get_a(obj::DormandPrince54Integrator)
    return jcall(obj, "getA", Vector{Vector{jdouble}}, ())
end

function get_b(obj::DormandPrince54Integrator)
    return jcall(obj, "getB", Vector{jdouble}, ())
end

function get_c(obj::DormandPrince54Integrator)
    return jcall(obj, "getC", Vector{jdouble}, ())
end

function get_max_growth(obj::EmbeddedRungeKuttaIntegrator)
    return jcall(obj, "getMaxGrowth", jdouble, ())
end

function get_min_reduction(obj::EmbeddedRungeKuttaIntegrator)
    return jcall(obj, "getMinReduction", jdouble, ())
end

function get_order(obj::DormandPrince54Integrator)
    return jcall(obj, "getOrder", jint, ())
end

function get_safety(obj::EmbeddedRungeKuttaIntegrator)
    return jcall(obj, "getSafety", jdouble, ())
end

function integrate(obj::EmbeddedRungeKuttaIntegrator, arg0::ExpandableODE, arg1::ODEState, arg2::jdouble)
    return jcall(obj, "integrate", ODEStateAndDerivative, (ExpandableODE, ODEState, jdouble), arg0, arg1, arg2)
end

function set_max_growth(obj::EmbeddedRungeKuttaIntegrator, arg0::jdouble)
    return jcall(obj, "setMaxGrowth", void, (jdouble,), arg0)
end

function set_min_reduction(obj::EmbeddedRungeKuttaIntegrator, arg0::jdouble)
    return jcall(obj, "setMinReduction", void, (jdouble,), arg0)
end

function set_safety(obj::EmbeddedRungeKuttaIntegrator, arg0::jdouble)
    return jcall(obj, "setSafety", void, (jdouble,), arg0)
end


text:
using CSV, DataFrames

export _select
export _except
export _starts_with
export _ends_with
export _contains
export _mutate
export _filter
export _arrange
export _summarise
export _summarize
export _group_by
export _left_join
export _right_join
export _inner_join
export _outer_join
export _gather
export _spread
export _head
export _tail
export _rename
export _slice
export _desc
export summarise_cols
export summarize_cols
export _read_csv
export _write_csv

# select
function _except(df, x)
    col_order = Dict(zip(1:length(names(df)), names(df)))
    col_order = DataFrame(order=collect(keys(col_order)), col=collect(values(col_order)))
    keep_cols = setdiff(Set(names(df)), Set(x)) |> collect
    return sort(col_order[in.(col_order.col, (keep_cols,)), :], :order)[!, :col]
end
_starts_with(df, x) = names(df)[startswith.(string.(names(df)), x)]
_ends_with(df, x) = names(df)[endswith.(string.(names(df)), x)]
_contains(df, x) = names(df)[occursin.(string.(names(df)), x)]
"""
    select columns from a dataframe

    parameters:
        args[1] : DataFrame
            dataframe to select from
        args[2:end] : Symbol
            arbitrary number of columns to select

    returns: DataFrame
        selected columns of the dataframe

    example:
        df |> x->
            _select(x, :col1, :col2, [:col3, :col4])
        df |> x->
            _select(x, _except(x, [:col1, :col2]))
"""
function _select(args...)
    args[1][!, vcat(args[2:end]...)]
end

# mutate
"""
    create new columns in a dataframe

    parameters:
        df : DataFrame
            dataframe to mutate
        kwargs :
            column names and values, values can either be a scalar or vector of same length as number of rows of dataframe

    returns: DataFrame
        dataframe with mutated columns. If same name given to column, will update values in place.

    example:
        df |> x->
            _mutate(x, new_col=10, new_col2=x.old .+ 1)
"""
function _mutate(df::DataFrame; kwargs...)
    new_df = copy(df)
    for (new_col, values) in Dict(kwargs)
        new_df[!, Symbol(new_col)] .= values
    end
    return new_df
end

# filter
"""
    filter a dataframe row-wise

    parameters:
        args[1] : DataFrame
            dataframe to filter
        args[2:end] : BitArray
            arbitrary number of arrays boolean BitArrays

    returns: DataFrame
        dataframe with filtered rows. Subsequent kwargs will be treated as AND operators

    example:
        df |> x->
            _filter(x, x.value .> 10, x.value2 .< 5, (x.value3 .== 1) .| (x.value4 .== 2))
"""
function _filter(args...)
    new_df = copy(args[1])
    conds = [minimum(x) for x in eachrow(hcat(collect(args[2:end])...))]
    new_df[conds, :]
end

# arrange
"""
    sort a dataframe

    parameters:
        args[1] : DataFrame
            dataframe to sort
        args[2:end] : Symbol
            columns to be sorted by, in order input. _desc(:col) will sort Z to A

    returns: DataFrame
        sorted dataframe

    example:
        df |> x->
            _arrange(x, :col1, _desc(:col2))
"""
_desc(x) = order(x, rev=true)
function _arrange(args...)
    sort(args[1], args[2:end])
end

#summarise
"""
    summarise columns of a dataframe

    parameters:
        args[1] : DataFrame
            dataframe to summarise
        args[2:end] : Pair
            (optional) column and function to be summarised, e.g. :col => sum
        kwargs : Pair
            (optional) name of new column, column and function to be summarised, e.g. new_col = :col => sum

    returns: DataFrame
        summarised dataframe

    example:
        df |> x->
            _summarise(x, new_col = :col => sum)

    notes:
        parameters must be passed either as all args (default new column names), or all kwargs (named new column names)
        can be used with summarise_cols function to summarise many columns without explicitly typing them out (only works for column names with no spaces)
            e.g.: data |> x->
                    _summarise(x, summarise_cols([:col1, :col2], "mean")...)
"""
function _summarise(args...; kwargs...)
    typeof(args[1]) == GroupedDataFrame{DataFrame} ? df = args[1] : df = DataFrames.groupby(args[1], [])
    if !isempty(kwargs)
        new_df = combine(values(kwargs), df)
    else
        new_df = combine(args[2:end], df)
    end
    return new_df
end
_summarize = _summarise
summarise_cols(cols, operator) = eval(Meta.parse(replace(":" .* (cols .|> string) .* " => $operator" .|> string |> string, r"\"|\[|\]"=>"")))
summarize_cols = summarise_cols

# group by
"args[1] = dataframe to group, args[2:end = column names to group by (Symbols)]"
function _group_by(args...)
    DataFrames.groupby(args[1], collect(args[2:end]))
end

# join
"""
    identical functionality to DataFrames.join, reproduced here for syntactical continuity

    parameters:
        a : DataFrame
            original dataframe
        b : DataFrame
            dataframe to join to a
        on : Dict{Symbol, Symbol} | Symbol
            key columns, e.g. Dict(:ida => :idb, :id2a => :id2b), or just :id if the id column is named the same in both dataframes

    returns: DataFrame
        joined dataframe

    example:
        df |> x->
            _left_join(x, y, Dict(:ida => :idb))
"""
function _macro_join(a::DataFrame, b::DataFrame; on, kind)
    typeof(on) == Dict{Symbol, Symbol} ? join_on = [Pair(key, value) for (key, value) in on] : join_on = on
    join(a, b, on=join_on, kind=kind, makeunique=true)
end
_left_join(a, b; on) = _macro_join(a, b; on=on, kind=:left)
_right_join(a, b; on) = _macro_join(a, b; on=on, kind=:right)
_inner_join(a, b; on) = _macro_join(a, b; on=on, kind=:inner)
_outer_join(a, b; on) = _macro_join(a, b; on=on, kind=:outer)

# gather
"""
    convert a dataframe from long format to wide format

    parameters:
        df : DataFrame
            original dataframe
        key : Symbol
            what to name the new key column (previously the wide column names)
        value : Symbol
            what to call the new value column
        factor_cols :  Array{Symbol}
            which columns are factors and should not be put into the key column

    returns: DataFrame
        long dataframe

    example:
        df |> x->
            _gather(x, key=:country, value=:population, factor_cols=[:date])
"""
function _gather(df::DataFrame; key=:type, value=:value, factor_cols)
    non_factor_cols = collect(setdiff(Set(names(df)), Set(factor_cols)))
    new_df = stack(df, non_factor_cols)
    rename!(new_df, Dict(:variable => key, :value => value))
    col_order = [factor_cols; key; value]
    return new_df[!, col_order]
end

# spread
"identical to DataFrames.unstack, reproduced here for syntactical continuity"
_spread = unstack

# head / tail
"return the first n rows of a dataframe"
function _head(df::DataFrame, n=5)
    first(df, n)
end

"return the last n rows of a dataframe"
function _tail(df::DataFrame, n=5)
    df[end-n+1:end,:]
end

# rename
"""
    rename columns of a dataframe

    parameters:
        df : DataFrame
            original dataframe
        kwargs : new_name=:old_name
            arbitrary number of new colum names to rename old columns

    returns: DataFrame
        dataframe with renamed columns

    example:
        df |> x->
            _rename(x, new_name=:old_name, new2=:old2)
"""
function _rename(df::DataFrame; kwargs...)
    rename(df, Dict(zip(values(kwargs), Symbol.(keys(kwargs)))))
end

# slice
"return selected rows of form 1:10 of a dataframe"
function _slice(df::DataFrame, rows)
    return df[rows, :]
end

# read csv
"pass CSV.read to a dataframe, takes same kwargs as CSV.read"
function _read_csv(path::String; kwargs...)
    CSV.read(path; kwargs...) |> DataFrame
end

# write csv
"write df to a CSV, takes same kwargs as CSV.write"
function _write_csv(df::DataFrame, path::String; kwargs...)
    CSV.write(path, df; kwargs...)
end


text:
# This file was generated by the Julia Swagger Code Generator
# Do not modify this file directly. Modify the swagger specification instead.

mutable struct PrepareNetworkPoliciesRequest <: SwaggerModel
    serviceName::Any # spec type: Union{ Nothing, String } # spec name: serviceName
    networkIntentPolicyConfigurations::Any # spec type: Union{ Nothing, Vector{NetworkIntentPolicyConfiguration} } # spec name: networkIntentPolicyConfigurations

    function PrepareNetworkPoliciesRequest(;serviceName=nothing, networkIntentPolicyConfigurations=nothing)
        o = new()
        validate_property(PrepareNetworkPoliciesRequest, Symbol("serviceName"), serviceName)
        setfield!(o, Symbol("serviceName"), serviceName)
        validate_property(PrepareNetworkPoliciesRequest, Symbol("networkIntentPolicyConfigurations"), networkIntentPolicyConfigurations)
        setfield!(o, Symbol("networkIntentPolicyConfigurations"), networkIntentPolicyConfigurations)
        o
    end
end # type PrepareNetworkPoliciesRequest

const _property_map_PrepareNetworkPoliciesRequest = Dict{Symbol,Symbol}(Symbol("serviceName")=>Symbol("serviceName"), Symbol("networkIntentPolicyConfigurations")=>Symbol("networkIntentPolicyConfigurations"))
const _property_types_PrepareNetworkPoliciesRequest = Dict{Symbol,String}(Symbol("serviceName")=>"String", Symbol("networkIntentPolicyConfigurations")=>"Vector{NetworkIntentPolicyConfiguration}")
Base.propertynames(::Type{ PrepareNetworkPoliciesRequest }) = collect(keys(_property_map_PrepareNetworkPoliciesRequest))
Swagger.property_type(::Type{ PrepareNetworkPoliciesRequest }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_PrepareNetworkPoliciesRequest[name]))}
Swagger.field_name(::Type{ PrepareNetworkPoliciesRequest }, property_name::Symbol) =  _property_map_PrepareNetworkPoliciesRequest[property_name]

function check_required(o::PrepareNetworkPoliciesRequest)
    true
end

function validate_property(::Type{ PrepareNetworkPoliciesRequest }, name::Symbol, val)
end


text:
import AlphaZero.GI
using AlphaZero:AbstractSchedule, ConstSchedule
using GraphNeuralNetworks
using Random
using Crayons

i2mn(i, M, N) = CartesianIndices((M,N))[i]
mn2i(m, n, M, N) = LinearIndices((M,N))[m,n]

struct GameSpec <: GI.AbstractGameSpec
  M::Pair{AbstractSchedule, AbstractSchedule}
  N::Pair{AbstractSchedule, AbstractSchedule}
  P::Pair{UInt8, UInt8}
end

function generate_conjuctive_edges(rng::AbstractRNG, M, N, N_NODES, T, S)
  order = reduce(vcat,[(randperm(rng, M).+i*M) for i in 0:N-1])#flattend order of operations
  target = zeros(UInt8, N_NODES+1+N)
  target[T] = T
  n = 0
  for i in 1:N*M
    if(i%M == 1) #first in row: s->
      target[S+n] = order[i]
    end
    if(i%M == 0)#last in row: ->t
      target[order[i]] = T
      n += 1
    else #propagate
      target[order[i]] = order[i+1]
    end
  end
  return target
end

function generate_done_time(p_time, conj_tar, start_edges, S, T)
  done_time = zeros(UInt16, S)
  for o in start_edges
    last_done_time = 0
    while(true)#propagate expected done time
      o = conj_tar[o]
      last_done_time = done_time[o] = max(last_done_time + p_time[o], done_time[o])
      o == T && break
    end
  end
  return done_time
end

mutable struct GameEnv <: GI.AbstractGameEnv
  #Problem instance
  process_time::Vector{UInt8} #Index in Mxn
  conj_src::Vector{UInt8}
  conj_tar::Vector{UInt8}
  M::UInt8
  N::UInt8
  N_NODES::UInt16
  T::UInt16
  S::UInt16
  UB::UInt16
  LB::UInt16
  #State
  disj_src::Vector{UInt8}
  disj_tar::Vector{UInt8}
  is_done::Vector{Bool}
  done_time::Vector{UInt16}
  #Info
  prev_operation::Vector{UInt8}
  prev_machine::Vector{UInt8}
end

function GI.init(spec::GameSpec, itc::Int, rng::AbstractRNG)
  M = rand(rng, spec.M.first[itc]:spec.M.second[itc])
  N = rand(rng, spec.N.first[itc]:spec.N.second[itc])
  N_NODES = M*N #[nodes, T, S]
  T = M*N+1
  S = M*N+2
  p_time = [rand(rng, spec.P.first:spec.P.second, N_NODES); 0; 0] #Nodes time plus t, s = 0
  conj_tar = generate_conjuctive_edges(rng, M, N, N_NODES, T, S)
  start_edges_n = collect(0:N-1) .+ S
  start_edges_m = collect(0:M-1) .+ S
  return GameEnv(
    #Problem instance
    p_time,
    [collect(1:N_NODES)..., T, S * ones(N)...],
    conj_tar,
    M,
    N,
    N_NODES,
    T,
    S,
    sum(p_time),
    maximum(sum.([p_time[i*M+1:(i+1)*M] for i in 0:N-1])),
    #State
    [collect(1:N_NODES)..., T, S * ones(M)...],
    [collect(1:N_NODES)..., T, S * ones(M)...],
    [falses(N_NODES)..., false, true], #[nodes, T, S]
    generate_done_time(p_time, conj_tar, start_edges_n, S, T),
    #Info
    start_edges_n,
    start_edges_m
  )
end

GI.init(spec::GameSpec, s) = GameEnv(
  #Static values
  s.process_time,
  s.conj_src,
  s.conj_tar,
  s.M,
  s.N,
  s.N_NODES,
  s.T,
  s.S,
  s.UB,
  s.LB,
  #Mutable values
  copy(s.disj_src),
  copy(s.disj_tar),
  copy(s.is_done),
  copy(s.done_time),
  copy(s.prev_operation),
  copy(s.prev_machine),
)

GI.spec(g::GameEnv) = GameSpec(ConstSchedule(g.M)=>ConstSchedule(g.M), ConstSchedule(g.N)=>ConstSchedule(g.N), 1=>5)

GI.two_players(::GameSpec) = false

GI.state_dim(spec::GameSpec) = (2, (spec.M.second[1]*spec.N.second[1]+2))#Opperations + source and sink

function GI.set_state!(g::GameEnv, s)
  g.process_time = s.process_time
  g.conj_src = s.conj_src
  g.conj_tar = s.conj_tar
  g.M = s.M
  g.N = s.N
  g.N_NODES = s.N_NODES
  g.T = s.T
  g.S = s.S
  g.UB = s.UB
  g.LB = s.LB
  g.disj_src = copy(s.disj_src)
  g.disj_tar = copy(s.disj_tar)
  g.is_done = copy(s.is_done)
  g.done_time = copy(s.done_time)
  g.prev_operation = copy(s.prev_operation)
  g.prev_machine = copy(s.prev_machine)
end

GI.current_state(g::GameEnv) = (
  process_time = g.process_time,
  conj_src = g.conj_src,
  conj_tar = g.conj_tar,
  M = g.M,
  N = g.N,
  N_NODES = g.N_NODES,
  T = g.T,
  S = g.S,
  UB = g.UB,
  LB = g.LB,
  disj_src = copy(g.disj_src),
  disj_tar = copy(g.disj_tar),
  is_done = copy(g.is_done),
  done_time = copy(g.done_time),
  prev_operation = copy(g.prev_operation),
  prev_machine = copy(g.prev_machine),
)

GI.white_playing(g::GameEnv) = true

GI.game_terminated(g::GameEnv) = all(g.conj_tar[g.prev_operation].==g.T)

GI.actions(spec::GameSpec) = collect(1:(spec.M.second[1]*spec.N.second[1]+2))

GI.available_actions(g::GameEnv) = filter(x->x!=g.T, g.conj_tar[g.prev_operation])

function GI.actions_mask(g::GameEnv)
  valid_action = zeros(Bool, g.S)
  valid_action[g.conj_tar[g.prev_operation]] .= true
  valid_action[g.T] = false #We cant schedule sink node
  return valid_action
end

function GI.play!(g::GameEnv, o)
  #mark operation scheduled
  g.is_done[o] = true
  mn = i2mn(o, g.M, g.N)
  #update previous operation and machine
  k = g.prev_machine[mn[1]] #previous operation done on machine of todo operation
  l = g.prev_operation[mn[2]] #previous operation done in job of todo operation
  #update info vectors
  g.prev_machine[mn[1]] = o
  g.prev_operation[mn[2]] = o
  #determine if all opperations are done
  GI.game_terminated(g) && (g.is_done[g.T] = true)
  #add disjunctive link
  g.disj_tar[k] = o
  #convert from edge to node notation
  l = min(l, g.S)
  k = min(k, g.S)
  #update done time
  last_done_time = g.done_time[o] = max(g.done_time[l], g.done_time[k] * g.is_done[k]) + g.process_time[o]
  while(true)#propagate expected done time
    o = g.conj_tar[o]
    last_done_time = g.done_time[o] = max(g.done_time[o], last_done_time + g.process_time[o])
    o == g.T && return
  end
end

function GI.white_reward(g::GameEnv)
  if(all(g.is_done))
    #return -convert(Float32, g.done_time[g.T])
    return ((g.UB - g.done_time[g.T])/(g.UB - g.LB))
  end
  return 0
end

function GI.vectorize_state(::GameSpec, state) #
  return  GNNGraph([state.conj_src; state.disj_src],
                   [state.conj_tar; state.disj_tar],
                   num_nodes = state.S,
                   ndata = Float32.(hcat(state.done_time, state.is_done)'))
end

#####
##### Interaction APIc
#####

function GI.action_string(spec::GameSpec, o)
  mn = i2mn(o, spec.M.second, spec.N.second)
  return string("job: ", mn[2], " machine: ", mn[1])
end

function GI.parse_action(spec::GameSpec, str)
  try
    s = split(str)
    @assert length(s) == 2
    n = parse(Int, s[1])
    m = parse(Int, s[2])
    return mn2i(m,n, spec.M.second, spec.N.second)
  catch e
    return nothing
  end
end

function GI.read_state(::GameSpec)#input problem
  return nothing
end

function GI.render(g::GameEnv)
  for (m,o) in enumerate(g.disj_tar[g.S:end])
    print(crayon"white", "m", m, ":")
    o == g.S && (println(); continue)
    last_op = 0
    while(true)
      mn = i2mn(o, g.M, g.N)
      idle = (crayon"dark_gray", repeat("-", g.done_time[o] - (last_op + g.process_time[o])))
      active = (Crayon(foreground = mn[2]), repeat("=", g.process_time[o]))
      print(idle..., active...)
      last_op = g.done_time[o]
      g.disj_tar[o] == o && break
      o = g.disj_tar[o]
    end
    println(crayon"reset")
  end
  for n in 1:g.N
    print(Crayon(foreground = n), "n", n, " ")
  end
  println(crayon"reset")
end


text:
set_scheduler_update_second(0.05)

scheduler_status()

@time for i in 1:100
    local job = Job() do
        threadid()
    end
    submit!(job)
    if 1 == fetch(job.task)
        error("Test fail. Assigning jobs to thread 1 is not allowed, but observed.")
    end
end


text:
using Mdp.FH

# Define simple FH domain (See figure in docs)
S = [1,2] # States
A = [1,2] # Actions
N = 1:3 # timesteps
T = Dict(   # Transitions, prob = T[(state, action, next_state, timestep)]
    (1,1,1,1)=>1.,
    (1,2,1,1)=>0.5,
    (1,2,2,1)=>0.5,
    (2,1,2,1)=>1.,
    (1,1,1,2)=>1.,
    (1,2,1,2)=>0.7,
    (1,2,2,2)=>0.3,
    (2,1,2,2)=>1.,
)
R = Dict( # Rewards, reward = R[(state, action, next_state, timestep)]
    (1,1,1,1)=>0.,
    (1,2,1,1)=>0.,
    (1,2,2,1)=>1.,
    (2,1,2,1)=>0.,
    (1,1,1,2)=>0.,
    (1,2,1,2)=>0.,
    (1,2,2,2)=>1.7,
    (2,1,2,2)=>0.,
)

V, π = finite_horizon(S,A,N,T,R)
@test V==[[0.755,0.] [0.51, 0.] [ 0., 0.]]
@test π[:, 1:end-1]==[[2,1] [2, 1]]


text:
using LegendHDF5IO: _nt_to_range, _range_to_nt

@testset "Range <-> NamedTuple" begin
    @testset "UnitRange" begin
        @test _nt_to_range(_range_to_nt(1:10)) == 1:10
    end
    @testset "StepRange" begin
        @test _nt_to_range(_range_to_nt(1:2:10)) == 1:2:10
    end
    @testset "LinRange" begin
        @test _nt_to_range(_range_to_nt(LinRange(1, 10, 3))) == LinRange(1, 10, 3)
    end
    @testset "StepRangeLen" begin
        @test _nt_to_range(_range_to_nt(StepRangeLen(1.0:0.3:1.7))) == StepRangeLen(1.0:0.3:1.7)
    end
end


text:
#L1HingeLoss

using LaTeXStrings, LossFunctions, Measures, Latexify

Plots.plot(L1HingeLoss(), c=:olive, linewidth=2, annotation=(1, 1.6, L"L\left( a \right) = max\{0,1, - a \}", 18))

# smoothed

Plots.plot(SmoothedL1HingeLoss(2), leg=:topright, c=:olive, linewidth=2)
Plots.plot!(SmoothedL1HingeLoss(1.5), c=:orangered4, linewidth=2.5)
Plots.plot!(SmoothedL1HingeLoss(1), c=:springgreen4, linewidth=2.5)
Plots.plot!(SmoothedL1HingeLoss(.5), c=:springgreen4, linewidth=2.5)

max_stars_repo_name: Ellon-M/visualizations

max_issues_repo_name: Ellon-M/visualizations

max_forks_repo_name: Ellon-M/visualizations


text:
module HiddenMarkovModels

importall DynamicDiscreteModels
importall Distributions
using StatsBase:sample,WeightVec,StatisticalModel

# When I get around to spinning of a Markov.jl
# import Markov: rsm, nsm, z2q, q2z
include("stochasticmatrices.jl")

# Ben's exports
export 	coef!, rand, loglikelihood, mle, dim,
		em, viterbi,
		baumwelch, hmm, theta2ab

#Alex's exports
export	HMM, forward_backward, viterbi, smoothed_forward_backward, fit!

#Ben's sources
include("hiddenmarkovmodel.jl")

#Alex's sources
include("HMM.jl")
include("forward_backward.jl")
include("fit.jl")

end


text:
using Test, Astro

# solve_kepler(mean_anomaly, eccentricity, desired_accuracy = 1e-6)

println("Kepler's equation")
print("Duffett-Smith PA with your Computer, page 116 ")

eccentric_anomaly = solve_kepler(deg2rad(201.7292), 0.016718) |> rad2deg
@test isapprox(eccentric_anomaly, 201.38, atol=.01)

eccentric_anomaly = solve_kepler(deg2rad(43.7172), 0.965) |> rad2deg
@test isapprox(eccentric_anomaly, 98.41, atol=.01)

# circular orbit
eccentric_anomaly = solve_kepler(deg2rad(60), 0.0) |> rad2deg
@test isapprox(eccentric_anomaly, 60, atol=.001)

println("passed")


text:
using Test

using MathOptInterface
const MOI = MathOptInterface
const MOIU = MathOptInterface.Utilities

struct DummyOptimizer <: MOI.AbstractOptimizer end
MOI.is_empty(::DummyOptimizer) = true

@testset "Instantiate with $T" for T in [Float64, Int]
    f() = MOIU.MockOptimizer(MOIU.UniversalFallback(MOIU.Model{T}()))
    optimizer_constructor = MOI.OptimizerWithAttributes(f, MOI.Silent() => true, "a" => 1, "b" => 2)
    optimizer = MOI.instantiate(optimizer_constructor)
    @test optimizer isa MOIU.MockOptimizer{MOIU.UniversalFallback{MOIU.Model{T}}}
    @test MOI.get(optimizer, MOI.Silent())
    for with_names in [true, false]
        optimizer = MOI.instantiate(optimizer_constructor, with_bridge_type=T, with_names=with_names)
        @test optimizer isa MOI.Bridges.LazyBridgeOptimizer{MOIU.MockOptimizer{MOIU.UniversalFallback{MOIU.Model{T}}}}
        @test MOI.get(optimizer, MOI.Silent())
        @test MOI.get(optimizer, MOI.RawParameter("a")) == 1
        @test MOI.get(optimizer, MOI.RawParameter("b")) == 2
    end

    optimizer_constructor = MOI.OptimizerWithAttributes(DummyOptimizer, [])
    optimizer = MOI.instantiate(optimizer_constructor)
    @test optimizer isa DummyOptimizer
    for with_names in [true, false]
        optimizer = MOI.instantiate(optimizer_constructor, with_bridge_type=T, with_names=with_names)
        @test optimizer isa MOI.Bridges.LazyBridgeOptimizer{MOIU.CachingOptimizer{DummyOptimizer, MOIU.UniversalFallback{MOIU.Model{T}}}}
    end

    err = ErrorException("The provided `optimizer_constructor` returned a non-empty optimizer.")
    function g()
        model = f()
        MOI.add_variable(model)
        return model
    end
    @test_throws err MOI.instantiate(g)
    @test_throws err MOI.instantiate(g, with_bridge_type=T)
    optimizer_constructor = MOI.OptimizerWithAttributes(g)
    @test_throws err MOI.instantiate(optimizer_constructor)
    @test_throws err MOI.instantiate(optimizer_constructor, with_bridge_type=T)

    err = ErrorException(MOI._INSTANTIATE_NOT_CALLABLE_MESSAGE)
    @test_throws err MOI.OptimizerWithAttributes(1)
    @test_throws err MOI.OptimizerWithAttributes(1, MOI.Silent() => true)
    @test_throws err MOI.instantiate(1)
    @test_throws err MOI.instantiate(1, with_bridge_type=T)

    err = ErrorException("The provided `optimizer_constructor` returned an object of type " *
        "$Int. Expected a MathOptInterface.AbstractOptimizer.")
    h() = 1
    @test_throws err MOI.instantiate(h)
    @test_throws err MOI.instantiate(h, with_bridge_type=T)
    optimizer_constructor = MOI.OptimizerWithAttributes(h)
    @test_throws err MOI.instantiate(optimizer_constructor)
    @test_throws err MOI.instantiate(optimizer_constructor, with_bridge_type=T)
end


text:
using PyPlot, Test, Random, Revise, Statistics, LinearAlgebra
any(pwd() .== LOAD_PATH) || push!(LOAD_PATH, pwd())
import GP, TransD_GP
## make options for the multichannel lengthscale GP
nminlog10λ, nmaxlog10λ = 2, 20
pnorm = 2.
Klog10λ = GP.Mat32()
λx = 1
x = 0:(0.01λx):λx
λlog10λ = [0.05maximum(x)]
demean = false
sdev_poslog10λ = [0.01maximum(x)]
log10bounds = [-1 -0.69]
δlog10λ = 0.1
sdev_proplog10λ = [0.1]
xall = permutedims(collect(x))
xbounds = permutedims([extrema(x)...])
## Initialize a model using these options
Random.seed!(12)
optlog10λ = TransD_GP.OptionsStat(nmin = nminlog10λ,
                        nmax = nmaxlog10λ,
                        xbounds = xbounds,
                        fbounds = log10bounds,
                        xall = xall,
                        λ = λlog10λ,
                        δ = δlog10λ,
                        demean = demean,
                        sdev_prop = sdev_proplog10λ,
                        sdev_pos = sdev_poslog10λ,
                        pnorm = pnorm,
                        quasimultid = false,
                        K = Klog10λ,
                        timesλ = 3.
                        )
@time  log10λ = TransD_GP.init(optlog10λ)
## make options for the nonstationary GP
nmin, nmax = 2, 20
fbounds = [-2. 2]
δ = 0.1
sdev_prop = [0.1]
sdev_pos = [0.05]
demean_ns = true
K = GP.Mat32()
## Initialize model for the nonstationary GP
Random.seed!(13)
opt = TransD_GP.OptionsNonstat(optlog10λ;
                        nmin = nmin,
                        nmax = nmax,
                        fbounds = fbounds,
                        δ = δ,
                        demean = demean_ns,
                        sdev_prop = sdev_prop,
                        sdev_pos = sdev_pos,
                        pnorm = pnorm,
                        K = K
                        )
mns = TransD_GP.init(opt, log10λ)
## update λ and mns.fstar through birth in λ
doall = false
lold = copy(log10λ.fstar)
TransD_GP.birth!(log10λ, optlog10λ, mns, opt, doall=doall)
lsc = TransD_GP.testupdate(optlog10λ, log10λ)
ftest = TransD_GP.testupdate(opt, log10λ, mns)

f, ax = plt.subplots(2, 1, sharex=true)
ax[1].plot(xall', sqrt.(log10λ.fstar)')
ax[1].plot(xall', sqrt.(lold)')
ax[1].plot(xall', 10 .^lsc, "--k")
ax[1].plot(log10λ.xtrain[:,1:log10λ.n]', 10 .^(log10λ.ftrain[1:log10λ.n]), "+m")
ax[1].plot(log10λ.xtrain[:,log10λ.n]', 10^(log10λ.ftrain[log10λ.n]), ".r", markersize=10)
ax[1].set_title("λ")

ax[2].plot(xall', mns.fstar)
ax[2].plot(xall', ftest)
ax[2].plot(mns.xtrain[:,1:mns.n]', mns.ftrain[1:mns.n], "xr")
ax[2].set_title("function")

ax2 = ax[1].twinx()
ax2.plot(xall', log10.(abs.(lold' -10 .^2lsc)))
ax[1].grid()
ax[2].grid()
## update mns.fstar through birth in mns
TransD_GP.birth!(mns, opt, log10λ)
lsc = TransD_GP.testupdate(optlog10λ, log10λ)
ftest = TransD_GP.testupdate(opt, log10λ, mns)

f, ax = plt.subplots(2, 1, sharex=true)
ax[1].plot(xall', sqrt.(log10λ.fstar)')
ax[1].plot(xall', 10 .^lsc, "--k")
ax[1].plot(log10λ.xtrain[:,1:log10λ.n]', 10 .^(log10λ.ftrain[1:log10λ.n]), "+m")
ax[1].plot(log10λ.xtrain[:,log10λ.n]', 10^(log10λ.ftrain[log10λ.n]), ".r", markersize=10)
ax[1].set_title("λ")

ax[2].plot(xall', mns.fstar)
ax[2].plot(xall', ftest)
ax[2].plot(mns.xtrain[:,1:mns.n]', mns.ftrain[1:mns.n], "xr")
ax[2].plot(mns.xtrain[:,mns.n]', mns.ftrain[mns.n], ".m", markersize=10)
ax[2].set_title("function")
## update mns.fstar through death in mns
TransD_GP.death!(mns, opt)
lsc = TransD_GP.testupdate(optlog10λ, log10λ)
ftest = TransD_GP.testupdate(opt, log10λ, mns)

f, ax = plt.subplots(2, 1, sharex=true)
ax[1].plot(xall', sqrt.(log10λ.fstar)')
ax[1].plot(xall', 10 .^lsc, "--k")
ax[1].plot(log10λ.xtrain[:,1:log10λ.n]', 10 .^(log10λ.ftrain[1:log10λ.n]), "+m")
ax[1].plot(log10λ.xtrain[:,log10λ.n]', 10^(log10λ.ftrain[log10λ.n]), ".r", markersize=10)
ax[1].set_title("λ")

ax[2].plot(xall', mns.fstar)
ax[2].plot(xall', ftest)
ax[2].plot(mns.xtrain[:,1:mns.n]', mns.ftrain[1:mns.n], "xr")
ax[2].plot(mns.xtrain[:,mns.n]', mns.ftrain[mns.n], ".m", markersize=10)
ax[2].set_title("function")
## update λ and mns.fstar through death in λ
doall = false
lold = copy(log10λ.fstar)
TransD_GP.death!(log10λ, optlog10λ, mns, opt, doall=doall)
lsc = TransD_GP.testupdate(optlog10λ, log10λ)
ftest = TransD_GP.testupdate(opt, log10λ, mns)

f, ax = plt.subplots(2, 1, sharex=true)
ax[1].plot(xall', sqrt.(log10λ.fstar)')
ax[1].plot(xall', sqrt.(lold)')
ax[1].plot(xall', 10 .^lsc, "--k")
ax[1].plot(log10λ.xtrain[:,1:log10λ.n]', 10 .^(log10λ.ftrain[1:log10λ.n]), "+m")
ax[1].plot(log10λ.xtrain[:,log10λ.n]', 10^(log10λ.ftrain[log10λ.n]), ".r", markersize=10)
ax[1].set_title("λ")

ax[2].plot(xall', mns.fstar)
ax[2].plot(xall', ftest)
ax[2].plot(mns.xtrain[:,1:mns.n]', mns.ftrain[1:mns.n], "xr")
ax[2].set_title("function")

ax2 = ax[1].twinx()
ax2.plot(xall', log10.(abs.(lold' -10 .^2lsc)))
ax[1].grid()
ax[2].grid()
## update λ and mns.fstar through property change in λ
doall = false
lold = copy(log10λ.fstar)
TransD_GP.property_change!(log10λ, optlog10λ, mns, opt, doall=doall)
lsc = TransD_GP.testupdate(optlog10λ, log10λ)
ftest = TransD_GP.testupdate(opt, log10λ, mns)

f, ax = plt.subplots(2, 1, sharex=true)
ax[1].plot(xall', sqrt.(log10λ.fstar)')
ax[1].plot(xall', sqrt.(lold)')
ax[1].plot(xall', 10 .^lsc, "--k")
ax[1].plot(log10λ.xtrain[:,1:log10λ.n]', 10 .^(log10λ.ftrain[1:log10λ.n]), "+m")
ax[1].plot(log10λ.xtrain[:,log10λ.n]', 10^(log10λ.ftrain[log10λ.n]), ".r", markersize=10)
ax[1].set_title("λ")

ax[2].plot(xall', mns.fstar)
ax[2].plot(xall', ftest)
ax[2].plot(mns.xtrain[:,1:mns.n]', mns.ftrain[1:mns.n], "xr")
ax[2].set_title("function")

ax2 = ax[1].twinx()
ax2.plot(xall', log10.(abs.(lold' -10 .^2lsc)))
ax[1].grid()
ax[2].grid()
## update λ and mns.fstar through position change in λ
doall = false
lold = copy(log10λ.fstar)
TransD_GP.position_change!(log10λ, optlog10λ, mns, opt, doall=doall)
lsc = TransD_GP.testupdate(optlog10λ, log10λ)
ftest = TransD_GP.testupdate(opt, log10λ, mns)

f, ax = plt.subplots(2, 1, sharex=true)
ax[1].plot(xall', sqrt.(log10λ.fstar)')
ax[1].plot(xall', sqrt.(lold)')
ax[1].plot(xall', 10 .^lsc, "--k")
ax[1].plot(log10λ.xtrain[:,1:log10λ.n]', 10 .^(log10λ.ftrain[1:log10λ.n]), "+m")
ax[1].plot(log10λ.xtrain[:,log10λ.n]', 10^(log10λ.ftrain[log10λ.n]), ".r", markersize=10)
ax[1].set_title("λ")

ax[2].plot(xall', mns.fstar)
ax[2].plot(xall', ftest)
ax[2].plot(mns.xtrain[:,1:mns.n]', mns.ftrain[1:mns.n], "xr")
ax[2].set_title("function")

ax2 = ax[1].twinx()
ax2.plot(xall', log10.(abs.(lold' -10 .^2lsc)))
ax[1].grid()
ax[2].grid()


text:
# This file was generated by the Julia Swagger Code Generator
# Do not modify this file directly. Modify the swagger specification instead.

struct AutoscalingV2beta2Api <: SwaggerApi
    client::Swagger.Client
end

function _swaggerinternal_createAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "POST", IoK8sApiAutoscalingV2beta2HorizontalPodAutoscaler, "/apis/autoscaling/v2beta2/namespaces/{namespace}/horizontalpodautoscalers", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldManager", fieldManager)  # type String
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

create a HorizontalPodAutoscaler
Param: namespace::String (required)
Param: body::IoK8sApiAutoscalingV2beta2HorizontalPodAutoscaler (required)
Param: pretty::String
Param: dryRun::String
Param: fieldManager::String
Return: IoK8sApiAutoscalingV2beta2HorizontalPodAutoscaler
"""
function createAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_createAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function createAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, response_stream::Channel, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_createAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_deleteAutoscalingV2beta2CollectionNamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, namespace::String; pretty=nothing, allowWatchBookmarks=nothing, body=nothing, __continue__=nothing, dryRun=nothing, fieldSelector=nothing, gracePeriodSeconds=nothing, labelSelector=nothing, limit=nothing, orphanDependents=nothing, propagationPolicy=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "DELETE", IoK8sApimachineryPkgApisMetaV1Status, "/apis/autoscaling/v2beta2/namespaces/{namespace}/horizontalpodautoscalers", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "gracePeriodSeconds", gracePeriodSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "orphanDependents", orphanDependents)  # type Bool
    Swagger.set_param(_ctx.query, "propagationPolicy", propagationPolicy)  # type String
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

delete collection of HorizontalPodAutoscaler
Param: namespace::String (required)
Param: pretty::String
Param: allowWatchBookmarks::Bool
Param: body::IoK8sApimachineryPkgApisMetaV1DeleteOptions
Param: __continue__::String
Param: dryRun::String
Param: fieldSelector::String
Param: gracePeriodSeconds::Int32
Param: labelSelector::String
Param: limit::Int32
Param: orphanDependents::Bool
Param: propagationPolicy::String
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApimachineryPkgApisMetaV1Status
"""
function deleteAutoscalingV2beta2CollectionNamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, namespace::String; pretty=nothing, allowWatchBookmarks=nothing, body=nothing, __continue__=nothing, dryRun=nothing, fieldSelector=nothing, gracePeriodSeconds=nothing, labelSelector=nothing, limit=nothing, orphanDependents=nothing, propagationPolicy=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_deleteAutoscalingV2beta2CollectionNamespacedHorizontalPodAutoscaler(_api, namespace; pretty=pretty, allowWatchBookmarks=allowWatchBookmarks, body=body, __continue__=__continue__, dryRun=dryRun, fieldSelector=fieldSelector, gracePeriodSeconds=gracePeriodSeconds, labelSelector=labelSelector, limit=limit, orphanDependents=orphanDependents, propagationPolicy=propagationPolicy, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function deleteAutoscalingV2beta2CollectionNamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, response_stream::Channel, namespace::String; pretty=nothing, allowWatchBookmarks=nothing, body=nothing, __continue__=nothing, dryRun=nothing, fieldSelector=nothing, gracePeriodSeconds=nothing, labelSelector=nothing, limit=nothing, orphanDependents=nothing, propagationPolicy=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_deleteAutoscalingV2beta2CollectionNamespacedHorizontalPodAutoscaler(_api, namespace; pretty=pretty, allowWatchBookmarks=allowWatchBookmarks, body=body, __continue__=__continue__, dryRun=dryRun, fieldSelector=fieldSelector, gracePeriodSeconds=gracePeriodSeconds, labelSelector=labelSelector, limit=limit, orphanDependents=orphanDependents, propagationPolicy=propagationPolicy, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_deleteAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, name::String, namespace::String; pretty=nothing, body=nothing, dryRun=nothing, gracePeriodSeconds=nothing, orphanDependents=nothing, propagationPolicy=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "DELETE", IoK8sApimachineryPkgApisMetaV1Status, "/apis/autoscaling/v2beta2/namespaces/{namespace}/horizontalpodautoscalers/{name}", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "gracePeriodSeconds", gracePeriodSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "orphanDependents", orphanDependents)  # type Bool
    Swagger.set_param(_ctx.query, "propagationPolicy", propagationPolicy)  # type String
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

delete a HorizontalPodAutoscaler
Param: name::String (required)
Param: namespace::String (required)
Param: pretty::String
Param: body::IoK8sApimachineryPkgApisMetaV1DeleteOptions
Param: dryRun::String
Param: gracePeriodSeconds::Int32
Param: orphanDependents::Bool
Param: propagationPolicy::String
Return: IoK8sApimachineryPkgApisMetaV1Status
"""
function deleteAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, name::String, namespace::String; pretty=nothing, body=nothing, dryRun=nothing, gracePeriodSeconds=nothing, orphanDependents=nothing, propagationPolicy=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_deleteAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api, name, namespace; pretty=pretty, body=body, dryRun=dryRun, gracePeriodSeconds=gracePeriodSeconds, orphanDependents=orphanDependents, propagationPolicy=propagationPolicy, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function deleteAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, response_stream::Channel, name::String, namespace::String; pretty=nothing, body=nothing, dryRun=nothing, gracePeriodSeconds=nothing, orphanDependents=nothing, propagationPolicy=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_deleteAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api, name, namespace; pretty=pretty, body=body, dryRun=dryRun, gracePeriodSeconds=gracePeriodSeconds, orphanDependents=orphanDependents, propagationPolicy=propagationPolicy, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_getAutoscalingV2beta2APIResources(_api::AutoscalingV2beta2Api; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApimachineryPkgApisMetaV1APIResourceList, "/apis/autoscaling/v2beta2/", ["BearerToken"])
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"] : [_mediaType])
    return _ctx
end

"""

get available resources
Return: IoK8sApimachineryPkgApisMetaV1APIResourceList
"""
function getAutoscalingV2beta2APIResources(_api::AutoscalingV2beta2Api; _mediaType=nothing)
    _ctx = _swaggerinternal_getAutoscalingV2beta2APIResources(_api; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function getAutoscalingV2beta2APIResources(_api::AutoscalingV2beta2Api, response_stream::Channel; _mediaType=nothing)
    _ctx = _swaggerinternal_getAutoscalingV2beta2APIResources(_api; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_listAutoscalingV2beta2HorizontalPodAutoscalerForAllNamespaces(_api::AutoscalingV2beta2Api; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApiAutoscalingV2beta2HorizontalPodAutoscalerList, "/apis/autoscaling/v2beta2/horizontalpodautoscalers", ["BearerToken"])
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf", "application/json;stream=watch", "application/vnd.kubernetes.protobuf;stream=watch"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

list or watch objects of kind HorizontalPodAutoscaler
Param: allowWatchBookmarks::Bool
Param: __continue__::String
Param: fieldSelector::String
Param: labelSelector::String
Param: limit::Int32
Param: pretty::String
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApiAutoscalingV2beta2HorizontalPodAutoscalerList
"""
function listAutoscalingV2beta2HorizontalPodAutoscalerForAllNamespaces(_api::AutoscalingV2beta2Api; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_listAutoscalingV2beta2HorizontalPodAutoscalerForAllNamespaces(_api; allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, pretty=pretty, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function listAutoscalingV2beta2HorizontalPodAutoscalerForAllNamespaces(_api::AutoscalingV2beta2Api, response_stream::Channel; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_listAutoscalingV2beta2HorizontalPodAutoscalerForAllNamespaces(_api; allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, pretty=pretty, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_listAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, namespace::String; pretty=nothing, allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApiAutoscalingV2beta2HorizontalPodAutoscalerList, "/apis/autoscaling/v2beta2/namespaces/{namespace}/horizontalpodautoscalers", ["BearerToken"])
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf", "application/json;stream=watch", "application/vnd.kubernetes.protobuf;stream=watch"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

list or watch objects of kind HorizontalPodAutoscaler
Param: namespace::String (required)
Param: pretty::String
Param: allowWatchBookmarks::Bool
Param: __continue__::String
Param: fieldSelector::String
Param: labelSelector::String
Param: limit::Int32
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApiAutoscalingV2beta2HorizontalPodAutoscalerList
"""
function listAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, namespace::String; pretty=nothing, allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_listAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api, namespace; pretty=pretty, allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function listAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, response_stream::Channel, namespace::String; pretty=nothing, allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_listAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api, namespace; pretty=pretty, allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_patchAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, force=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PATCH", IoK8sApiAutoscalingV2beta2HorizontalPodAutoscaler, "/apis/autoscaling/v2beta2/namespaces/{namespace}/horizontalpodautoscalers/{name}", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldManager", fieldManager)  # type String
    Swagger.set_param(_ctx.query, "force", force)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json-patch+json", "application/merge-patch+json", "application/strategic-merge-patch+json", "application/apply-patch+yaml"] : [_mediaType])
    return _ctx
end

"""

partially update the specified HorizontalPodAutoscaler
Param: name::String (required)
Param: namespace::String (required)
Param: body::IoK8sApimachineryPkgApisMetaV1Patch (required)
Param: pretty::String
Param: dryRun::String
Param: fieldManager::String
Param: force::Bool
Return: IoK8sApiAutoscalingV2beta2HorizontalPodAutoscaler
"""
function patchAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, force=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_patchAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api, name, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, force=force, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function patchAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, response_stream::Channel, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, force=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_patchAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api, name, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, force=force, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_patchAutoscalingV2beta2NamespacedHorizontalPodAutoscalerStatus(_api::AutoscalingV2beta2Api, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, force=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PATCH", IoK8sApiAutoscalingV2beta2HorizontalPodAutoscaler, "/apis/autoscaling/v2beta2/namespaces/{namespace}/horizontalpodautoscalers/{name}/status", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldManager", fieldManager)  # type String
    Swagger.set_param(_ctx.query, "force", force)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json-patch+json", "application/merge-patch+json", "application/strategic-merge-patch+json", "application/apply-patch+yaml"] : [_mediaType])
    return _ctx
end

"""

partially update status of the specified HorizontalPodAutoscaler
Param: name::String (required)
Param: namespace::String (required)
Param: body::IoK8sApimachineryPkgApisMetaV1Patch (required)
Param: pretty::String
Param: dryRun::String
Param: fieldManager::String
Param: force::Bool
Return: IoK8sApiAutoscalingV2beta2HorizontalPodAutoscaler
"""
function patchAutoscalingV2beta2NamespacedHorizontalPodAutoscalerStatus(_api::AutoscalingV2beta2Api, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, force=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_patchAutoscalingV2beta2NamespacedHorizontalPodAutoscalerStatus(_api, name, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, force=force, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function patchAutoscalingV2beta2NamespacedHorizontalPodAutoscalerStatus(_api::AutoscalingV2beta2Api, response_stream::Channel, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, force=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_patchAutoscalingV2beta2NamespacedHorizontalPodAutoscalerStatus(_api, name, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, force=force, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_readAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, name::String, namespace::String; pretty=nothing, exact=nothing, __export__=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApiAutoscalingV2beta2HorizontalPodAutoscaler, "/apis/autoscaling/v2beta2/namespaces/{namespace}/horizontalpodautoscalers/{name}", ["BearerToken"])
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "exact", exact)  # type Bool
    Swagger.set_param(_ctx.query, "export", __export__)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

read the specified HorizontalPodAutoscaler
Param: name::String (required)
Param: namespace::String (required)
Param: pretty::String
Param: exact::Bool
Param: __export__::Bool
Return: IoK8sApiAutoscalingV2beta2HorizontalPodAutoscaler
"""
function readAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, name::String, namespace::String; pretty=nothing, exact=nothing, __export__=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_readAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api, name, namespace; pretty=pretty, exact=exact, __export__=__export__, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function readAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, response_stream::Channel, name::String, namespace::String; pretty=nothing, exact=nothing, __export__=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_readAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api, name, namespace; pretty=pretty, exact=exact, __export__=__export__, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_readAutoscalingV2beta2NamespacedHorizontalPodAutoscalerStatus(_api::AutoscalingV2beta2Api, name::String, namespace::String; pretty=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApiAutoscalingV2beta2HorizontalPodAutoscaler, "/apis/autoscaling/v2beta2/namespaces/{namespace}/horizontalpodautoscalers/{name}/status", ["BearerToken"])
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

read status of the specified HorizontalPodAutoscaler
Param: name::String (required)
Param: namespace::String (required)
Param: pretty::String
Return: IoK8sApiAutoscalingV2beta2HorizontalPodAutoscaler
"""
function readAutoscalingV2beta2NamespacedHorizontalPodAutoscalerStatus(_api::AutoscalingV2beta2Api, name::String, namespace::String; pretty=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_readAutoscalingV2beta2NamespacedHorizontalPodAutoscalerStatus(_api, name, namespace; pretty=pretty, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function readAutoscalingV2beta2NamespacedHorizontalPodAutoscalerStatus(_api::AutoscalingV2beta2Api, response_stream::Channel, name::String, namespace::String; pretty=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_readAutoscalingV2beta2NamespacedHorizontalPodAutoscalerStatus(_api, name, namespace; pretty=pretty, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_replaceAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PUT", IoK8sApiAutoscalingV2beta2HorizontalPodAutoscaler, "/apis/autoscaling/v2beta2/namespaces/{namespace}/horizontalpodautoscalers/{name}", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldManager", fieldManager)  # type String
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

replace the specified HorizontalPodAutoscaler
Param: name::String (required)
Param: namespace::String (required)
Param: body::IoK8sApiAutoscalingV2beta2HorizontalPodAutoscaler (required)
Param: pretty::String
Param: dryRun::String
Param: fieldManager::String
Return: IoK8sApiAutoscalingV2beta2HorizontalPodAutoscaler
"""
function replaceAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_replaceAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api, name, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function replaceAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, response_stream::Channel, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_replaceAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api, name, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_replaceAutoscalingV2beta2NamespacedHorizontalPodAutoscalerStatus(_api::AutoscalingV2beta2Api, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PUT", IoK8sApiAutoscalingV2beta2HorizontalPodAutoscaler, "/apis/autoscaling/v2beta2/namespaces/{namespace}/horizontalpodautoscalers/{name}/status", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldManager", fieldManager)  # type String
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

replace status of the specified HorizontalPodAutoscaler
Param: name::String (required)
Param: namespace::String (required)
Param: body::IoK8sApiAutoscalingV2beta2HorizontalPodAutoscaler (required)
Param: pretty::String
Param: dryRun::String
Param: fieldManager::String
Return: IoK8sApiAutoscalingV2beta2HorizontalPodAutoscaler
"""
function replaceAutoscalingV2beta2NamespacedHorizontalPodAutoscalerStatus(_api::AutoscalingV2beta2Api, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_replaceAutoscalingV2beta2NamespacedHorizontalPodAutoscalerStatus(_api, name, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function replaceAutoscalingV2beta2NamespacedHorizontalPodAutoscalerStatus(_api::AutoscalingV2beta2Api, response_stream::Channel, name::String, namespace::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_replaceAutoscalingV2beta2NamespacedHorizontalPodAutoscalerStatus(_api, name, namespace, body; pretty=pretty, dryRun=dryRun, fieldManager=fieldManager, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_watchAutoscalingV2beta2HorizontalPodAutoscalerListForAllNamespaces(_api::AutoscalingV2beta2Api; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApimachineryPkgApisMetaV1WatchEvent, "/apis/autoscaling/v2beta2/watch/horizontalpodautoscalers", ["BearerToken"])
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf", "application/json;stream=watch", "application/vnd.kubernetes.protobuf;stream=watch"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

watch individual changes to a list of HorizontalPodAutoscaler. deprecated: use the 'watch' parameter with a list operation instead.
Param: allowWatchBookmarks::Bool
Param: __continue__::String
Param: fieldSelector::String
Param: labelSelector::String
Param: limit::Int32
Param: pretty::String
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApimachineryPkgApisMetaV1WatchEvent
"""
function watchAutoscalingV2beta2HorizontalPodAutoscalerListForAllNamespaces(_api::AutoscalingV2beta2Api; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_watchAutoscalingV2beta2HorizontalPodAutoscalerListForAllNamespaces(_api; allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, pretty=pretty, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function watchAutoscalingV2beta2HorizontalPodAutoscalerListForAllNamespaces(_api::AutoscalingV2beta2Api, response_stream::Channel; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_watchAutoscalingV2beta2HorizontalPodAutoscalerListForAllNamespaces(_api; allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, pretty=pretty, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_watchAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, name::String, namespace::String; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApimachineryPkgApisMetaV1WatchEvent, "/apis/autoscaling/v2beta2/watch/namespaces/{namespace}/horizontalpodautoscalers/{name}", ["BearerToken"])
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf", "application/json;stream=watch", "application/vnd.kubernetes.protobuf;stream=watch"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

watch changes to an object of kind HorizontalPodAutoscaler. deprecated: use the 'watch' parameter with a list operation instead, filtered to a single item with the 'fieldSelector' parameter.
Param: name::String (required)
Param: namespace::String (required)
Param: allowWatchBookmarks::Bool
Param: __continue__::String
Param: fieldSelector::String
Param: labelSelector::String
Param: limit::Int32
Param: pretty::String
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApimachineryPkgApisMetaV1WatchEvent
"""
function watchAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, name::String, namespace::String; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_watchAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api, name, namespace; allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, pretty=pretty, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function watchAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api::AutoscalingV2beta2Api, response_stream::Channel, name::String, namespace::String; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_watchAutoscalingV2beta2NamespacedHorizontalPodAutoscaler(_api, name, namespace; allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, pretty=pretty, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

function _swaggerinternal_watchAutoscalingV2beta2NamespacedHorizontalPodAutoscalerList(_api::AutoscalingV2beta2Api, namespace::String; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApimachineryPkgApisMetaV1WatchEvent, "/apis/autoscaling/v2beta2/watch/namespaces/{namespace}/horizontalpodautoscalers", ["BearerToken"])
    Swagger.set_param(_ctx.path, "namespace", namespace)  # type String
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf", "application/json;stream=watch", "application/vnd.kubernetes.protobuf;stream=watch"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    return _ctx
end

"""

watch individual changes to a list of HorizontalPodAutoscaler. deprecated: use the 'watch' parameter with a list operation instead.
Param: namespace::String (required)
Param: allowWatchBookmarks::Bool
Param: __continue__::String
Param: fieldSelector::String
Param: labelSelector::String
Param: limit::Int32
Param: pretty::String
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApimachineryPkgApisMetaV1WatchEvent
"""
function watchAutoscalingV2beta2NamespacedHorizontalPodAutoscalerList(_api::AutoscalingV2beta2Api, namespace::String; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_watchAutoscalingV2beta2NamespacedHorizontalPodAutoscalerList(_api, namespace; allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, pretty=pretty, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function watchAutoscalingV2beta2NamespacedHorizontalPodAutoscalerList(_api::AutoscalingV2beta2Api, response_stream::Channel, namespace::String; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_watchAutoscalingV2beta2NamespacedHorizontalPodAutoscalerList(_api, namespace; allowWatchBookmarks=allowWatchBookmarks, __continue__=__continue__, fieldSelector=fieldSelector, labelSelector=labelSelector, limit=limit, pretty=pretty, resourceVersion=resourceVersion, timeoutSeconds=timeoutSeconds, watch=watch, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

export createAutoscalingV2beta2NamespacedHorizontalPodAutoscaler, deleteAutoscalingV2beta2CollectionNamespacedHorizontalPodAutoscaler, deleteAutoscalingV2beta2NamespacedHorizontalPodAutoscaler, getAutoscalingV2beta2APIResources, listAutoscalingV2beta2HorizontalPodAutoscalerForAllNamespaces, listAutoscalingV2beta2NamespacedHorizontalPodAutoscaler, patchAutoscalingV2beta2NamespacedHorizontalPodAutoscaler, patchAutoscalingV2beta2NamespacedHorizontalPodAutoscalerStatus, readAutoscalingV2beta2NamespacedHorizontalPodAutoscaler, readAutoscalingV2beta2NamespacedHorizontalPodAutoscalerStatus, replaceAutoscalingV2beta2NamespacedHorizontalPodAutoscaler, replaceAutoscalingV2beta2NamespacedHorizontalPodAutoscalerStatus, watchAutoscalingV2beta2HorizontalPodAutoscalerListForAllNamespaces, watchAutoscalingV2beta2NamespacedHorizontalPodAutoscaler, watchAutoscalingV2beta2NamespacedHorizontalPodAutoscalerList


text:
struct DBSpectrum
    database::SQLite.DB
    pkey::Int
    detector::DBDetector
    beamenergy::Float64
    composition::Union{Material,Missing}
    collectedby::DBPerson
    sample::DBSample
    collected::DateTime
    name::String
    artifact::DBArtifact
end

function sniffFormat(fn)
    if NeXLSpectrum.isemsa(fn)
        return "EMSA"
    elseif NeXLSpectrum.isAspexTIFF(fn)
        return "ASPEX"
    else
        error("Unknown file type in $fn.")
    end
end

function Base.write(#
        db::SQLite.DB, #
        ::Type{DBSpectrum}, #
        det::Int, #
        e0::Float64, #
        comp::Int, #
        collectedBy::Int, #
        sample::Int, #
        collected::DateTime, #
        name::String, #
        filename::String,
        format::String)::Int
    if !((format=="EMSA") || (format=="ASPEX"))
        error("Unknown format $(format) in write(db, DBSpectrum,...).")
    end
    artifact = write(db, DBArtifact, filename, format)
    stmt1 = SQLite.Stmt(db, "INSERT INTO SPECTRUM ( DETECTOR, BEAMENERGY, COMPOSITION, COLLECTEDBY, SAMPLE, COLLECTED, NAME, ARTIFACT ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ? );")
    results = DBInterface.execute(stmt1, (det, e0, comp, collectedBy, sample, Dates.datetime2julian(collected), name, artifact ))
    return  DBInterface.lastrowid(results)
end

function Base.write(#
        db::SQLite.DB, #
        ::Type{DBSpectrum}, #
        det::DBDetector, #
        e0::Float64, #
        comp::Union{Material, Missing}, #
        collectedBy::DBPerson, #
        sample::DBSample, #
        collected::DateTime, #
        name::String, #
        filename::String,
        format::String)::Int
    compidx = ismissing(comp) ? -1 : write(db, comp)
    return write(db, DBSpectrum, det.pkey, e0, compidx, collectedBy.pkey, sample.pkey, collected, name, filename, format)
end

function Base.read(db::SQLite.DB, ::Type{DBSpectrum}, pkey::Int)::DBSpectrum
    stmt1 = SQLite.Stmt(db, "SELECT * FROM SPECTRUM WHERE PKEY=?;")
    q = DBInterface.execute(stmt1, (pkey, ))
    if SQLite.done(q)
        error("No spectrum found with pkey=$(pkey)")
    end
    r=SQLite.Row(q)
    mat = r[:COMPOSITION] >= 0 ? read(db,Material,r[:COMPOSITION]) : missing
    det = read(db, DBDetector, r[:DETECTOR])
    colby = read(db, DBPerson, r[:COLLECTEDBY])
    samp = read(db, DBSample, r[:SAMPLE])
    art = read(db, DBArtifact, r[:ARTIFACT])
    acq = Dates.julian2datetime(r[:COLLECTED])
    return DBSpectrum(db, r[:PKEY], det, r[:BEAMENERGY], mat, colby, samp, acq, r[:NAME], art)
end

function NeXLUncertainties.asa(::Type{Spectrum}, dbspec::DBSpectrum)::Spectrum
    res = asa(Spectrum, dbspec.artifact)
    res[:Name] = dbspec.name
    res[:Sample] = repr(dbspec.sample)
    res[:Owner] = dbspec.collectedby.name
    res[:Detector] = convert(BasicEDS, dbspec.detector, length(res))
    res[:PKEY] = dbspec.pkey
    if !ismissing(dbspec.composition)
        res[:Composition] = dbspec.composition
    end
    return res
end


text:
using DelaySSAToolkit, Catalyst

rn = @reaction_network begin
    ρ, S+I --> E+I
    r, I --> R
end ρ r

jumpsys = convert(JumpSystem, rn, combinatoric_ratelaws=false)
states(jumpsys)

u0 = [999,1,0,0]
de_chan0 = [[]]
tf = 400.
tspan = (0,tf)

ps = [1e-4, 1e-2]
τ = 20.
dprob = DiscreteProblem(jumpsys,u0,tspan, ps)
delay_trigger_affect! = function (integrator, rng)
    append!(integrator.de_chan[1], τ)
end
delay_trigger = Dict(1=>delay_trigger_affect!)
# delay_trigger = Dict(1=>[1=>τ])
delay_complete = Dict(1=>[2=>1, 3=>-1])
delay_interrupt = Dict()
# algo = DelayDirect()
# algo = DelayDirectCR()
algo = DelayRejection()
delayjumpset = DelayJumpSet(delay_trigger, delay_complete, delay_interrupt)
jprob = DelayJumpProblem(jumpsys, dprob, algo, delayjumpset, de_chan0, save_positions=(true,true))
@time sol = solve(jprob, SSAStepper(), seed = 1234)
using Plots; theme(:vibrant)
fig = plot(sol, label = ["S" "I" "E" "R"], linewidth = 3, legend = :top, ylabel = "# of individuals", xlabel = "Time", fmt=:png)
savefig(fig,"docs/src/assets/seir.png")