text:
@testset "Testing lss.jl" begin

    rough_kwargs = Dict(:atol => 1e-7, :rtol => 1e-7)

    # set up
    A = .95
    C = .05
    G = 1.
    H = 0
    mu_0 = [.75;]
    Sigma_0 = fill(0.000001, 1, 1)

    ss = LSS(A, C, G, H, mu_0)
    ss1 = LSS(A, C, G, H, mu_0, Sigma_0)

    vals = stationary_distributions(ss, max_iter=1000, tol=1e-9)

    @testset "test stationarity" begin
        vals = stationary_distributions(ss, max_iter=1000, tol=1e-9)
        ssmux, ssmuy, sssigx, sssigy = vals

        @test isapprox(ssmux, ssmuy; rough_kwargs...)
        @test isapprox(sssigx, sssigy; rough_kwargs...)
        @test isapprox(ssmux, [0.0]; rough_kwargs...)
        @test isapprox(sssigx, ss.C.^2 ./ (1 - ss.A .^2); rough_kwargs...)
    end

    @testset "test replicate" begin
        xval1, yval1 = replicate(ss, 100, 5000)
        xval2, yval2 = replicate(ss; t=100, num_reps=5000)
        xval3, yval3 = replicate(ss1; t=100, num_reps=5000)

        for (x, y)  in [(xval1, yval1), (xval2, yval2), (xval3, yval3)]
            @test isapprox(x , y; rough_kwargs...)
            @test abs(mean(x)) <= 0.05
        end

    end

    @testset "test convergence error" begin
        @test_throws ErrorException stationary_distributions(ss; max_iter=1, tol=eps())
    end

    @testset "test geometric_sums" begin
        β = 0.98
        xs = rand(10)
        for x in xs
            gsum_x, gsum_y = QuantEcon.geometric_sums(ss, β, [x])
            @test isapprox(gsum_x, ([x/(1-β *ss.A[1])]))
            @test isapprox(gsum_y, ([ss.G[1]*x/(1-β *ss.A[1])]))
        end
    end

    @testset "test constructors" begin
        # kwarg version
        other_ss = LSS(A, C, G; H=H, mu_0=[mu_0;])
        for nm in fieldnames(ss)
            @test getfield(ss, nm) == getfield(other_ss, nm)
        end
    end

    @testset "test moment iterator" begin
        m = QuantEcon.LSSMoments(ss)

        # never done
        @test !done(m, 1)

        # start should give us mu_0, Sigma_0
        @test start(m) == (ss.mu_0, ss.Sigma_0)
    end

    @testset "test positive semi-dfinite covariance" begin

        # set up
        A = [1.0      0.0       0.0 0.0;
             10.0     0.9       0.0 0.0;
             0.0      1.0       0.0 0.0;
             68.9655  -0.689655 0.0 1.0]
        C = [0.0;
             1.0;
             0.0;
             0.0]
        G = [0.0     1.0       0.0  0.0;
             65.5172 0.344828  0.0  -0.05]
        H = [0.6     1.3;
             -5.8    0.1]
        mu_0 = [1.0;
                99.9999;
                99.9999;
                0.0]
        Sigma_0 = [0.0  0.0      0.0      0.0;
                   0.0  5.26316  4.73684  0.0;
                   0.0  4.73684  5.26316  0.0;
                   0.0  0.0      0.0      0.0]

        lss_psd = LSS(A, C, G, H, mu_0, Sigma_0)

        @test isapprox(lss_psd.dist.Sigma,
                    lss_psd.dist.Q*lss_psd.dist.Q')

        @test size(rand(lss_psd.dist,10)) == (4,10)
    end

    @testset "test stability checks: unstable systems" begin

        phi_0, phi_1, phi_2 = 1.1, 1.8, -1.8

        A = [1.0   0.0   0
            phi_0 phi_1 phi_2
            0.0   1.0   0.0]
        C = zeros(3, 1)
        G = [0.0 1.0 0.0]

        lss = LSS(A, C, G)
        lss2 = LSS(A[2:end, 2:end], C[2:end, :], G[:, 2:end])   # system without constant
        lss_vec = [lss, lss2]

        for sys in lss_vec
            @test is_stable(sys) == false
            @test_throws ErrorException stationary_distributions(sys)
            @test_throws ErrorException geometric_sums(sys, 0.97, rand(3))
        end

    end

    @testset "test stability checks: stable systems" begin

        phi_0, phi_1, phi_2 = 1.1, 0.8, -0.8

        A = [1.0   0.0   0
            phi_0 phi_1 phi_2
            0.0   1.0   0.0]
        C = zeros(3, 1)
        G = [0.0 1.0 0.0]

        lss = LSS(A, C, G)
        lss2 = LSS(A[2:end, 2:end], C[2:end, :], G[:, 2:end])   # system without constant
        lss_vec = [lss, lss2]

        for sys in lss_vec
            @test is_stable(sys) == true
        end

    end

end  # @testset


text:
module TestArrows

using MLJBase
using ..Models
using Test
using Random

@testset "|> syntax for pipelines" begin
    Random.seed!(142)
    @load RidgeRegressor pkg="MultivariateStats"
    @load KNNRegressor pkg="NearestNeighbors"
    X = MLJBase.table(randn(500, 5))
    y = abs.(randn(500))
    train, test = partition(eachindex(y), 0.7)

    # Feeding data directly to a supervised model
    knn = KNNRegressor(K=10)
    ŷ   = (X, y) |> knn
    fit!(ŷ, rows=train)

    # Describing a full pipeline using |> syntax.
    Xs, ys = source.((X, y))

    # "first layer"
    W = Xs |> Standardizer()
    z = ys |> UnivariateBoxCoxTransformer()
    # "second layer"
    ẑ = (W, z) |> RidgeRegressor(lambda=0.1)
    # "output layer"
    ŷ = ẑ |> inverse_transform(z)

    fit!(ŷ, rows=train)

    @test isapprox(rms(ŷ(rows=test), ys(rows=test)), 0.627123, rtol=1e-4)

    # shortcut to get and set hyperparameters of a node
    ẑ[:lambda] = 5.0
    fit!(ŷ, rows=train)
    @test isapprox(rms(ŷ(rows=test), ys(rows=test)), 0.62699, rtol=1e-4)
end

@testset "Auto-source" begin
    @load PCA
    @load RidgeRegressor pkg="MultivariateStats"
    Random.seed!(5615151)

    X = MLJBase.table(randn(500, 5))
    y = abs.(randn(500))

    pca = X |> Standardizer() |> PCA(maxoutdim=2)
    fit!(pca)

    W = pca()
    sch = schema(W)
    @test sch.names == (:x1, :x2)
    @test sch.scitypes == (Continuous, Continuous)
    @test sch.nrows == 500

    pipe = (pca, y) |> RidgeRegressor()
    fit!(pipe)

    ŷ = pipe()
    @test ŷ isa Vector{Float64}
    @test length(ŷ) == 500
end

@testset "Auto-table" begin
    @load PCA
    @load RidgeRegressor pkg="MultivariateStats"
    Random.seed!(5615151)

    X = randn(500, 5)
    y = abs.(randn(500))

    pca = X |> Standardizer() |> PCA(maxoutdim=2)
    pipe = (pca, y) |> RidgeRegressor()
    fit!(pipe)

    ŷ = pipe()
    @test ŷ isa Vector{Float64}
    @test length(ŷ) == 500
end

@testset "Stacking" begin
    @load PCA
    @load RidgeRegressor pkg=MultivariateStats
    @load DecisionTreeRegressor pkg=DecisionTree
    Random.seed!(5615151)

    X = randn(500, 5)
    y = abs.(randn(500))

    W = X |> Standardizer() |> PCA(maxoutdim=3)
    z = y |> UnivariateBoxCoxTransformer()
    ẑ₁ = (W, z) |> RidgeRegressor()
    ẑ₂ = (W, z) |> DecisionTreeRegressor()
    R = hcat(ẑ₁, ẑ₂)
    ẑ = (R, z) |> DecisionTreeRegressor()
    ŷ = ẑ |> inverse_transform(z)

    fit!(ŷ)

    p̂ = ŷ()
    @test p̂ isa Vector{Float64}
    @test length(p̂) == 500
end

@testset "functions and static transfomers" begin
    x1 = rand(30)
    x2 = rand(30)
    x3 = rand(30)
    y = exp.(x1 - x2 -2x3 + 0.1*rand(30))
    X = (x1=x1, x2=x2, x3=x3)

    f(X) = (a=selectcols(X, :x1), b=selectcols(X, :x2))

    knn = @load KNNRegressor

    Xs = source(X)
    ys = source(y, kind=:target)

    f(X::AbstractNode) = node(f, X)
    W = Xs |> f |> Standardizer()
    z = ys |> UnivariateBoxCoxTransformer()
    zhat = (W, z) |> knn
    yhat = zhat |> inverse_transform(z)
    fit!(yhat)
    pred = yhat()

    mutable struct MyTransformer <: Static
        ftr::Symbol
    end
    MLJBase.transform(transf::MyTransformer, verbosity, X) =
        (a=selectcols(X, transf.ftr), b=selectcols(X, :x2))
    inserter = MyTransformer(:x1)
    W = Xs |> inserter |> Standardizer()
    z = ys |> UnivariateBoxCoxTransformer()
    zhat = (W, z) |> knn
    yhat = zhat |> inverse_transform(z)
    fit!(yhat)
    @test yhat() ≈ pred
end

end
true

ext: jl


text:
# Cook membrane problem, plane stress.
module cook_membrane_examples

using FinEtools
using FinEtoolsDeforLinear
using FinEtoolsFlexStructures.FESetShellT3Module: FESetShellT3
using FinEtoolsFlexStructures.FESetShellQ4Module: FESetShellQ4
using FinEtoolsFlexStructures.FEMMShellT3FFModule
using FinEtoolsFlexStructures.RotUtilModule: initial_Rfield, update_rotation_field!
using VisualStructures: plot_nodes, plot_midline, render, plot_space_box, plot_midsurface, space_aspectratio, save_to_json
using FinEtools.MeshExportModule.VTKWrite: vtkwrite

function _execute(n = 8, visualize = true)
    E = 1.0;
    nu = 1.0/3;
    width = 48.0;
    height = 44.0;
    thickness  = 1.0;
    free_height  = 16;
    mid_edge  = [48.0, 52.0];# Location of tracked  deflection
    magn=1/free_height;# Magnitude of applied load
    convutip=23.97;
    formul = FEMMShellT3FFModule

    @info "Mesh: $n elements per side"
    tolerance = thickness/n/100
    fens, fes = T3block(width,height,n,n);
    for k in 1:count(fens)
        x = fens.xyz[k,1]
        y = fens.xyz[k,2] + (x/width)*(height -fens.xyz[k,2]/height*(height-free_height));
        fens.xyz[k, :] .= (x, y)
    end
    fens.xyz = xyz3(fens)

    mater = MatDeforElastIso(DeforModelRed3D, E, nu)

    sfes = FESetShellT3()
    accepttodelegate(fes, sfes)
    femm = formul.make(IntegDomain(fes, TriRule(1), thickness), mater)
    stiffness = formul.stiffness
    associategeometry! = formul.associategeometry!

    # Construct the requisite fields, geometry and displacement
    # Initialize configuration variables
    geom0 = NodalField(fens.xyz)
    u0 = NodalField(zeros(size(fens.xyz,1), 3))
    Rfield0 = initial_Rfield(fens)
    dchi = NodalField(zeros(size(fens.xyz,1), 6))

    # Apply EBC's
    # Clamped edge
    l1 = selectnode(fens; box = Float64[0 0 -Inf Inf -Inf Inf], inflate = tolerance)
    for i in [1,2,3,4,5,6]
        setebc!(dchi, l1, true, i)
    end
    applyebc!(dchi)
    numberdofs!(dchi);

    # Assemble the system matrix
    associategeometry!(femm, geom0)
    K = stiffness(femm, geom0, u0, Rfield0, dchi);

    # Load
    bfes = meshboundary(fes)
    nl = selectelem(fens, bfes; box = Float64[width width -Inf Inf -Inf Inf], tolerance = tolerance)
    loadbdry = subset(bfes, nl)
    lfemm = FEMMBase(IntegDomain(loadbdry, GaussRule(1, 2)))
    fi = ForceIntensity(FFlt[0, magn, 0, 0, 0, 0]);
    F = distribloads(lfemm, geom0, dchi, fi, 2);

    # Solve
    U = K\F
    scattersysvec!(dchi, U[:])

    l1 = selectnode(fens; box = [mid_edge[1] mid_edge[1] mid_edge[2] mid_edge[2] -Inf Inf], inflate = tolerance)
    resultpercent = dchi.values[l1, 2][1]/convutip*100
    @info "Solution: $(round(resultpercent, digits = 4))%"

    # Generate a graphical display of resultants
    scalars = []
    for nc in 1:3
        fld = fieldfromintegpoints(femm, geom0, dchi, :membrane, nc)
            # fld = elemfieldfromintegpoints(femm, geom0, dchi, :membrane, nc)
        push!(scalars, ("n$nc", fld.values))
    end
    vtkwrite("cook_membrane-n=$n-n.vtu", fens, fes; scalars = scalars, vectors = [("u", dchi.values[:, 1:3])])

    # Visualization
    if !visualize
        return true
    end
    scattersysvec!(dchi, (height/4)/maximum(abs.(U)).*U)
    update_rotation_field!(Rfield0, dchi)
    plots = cat(plot_space_box([[0 0 0]; [width height 0]]),
        #plot_nodes(fens),
        plot_midsurface(fens, fes; x = geom0.values, u = dchi.values[:, 1:3], R = Rfield0.values);
    dims = 1)
    pl = render(plots)
    return resultpercent
end

function test_convergence()

    @info "Cook trapezoidal membrane"

    for n in [2, 4, 8, 16, 32, 64, 128]
        _execute(n, false)
    end
    return true
end

function allrun()
    println("#####################################################")
    println("# test_convergence ")
    test_convergence()
    return true
end # function allrun

@info "All examples may be executed with "
println("using .$(@__MODULE__); $(@__MODULE__).allrun()")

end # module
nothing


text:
# vector conversion operators: joReal joImag joConj joConvert

export joReal, joImag, joConj, joConvert
"""
    julia> op = joReal(m;[VDP=...,][name=...])

Takes real part of vector (experimantal).

transpose/adjont puts the real vector into real part of the complex vector with zero imag part

# Signature

    joReal(m::Integer;VDP::DataType=joFloat,name::String="joReal")

# Arguments

- `m`: vector size
- keywords
    - `VDP`: float element type of Complex number in vector
    - `name`: custom name

"""
joReal(m::Integer;VDP::DataType=joFloat,name::String="joReal") =
    joMatrix{Complex{VDP},VDP}(name,m,m,
        v1->jo_convert(VDP,real(v1),false),
        v2->jo_convert(Complex{VDP},complex.(v2),false),
        v3->jo_convert(Complex{VDP},complex.(v3),false),
        v4->jo_convert(VDP,real(v4),false),
        @joNF, @joNF, @joNF, @joNF
        )
"""
    julia> op = joImag(m;[VDP=...,][name=...])

Takes imag part of vector (experimantal).

transpose/adjont puts the real vector into imag part of the complex vector with zero real part

# Signature

    joReal(m::Integer;VDP::DataType=joFloat,name::String="joImag")

# Arguments

- `m`: vector size
- keywords
    - `VDP`: float element type of Complex number in vector
    - `name`: custom name

"""
joImag(m::Integer;VDP::DataType=joFloat,name::String="joImag") =
    joMatrix{Complex{VDP},VDP}(name,m,m,
        v1->jo_convert(VDP,imag(v1),false),
        v2->jo_convert(Complex{VDP},complex.(zero(VDP),v2),false),
        v3->jo_convert(Complex{VDP},complex.(zero(VDP),-v3),false),
        v4->jo_convert(VDP,-imag(v4),false),
        @joNF, @joNF, @joNF, @joNF
        )
"""
    julia> op = joConj(m;[VDP=...,][name=...])

Takes conjugate of vector (experimantal).

# Signature

    joConj(m::Integer;VDP::DataType=joFloat,name::String="joConj")

# Arguments

- `m`: vector size
- keywords
    - `VDP`: float element type of Complex number in vector
    - `name`: custom name

"""
joConj(m::Integer;VDP::DataType=joFloat,name::String="joConj") =
    joMatrix{Complex{VDP},Complex{VDP}}(name,m,m,
        v1->jo_convert(Complex{VDP},conj(v1),false),
        v2->jo_convert(Complex{VDP},conj(v2),false),
        v3->jo_convert(Complex{VDP},conj(v3),false),
        v4->jo_convert(Complex{VDP},conj(v4),false),
        @joNF, @joNF, @joNF, @joNF
        )
"""
    julia> op = joConvert(m,DDT,RDT;[name=...])

Converts vector between different types (experimental)

# Signature

    joConvert(m::Integer,DDT::DataType,RDT::DataType;name::String="joConvert")

# Arguments

- `m`: vector size
- `DDT`: domain data type
- `RDT`: range data type
- keywords
    - `name`: custom name

"""
joConvert(m::Integer,DDT::DataType,RDT::DataType;name::String="joConvert") =
    joMatrix{DDT,RDT}(name,m,m,
        v1->jo_convert(RDT,v1,false),
        v2->jo_convert(DDT,v2,false),
        v3->jo_convert(DDT,v3,false),
        v4->jo_convert(RDT,v4,false),
        v5->jo_convert(DDT,v5,false),
        v6->jo_convert(RDT,v6,false),
        v7->jo_convert(RDT,v7,false),
        v8->jo_convert(DDT,v8,false)
        )


text:
function _process_reaction_phrase(phrase_array::Array{String,1})

    tmp_string = ""
    for phrase in phrase_array
        tmp_string*="$(phrase) + "
    end

    # cutoff -
    tmp_string = tmp_string |> rstrip

    # cutoff the trailing +
    return (tmp_string[1:end-1] |> rstrip)
end

function build_stoichiometric_matrix(model::Dict{Symbol,Any})

    try

        # get the reaction table -
        reaction_table = model[:reactions]
        reaction_id_array = reaction_table[!, :reaction_number]
        compound_id_array = model[:compounds][!,:compound_id]

        # now - let's build the stm -
        number_of_species = length(compound_id_array)
        number_of_reactions = length(reaction_id_array)
        stoichiometric_matrix = zeros(number_of_species, number_of_reactions)

        # build the array -
        for reaction_index = 1:number_of_reactions

            # what is my reaction id?
            reaction_id = reaction_id_array[reaction_index]

            # get row from the reaction table -
            df_reaction = filter(:reaction_number => x -> (x == reaction_id), reaction_table)

            # grab the stm dictionary -
            stm_dictionary = df_reaction[1, :stoichiometric_dictionary]

            # ok, lets see if we have these species -
            for species_index = 1:number_of_species

                # species code -
                species_symbol = compound_id_array[species_index]
                if (haskey(stm_dictionary, species_symbol) == true)
                    stm_coeff_value = stm_dictionary[species_symbol]
                    stoichiometric_matrix[species_index, reaction_index] = stm_coeff_value
                end
            end
        end

        # return -
        return (compound_id_array, reaction_id_array, stoichiometric_matrix)
    catch error

        # what is our error policy? => for now, just print the message
        error_message = sprint(showerror, error, catch_backtrace())
        println(error_message)

    end
end

function find_compound_index(model::Dict{Symbol,Any},
    search::Pair{Symbol,String})

    # get the compounds table -
    compounds_table = model[:compounds]

    # get list of compound names -
    tmp_array = compounds_table[!,search.first] |> collect

    # do we have this name? (if yes, then return index)
    return findfirst(x->x==search.second,tmp_array)
end

function find_reaction_index(model::Dict{Symbol,Any},
    search::Pair{Symbol,String})

    # get the compounds table -
    reaction_table = model[:reactions]

    # get list of compound names -
    tmp_array = reaction_table[!,search.first] |> collect

    # do we have this name? (if yes, then return index)
    return findfirst(x->x==search.second,tmp_array)
end

function update_flux_bounds_directionality(MODEL,default_flux_bounds)

    # get the ΔG table -> for now, just use the mean value -
    ΔG_table = MODEL[:ΔG]

    # how many reactions do we have ΔG data for?
    (number_of_reactions,_) = size(ΔG_table)
    for reaction_index = 1:number_of_reactions

        # get ΔG value -
        μ_ΔG_value = ΔG_table[reaction_index,:μ_ΔG]

        # get the corresponding reaction number -
        reaction_id = ΔG_table[reaction_index, :reaction_number]

        # what index is this?
        index_in_bounds_array = find_reaction_index(MODEL,:reaction_number=>reaction_id)
        if (isempty(index_in_bounds_array) == false)

            # backward?
            is_reversible = -1*(sign(μ_ΔG_value)) <= 0.0 ? true : false
            if (is_reversible == false)
                default_flux_bounds[index_in_bounds_array,1] = 0.0
            end
        end
    end

    return default_flux_bounds
end

function translation_reaction_string_to_human(model::Dict{Symbol,Any})

    # get the compound table -
    compound_table = model[:compounds]
    reaction_table = model[:reactions]

    # build a translation table -
    (number_of_compounds, _) = size(compound_table)
    compound_translation_table = Dict{String,String}()
    for compound_index = 1:number_of_compounds
        kegg_name = compound_table[compound_index, :compound_id]
        human_name = compound_table[compound_index, :compound_name]
        compound_translation_table[kegg_name] = human_name
    end

    # hack: -
    compound_translation_table["C00138"] = "Reduced ferredoxin"
    compound_translation_table["C00139"] = "Oxidized ferredoxin"

    # number of _reactions -
    (number_of_reactions, _) = size(reaction_table)

    # initialze space -
    tmp_reaction_string_array = Array{String,1}(undef,number_of_reactions)

    # just so we are safe - copy the old strings into the tmp array in case something doesn't work
    for reaction_index = 1:number_of_reactions
        old_string = reaction_table[reaction_index, :reaction_markup]
        tmp_reaction_string_array[reaction_index] = old_string
    end

    # init some tmp storage -
    tmp_reactant_phrase_array = Array{String,1}()
    tmp_product_phrase_array = Array{String,1}()

    # main loop - here we go .... let's do this ...
    for reaction_index = 1:number_of_reactions

        # grab the st dictionary for this reaction -
        stoichiometric_dictionary = reaction_table[reaction_index, :stoichiometric_dictionary]
        for (key,value) in stoichiometric_dictionary

            # look up this key in the translation table -
            human_key = get(compound_translation_table, key, "?")

            if (abs(value) != 1)
                tmp_phrase = "$(abs(value)) $(human_key)"
            else
                tmp_phrase = "$(human_key)"
            end

            if (value<0)
                push!(tmp_reactant_phrase_array, tmp_phrase)
            else
                push!(tmp_product_phrase_array, tmp_phrase)
            end
        end

        # build new reaction string ...
        reactant_string = _process_reaction_phrase(tmp_reactant_phrase_array)
        product_string = _process_reaction_phrase(tmp_product_phrase_array)
        full_reaction_string = "$(reactant_string) <=> $(product_string)"
        tmp_reaction_string_array[reaction_index] = full_reaction_string

        # empty -
        empty!(tmp_reactant_phrase_array)
        empty!(tmp_product_phrase_array)
    end

    return tmp_reaction_string_array
end


text:
using Statistics
function timeto1(mv)
    x = Int[]
    while true
        push!(x, rand(1:mv))
        1 in x && return length(x)
    end
end
agg(f, mv, rep) = mean(f(mv) for i in 1:rep)

max_stars_repo_path: Chapter08/03. Profiling Julia code/profiletest.jl


text:
module item_

using IUP

export
	item

include("../src/libiup_h.jl")

#------------------------example html/examples/C/item.c ----------------------------------
function item()
	IupOpen()	#Initializes IUP

	text = IupText()

	IupSetAttribute(text, "VALUE", "This is an empty text");

	item_save = IupItem("Save\tCtrl+S")     # this is NOT related with the Ctrl+S key callback, it will just align the text at right */
	item_autosave = IupItem("&Auto Save")
	item_exit = IupItem("Exit", "item_exit_act")

	IupSetAttribute(item_exit, "KEY", "x")  # this is NOT related with the K_X key callback, it will just underline the letter */

	IupSetCallback(item_exit, "ACTION", cfunction(item_exit_cb, Int, (),))
	IupSetCallback(item_autosave, "ACTION", cfunction(item_autosave_cb, Int, (),))

	IupSetAttribute(item_autosave, "VALUE", "ON")
	IupSetHandle("item_autosave", item_autosave)        # giving a name to a iup handle

	menu_file = IupMenu(item_save, item_autosave, item_exit)

	submenu_file = IupSubmenu("File", menu_file)

	menu = IupMenu(submenu_file)

	IupSetHandle("menu", menu)

	dlg = IupDialog(IupVbox(text, IupButton("Test")))

	IupSetAttribute(dlg, "MARGIN", "10x10")
	IupSetAttribute(dlg, "GAP", "10")
	IupSetAttribute(dlg, "TITLE", "IupItem")
	IupSetAttribute(dlg, "MENU", "menu")
	IupSetCallback(dlg, "K_cX", cfunction(item_exit_cb, Int, (),))     # this will also affect the IupText if at focus, since it is used for clipboard cut */
	IupSetCallback(dlg, "K_cA", cfunction(item_autosave_cb, Int, (),)) # this will also affect the IupText if at focus, since it is used for select all */
	IupSetCallback(dlg, "K_cS", cfunction(item_save_cb, Int, (),))

	IupShowXY(dlg, IUP_CENTER, IUP_CENTER)
	IupMainLoop()                               # Initializes IUP main loop
	IupClose()                                  # And close it when ready
end

function item_save_cb()
	IupMessage("Test","Saved!")
	return IUP_DEFAULT
end

function item_autosave_cb()
	item_autosave = IupGetHandle("item_autosave")
	if (IupGetInt(item_autosave, "VALUE"))
		IupMessage("Auto Save","OFF")
		IupSetAttribute(item_autosave, "VALUE", "OFF")
	else
		IupMessage("Auto Save","ON")
		IupSetAttribute(item_autosave, "VALUE", "ON")
	end

	return IUP_DEFAULT
end

function item_exit_cb()
	return IUP_CLOSE
end

end 	# module


text:
using DrWatson
@quickactivate "StatReth"

# %%
using DataFrames
using Turing
using Plots
using StatsPlots

# %% 4M1
N = 1000
σ = rand(Exponential(1), N)
μ = rand(Normal(0, 10), N)
y = rand.(Normal.(μ, σ))

# %% 4M2
@model function M1()
    μ ~ Normal(0, 10)
    σ ~ Exponential(1)
    y ~ Normal(μ, σ)
end

y2 = sample(M1(), Prior(), N) |> DataFrame

# %%
density(y)
density!(y2.y)

# %% 4M3
"""
y ~ Normal(μ, σ)
μᵢ = a + bxᵢ
a ~ Normal(0, 10)
b ~ Uniform(0, 1)
σ ~ Exponential(1)
"""

# %% 4M4
"""
Right of the bat, I don't like this exercise, I feel like I don't get it, maybe my english
leaves me hanging?
'Student' could mean everything from elementary school students (who will probably grow a
lot each year) to college student (who probably won't grow much, if at all).
Anyway.

height ~ Normal(μ, σ)
μᵢ = a + bxᵢ
a ~ Normal(140, 30)  # depending on what student we are talking about there is a huge range
b ~ Normal(0, 10)    # eh, kids grow a few cm each year
σ ~ truncated(Normal(0, 30), 0, ∞)   # again, depending on the sample the spread can be big
"""

# %% 4M5
"""
You remind me that this was the case in the data or that this is true in general? I didn't
grow like half the years I was a student.

b ~ truncated(Normal(0, 10), 0, ∞)   # now with 100% more truncation
"""

# %% 4M6
"""
Ah, so now you have the age? Why don't we use that to predict height? That's going to be so
much more effective. Did you mean year as in school year? If so, it really isn't clear from
the wording.
Variance 64cm (not sure, shouln't that be cm²?) == StdDev 8cm

σ ~ truncated(Normal(0, 5), 0, 8)  # might make sense for one year of young students,
                                   # for adults this is too narrow

But this depends on the fact that we have a mean per age (not year) or that the range of
ages it pretty small.
"""


text:
# ---
# title: 1255. Maximum Score Words Formed by Letters
# id: problem1255
# author: Tian Jun
# date: 2020-10-31
# difficulty: Hard
# categories: Bit Manipulation
# link: <https://leetcode.com/problems/maximum-score-words-formed-by-letters/description/>
# hidden: true
# ---
#
# Given a list of `words`, list of  single `letters` (might be repeating) and
# `score` of every character.
#
# Return the maximum score of **any** valid set of words formed by using the
# given letters (`words[i]` cannot be used two or more times).
#
# It is not necessary to use all characters in `letters` and each letter can
# only be used once. Score of letters `'a'`, `'b'`, `'c'`, ... ,`'z'` is given
# by `score[0]`, `score[1]`, ... , `score[25]` respectively.
#
#
#
# **Example 1:**
#
#
#
#     Input: words = ["dog","cat","dad","good"], letters = ["a","a","c","d","d","d","g","o","o"], score = [1,0,9,5,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0]
#     Output: 23
#     Explanation:
#     Score  a=1, c=9, d=5, g=3, o=2
#     Given letters, we can form the words "dad" (5+1+5) and "good" (3+2+2+5) with a score of 23.
#     Words "dad" and "dog" only get a score of 21.
#
# **Example 2:**
#
#
#
#     Input: words = ["xxxz","ax","bx","cx"], letters = ["z","a","b","c","x","x","x"], score = [4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,10]
#     Output: 27
#     Explanation:
#     Score  a=4, b=4, c=4, x=5, z=10
#     Given letters, we can form the words "ax" (4+5), "bx" (4+5) and "cx" (4+5) with a score of 27.
#     Word "xxxz" only get a score of 25.
#
# **Example 3:**
#
#
#
#     Input: words = ["leetcode"], letters = ["l","e","t","c","o","d"], score = [0,0,1,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0]
#     Output: 0
#     Explanation:
#     Letter "e" can only be used once.
#
#
#
# **Constraints:**
#
#   * `1 <= words.length <= 14`
#   * `1 <= words[i].length <= 15`
#   * `1 <= letters.length <= 100`
#   * `letters[i].length == 1`
#   * `score.length == 26`
#   * `0 <= score[i] <= 10`
#   * `words[i]`, `letters[i]` contains only lower case English letters.
#
#
## @lc code=start
using LeetCode

## add your code here:
## @lc code=end


text:
"""
    store_group(identifier, group; filename_prefix = "closed_group_", filename_suffix = "")

Stores a given group as a serialized array in a file.
The identifier could be something like `"n"` where `n` is a characteristic number.
"""
function store_group(identifier, group; filename_prefix = "closed_group_", filename_suffix = "")
    filename = filename_prefix * identifier * filename_suffix
    serialize(filename, group)
end

"""
    load_group(identifier; filename_prefix = "closed_group_", filename_suffix = "") -> group

Loads a serialized group from a given file and returns the group.
"""
function load_group(identifier; filename_prefix = "closed_group_", filename_suffix = "")
    filename = filename_prefix * identifier * filename_suffix
    return deserialize(filename)
end


text:
# I want to try a pure MC simulation that doesn't rely on a neural network and
# see how things
using Statistics: mean, quantile
using StatsBase: countmap
using Game2048
using Game2048: bitboard_to_array, DIRS
using Serialization: serialize, deserialize
using Base.Threads
using BSON
using BenchmarkTools
using Flux.Data: DataLoader
using Flux: throttle
using Flux: softmax, onecold
# make a nn to study these games
using Flux, CUDA
using Flux: onehot, logitbinarycrossentropy, onehotbatch
CUDA.allowscalar(false)

@time x = deserialize("x-data.jls");
@time y = deserialize("y-data.jls");

sample_size = round(Int, size(x, 4)*0.99)

train_x = x[:, :, :, 1:sample_size] |> cu;
test_x = x[:, :, :, sample_size+1:end] |> cu;

train_y = y[:, 1:sample_size] |> cu;
test_y = y[:, sample_size+1:end] |> cu;

x=nothing; y=nothing;GC.gc() # free up memory

loss(x, y) = logitbinarycrossentropy(model(x), y)

# model = nothing
# if isfile("model_cpu")
#     model = BSON.load("model_cpu")[:model_cpu] |> gpu
# else
    model = Chain(
        Conv((2,2), 1=>16, relu),
        #Conv((2,2), 16=>16, relu),
        Conv((2,2), 16=>16),
        flatten,
        Dense(64, 4)
    ) |> gpu
# end

@time softmax(model(test_x))
@time softmax(model(test_x))
@time loss(test_x, test_y)
@time loss(test_x, test_y)

opt=ADAM()

dl = DataLoader((train_x, train_y); batchsize=2^19, shuffle=true);

accuracy(x, y) = mean(onecold(softmax(model(x))) .== onecold(y))

# @time accuracy(train_x, train_y)

last_loss = loss(test_x, test_y)
last_acc = accuracy(test_x, test_y)
worse_cnt = 0

function evalcb()
    global last_loss, worse_cnt, last_acc
    new_loss = loss(test_x, test_y)
    new_acc = accuracy(test_x, test_y)
    # println("train loss: $(loss(train_x, train_y)) train accuracy: $(accuracy(train_x, train_y))")
    println("test loss: $(new_loss) test accuracy: $(new_acc)")

    if (new_loss < last_loss) | (new_acc > last_acc)
        last_loss = new_loss
        last_acc = new_acc
        worse_cnt = 0
    else
        worse_cnt += 1
        if worse_cnt == 8
            Flux.stop()
        end
    end
end

@time evalcb()

cb = throttle(evalcb, 8)

dl2 = DataLoader((train_x[:,:,:,1:100], train_y[:, 1:100]); batchsize=32, shuffle=true);

@time Flux.train!(loss, Flux.params(model), dl2, opt; cb); # compile
@time Flux.train!(loss, Flux.params(model), dl, opt; cb); # compile
@time Flux.@epochs 8 Flux.train!(loss, Flux.params(model), dl, opt; cb);
@time Flux.@epochs 88 Flux.train!(loss, Flux.params(model), dl, opt; cb);
@time Flux.@epochs 888 Flux.train!(loss, Flux.params(model), dl, opt; cb);
@time Flux.@epochs 8888 Flux.train!(loss, Flux.params(model), dl, opt; cb);

model_cpu = model |> cpu
# @time BSON.@save "model_cpu" model_cpu

pcpu = Flux.params(model_cpu)
serialize("pcpu", pcpu)
pcpu = deserialize("pcpu")
Flux.loadparams!(model_cpu, pcpu)

# I want to see which move it's the most sure about

model(test_x)

mtx = softmax(model(test_x)) |> cpu

full_results = mapreduce(deserialize, vcat, readdir("c:/data/game2048/raw/", join=true)[2:2]);

one_game = full_results[1]

# which move did I regret the most?

game_matrix = cu(mapreduce(b->reshape(bitboard_to_array(b), 4, 4, 1, :), (a,b)->cat(a,b, dims=4), one_game.states) ./ 11)

moves_idx = Int.(one_game.moves) .+ 1

regret = softmax(model(game_matrix)) |> cpu

# find the move that regret most
_, pos = findmax([maximum(r)/r[idx] for (r, idx) in zip(eachslice(regret, dims=2), moves_idx)])

one_game.states[pos]
one_game.moves[pos] # the move that was made

# best move according to random play
countmap([Game2048.find_best_move(one_game.states[pos], 1000, Game2048.randompolicy) for i in 1:100])

prob = one_game.states[pos] |>
    bitboard_to_array |>
    (x->reshape(x, 4, 4, 1, :) ./ 11) |>
    cu |> model |> softmax

best_move = prob |> onecold |> cpu |>
    (x->DIRS[x[1]])

# the rest is just checking to see how the recommendations change in relations to recommendations
one_game.states[pos] |>
    bitboard_to_array |>
    (x->reshape(x, 4, 4, 1, :) ./ 11) |>
    cu |> model |> softmax

one_game.states[pos] |>
    bitboard_to_array |>
    rotl90 |>
    (x->reshape(x, 4, 4, 1, :) ./ 11) |>
    cu |> model |> softmax

one_game.states[pos] |>
    bitboard_to_array |>
    rotr90 |>
    (x->reshape(x, 4, 4, 1, :) ./ 11) |>
    cu |> model |> softmax

one_game.states[pos] |>
    bitboard_to_array |>
    rot180 |>
    (x->reshape(x, 4, 4, 1, :) ./ 11) |>
    cu |> model |> softmax


text:
function valid(string_to_validate)
   is_valid = true

   req_words  = ["byr","iyr","eyr","hgt", "hcl", "ecl", "pid"]

   for word in req_words
       if ! occursin(word, string_to_validate)
          is_valid = false
       end
   end

   return is_valid
end

f = open("input_day4","r")

temp_s = ""
valid_p = 0

#note that I modified my inputs to have an empty line at the end
for lines in readlines(f)
   #if not empty line concatenate de string with space
   if lines != ""
      global temp_s = temp_s*" "*lines
   else
      #println(temp_s)
      if valid(temp_s)
         global valid_p += 1
      end
      global temp_s = ""

   end
end

println(valid_p)


text:
let

using POMDPToolbox
using POMDPModels

problem = GridWorld()

policy = UniformRandomPolicy(problem)
sim = RolloutSimulator(max_steps=10)
simulate(sim, problem, policy)

policy = CategoricalTabularPolicy(problem)
sim = RolloutSimulator(max_steps=10)
simulate(sim, problem, policy)

policy = EpsGreedyPolicy(problem, 0.5)
sim = RolloutSimulator(max_steps=10)
simulate(sim, problem, policy)

end


text:
"""
    ExchangeSort(arr)

Sort an array by exchanging elements that are not in their proper position, hence Exchange Sort

Exchange Sort Steps
1. Compares each element of an array
2. Swap those elements that are not in their proper position

Example
1. An array of [1, 2, 4, 3, 5] and compare each elements
2. Since 4 is greater than 3
3. Swap both position
4. Returns [1, 2, 3, 4, 5]

Program to sort an array

# Example
```julia
ExchangeSort([5, 4, 3, 2, 1]) # returns [1, 2, 3, 4, 5]
ExchangeSort([1, 2, 3, 4, 5]) # returns [1, 2, 3, 4, 5]
ExchangeSort(['5', '4', '3', '2', '1']) # returns ['1', '2', '3', '4', '5']
```

Contributed By:- [Gervin Fung](https://github.com/GervinFung)
"""

function ExchangeSort!(arr::Vector{T})where T
    size=length(arr)
    for i in 1:size
        for j in i:size
            if (arr[i]>arr[j])
                temp = arr[j];
                arr[j] = arr[i];
                arr[i] = temp;
            end
        end
    end
end

max_stars_repo_name: KohRongSoon/Julia

max_issues_repo_name: KohRongSoon/Julia

max_forks_repo_name: KohRongSoon/Julia


text:
# ------ Smoothing functions often used to permit continuous differentiability -----

"""
    abs_smooth(x, delta_x)

Smooth out the absolute value function with a quadratic interval.
delta_x is the half width of the smoothing interval.
Typically usage is with gradient-based optimization.
"""
function abs_smooth(x, delta_x)

    if x < delta_x && x > -delta_x
        return x^2/(2*delta_x) + delta_x/2
    else
        return abs(x)
    end

end

# TODO AN: add smooth max/min with cubic splines


text:
module Plots

using Winston
using Params

export initplots, plot_ee, displayplots, plot_buf

const colors = ["blue"; "cyan"; "green"; "red"; "magenta"; "yellow"; "black"]

type PlotFig
    l :: Array{Any, 1}
    p :: FramedPlot
    PlotFig() = new({})
end

p_ee = PlotFig()
p_ee_conv = PlotFig()
p_th = PlotFig()
p_buf = PlotFig()

function initplots()
    p_ee.p = FramedPlot(
            title="EE vs Time (Cumulative)",
            xlabel="Time (time slots)",
            ylabel="EE (\\Sigma b/\\Sigma E) (b/J)")
    p_ee_conv.p = FramedPlot(
            title="EE vs Time (501 Pt Average)",
            xlabel="Time (time slots)",
            ylabel="EE (b/E) (b/J)")
    p_th.p = FramedPlot(
            title="Throughput vs Time (501 Pt Average)",
            xlabel="Time (time slots)",
            ylabel="Throughput (b)")
    p_buf.p = FramedPlot(
            title="Buffer Occupancy (501 Pt Average)",
            xlabel="Time (time slots)",
            ylabel="Buffer Occupancy (b)")
    p_ee.l = {}
    p_ee_conv.l = {}
    p_th.l = {}
    p_buf.l = {}
end

function plot_ee(energies, bits, agent, i)
    # start from 100 in total EE plot to see the differences more easily
    ee = Curve(100:t_total, vec(cumsum(sum(bits, 1), 2) ./ cumsum(sum(energies, 1), 2))[100:end], color=colors[i])
    setattr(ee, "label", agent)
    add(p_ee.p, ee)
    push!(p_ee.l, ee)
    ee_conv = Curve(500:t_total, conv(vec(sum(bits, 1) ./ sum(energies, 1)), fill(1./501, 501))[500:end-500], color=colors[i])
    setattr(ee_conv, "label", agent)
    add(p_ee_conv.p, ee_conv)
    push!(p_ee_conv.l, ee_conv)
    th = Curve(500:t_total, conv(vec(sum(bits, 1)), fill(1./501, 501))[500:end-500], color=colors[i])
    setattr(th, "label", agent)
    add(p_th.p, th)
    push!(p_th.l, th)
    nothing
end

function plot_buf(buf_levels, agent, i)
    # start from 100 in total EE plot to see the differences more easily
    buf = Curve(500:t_total, conv(vec(mean(buf_levels, 1)) .* Params.pkt_size, fill(1./501, 501))[500:end-500], color=colors[i])
    setattr(buf, "label", agent)
    add(p_buf.p, buf)
    push!(p_buf.l, buf)
    nothing
end

function displayplots()
    for p in [p_ee, p_ee_conv, p_th, p_buf]
        f=figure()
        add(p.p, Legend(.7, .7, p.l))
        display(p.p)
        figure(f)
        savefig(string(getattr(p.p, "title"), ".png"))
        savefig(string(getattr(p.p, "title"), ".svg"))
    end
end

end # module


text:
module Experiment

include("agent.jl")
include("cartpoleenv.jl")

const episodesnum = 10000000
const stepsnum = Env.fps * 10

struct History
    states::Vector{Env.State}
    actions::Vector{Float64}
    rewards::Vector{Float64}
end

function newhistory()
    states = Vector{Env.State}(undef, stepsnum)
    actions = Vector{Float64}(undef, stepsnum)
    rewards = Vector{Float64}(undef, stepsnum)
    History(states, actions, rewards)
end

function run()
    returns = Vector{Float64}(undef, episodesnum)
    qtable = Agent.newqtable()
    agentparams = Agent.defaultparams

    for episode = 1:episodesnum
        hist = oneepisode(agentparams, qtable)
        returns[episode] = sum(hist.rewards)
    end

    returns, qtable
end

function test(qtable)
    hist = oneepisode(Agent.defaulttestparams, qtable)
    hist, qtable
end

function oneepisode(agentparams, qtable)
    hist = newhistory()

    s = Env.newstate()
    a = 0.0
    r = 0.0

    for step = 1:stepsnum
        hist.states[step] = s
        hist.actions[step] = a
        hist.rewards[step] = r

        a = Agent.action(agentparams, qtable, s)
        snext = Env.onestep(s, a)
        r = Env.reward(snext, a)
        Agent.learn!(agentparams, qtable, s, a, r, snext)

        s = snext
    end

    hist
end

end

max_stars_repo_name: high-moctane/anylang-rl

max_issues_repo_name: high-moctane/anylang-rl

max_forks_repo_name: high-moctane/anylang-rl


text:
using Random
using Test
using LinearAlgebra

using Turing
using Turing.DynamicPPL

using StatsFuns: logistic

@testset "Turing" begin
    Turing.setprogress!(false)

    Random.seed!(100)

    # Load test utilities.
    testdir(args...) = joinpath(pathof(Turing), "..", "..", "test", args...)
    include(testdir("test_utils", "AllUtils.jl"))

    # Test HMC.
    include(testdir("inference", "hmc.jl"))
end


text:
# Once this stabilizes, migrate to a Graphics layer? Only if that supports text, which seems unlikely.
using Colors
using Graphics, Cairo

function annotate!(guidict::Dict, ann; anchored::Bool=true)
    c, zr = guidict["gui"]["canvas"], guidict["roi"]["zoomregion"]
    if anchored
        annf = AnchoredAnnotation((_)->canvasbb(c), (_)->zoombb(zr), ann)
    else
        annf = FloatingAnnotation((_)->canvasbb(c), ann)
    end
    h = hash(annf)
    add_annotation!(guidict["annotations"], h=>annf)
    AnnotationHandle(annf, h)
end

function add_annotation!(anns::Signal{Dict{UInt,Any}}, p::Pair)
    a = value(anns)
    push!(a, p)
    push!(anns, a)
end

struct AnnotationHandle{T}
    ann::T
    hash::UInt
end

function Base.delete!(anns::Signal{Dict{UInt,Any}}, anh::AnnotationHandle)
    delete!(value(anns), anh.hash)
    push!(anns, value(anns))
end
Base.delete!(guidict::Dict, anh::AnnotationHandle) = delete!(guidict["annotations"], anh)

function draw_annotations(canvas, anns)
    for (h, ann) in anns
        draw(canvas, ann)
    end
    nothing
end

function canvasbb(c)
    sz = size(widget(c))
    BoundingBox(1, sz[1], 1, sz[2])
end
function zoombb(zr)
    inds = axes(value(zr))
    BoundingBox(first(inds[2]), last(inds[2]), first(inds[1]), last(inds[1]))
end

abstract type AbstractAnnotation end

# Use this type when you want your annotation to be linked to particular data-coordinates
# (for example, to highlight a particular data point)
# devicebb(data) returns a BoundingBox in device coordinates, userbb(data) returns one in user coordinates.
# It's up to the draw() function to decide how to exploit these (most commonly, with set_coordinates())
mutable struct AnchoredAnnotation{T} <: AbstractAnnotation
    devicebb::Function
    userbb::Function
    data::T
    valid::Bool
end
AnchoredAnnotation(devicebb::Function, userbb::Function, data::T) where {T} =
    AnchoredAnnotation{T}(devicebb, userbb, data, true)

# Use this type when you want your annotation to appear at a specific point on the screen, regardless
# of zoom/resize state (e.g., a scale bar)
mutable struct FloatingAnnotation{T} <: AbstractAnnotation
    devicebb::Function
    data::T
end
# FloatingAnnotation{T}(devicebb::Function, data::T) = AnchoredAnnotation{T}(devicebb, data)

mutable struct AnnotationScalebarFixed{T}
    width::T   # Probably has units
    height::T
    getsize::Function   # syntax w,h = getsize(width,height)
    centerx::Float64
    centery::Float64
    color::Color
end

AnnotationScalebarFixed(width::T, height::T, imsl::Signal{M},
                        centerx::Real, centery::Real,
                        color::Color = RGB(1,1,1)) where {M<:AbstractMatrix,T} =
    AnnotationScalebarFixed{T}(width, height, (wp,hp) -> normalized_lengths(imsl,wp,hp),
                               Float64(centerx), Float64(centery), color)

## Text annotations

mutable struct AnnotationText
    x::Float64
    y::Float64
    z::Float64
    t::Float64
    string::AbstractString
    color::Color
    fontfamily::String
    fontoptions::String
    fontsize::Integer
    fontdesc::String
    angle::Float64
    halign::String
    valign::String
    markup::Bool
    scale::Bool
end

function AnnotationText(x::Real, y::Real, str::AbstractString;
                        z = NaN, t = NaN,
                        color = RGB(0,0,0), angle = 0.0, fontfamily = "sans", fontsize = 10,
                        fontoptions = "",  halign = "center", valign = "center",
                        markup = false, scale=true)
    AnnotationText(Float64(x), Float64(y), Float64(z),
                   Float64(t), str, color, fontfamily, fontoptions,
                   fontsize, fontdescription(fontfamily, fontoptions, fontsize),
                   Float64(angle), halign, valign, markup, scale)
end

fontdescription(fontfamily, fontoptions, fontsize) =
    string(fontfamily, " ", fontoptions, " ", fontsize)

## Point annotations

mutable struct AnnotationPoints{T}
    pts::T
    z::Float64
    t::Float64
    size::Float64
    shape::Char
    color::Color
    linewidth::Float64
    linecolor::Color
    scale::Bool
end

function AnnotationPoints(xys::Vector{Tuple{R,R}}=Tuple{Float64,Float64}[];
                          z = NaN, t = NaN, size=10.0, shape::Char='x', color = RGB(1,1,1),
                          linewidth=1.0, linecolor=color, scale::Bool=false) where R<:Real
    AnnotationPoints{typeof(xys)}(xys, z, t, float(size), shape, to_colorant(color),
                                  float(linewidth), to_colorant(linecolor), scale)
end

function AnnotationPoints(xys::Matrix{R}; z = NaN, t = NaN, size=10.0,
                          shape::Char='x', color = RGB(1,1,1), linewidth=1.0,
                          linecolor=color, scale::Bool=false) where R<:Real
    AnnotationPoints{Matrix{R}}(xys, z, t, float(size),
                                shape, to_colorant(color), float(linewidth),
                                to_colorant(linecolor), scale)
end

function AnnotationPoint(xy::Tuple{Real,Real}; z = NaN, t = NaN, size=10.0,
                         shape::Char='x', color = RGB(1,1,1), linewidth=1.0,
                         linecolor=color, scale::Bool=false)
    AnnotationPoints{Tuple{Float64,Float64}}((Float64(xy[1]),Float64(xy[2])),
                                             z, t, float(size), shape,
                                             to_colorant(color), float(linewidth),
                                             to_colorant(linecolor), scale)
end

AnnotationPoint(x::Real, y::Real; args...) =
    AnnotationPoint((Float64(x), Float64(y)); args...)

## Line annotations

mutable struct AnnotationLines{R<:Union{Real, Tuple{Real, Real}}, T}
    lines::T
    z::Float64
    t::Float64
    linecolor::Color
    linewidth::Float64
    coordinate_order::Vector{Int}

    function AnnotationLines{R,T}(lines::T, z, t, linecolor, linewidth, coord_order_str) where {R,T}
        ord = sortperm(codeunits(coord_order_str))
        @assert coord_order_str[ord] == "xxyy"
        new{R,T}(lines, z, t, linecolor, linewidth, ord)
    end
end

function AnnotationLines(lines::Vector{Tuple{Tuple{R, R},Tuple{R, R}}}=
                         Tuple{Tuple{Float64, Float64},Tuple{Float64, Float64}}[];
                         z = NaN, t = NaN, color=RGB(1,1,1),
                         linewidth=1.0, coord_order="xyxy") where R<:Real
    AnnotationLines{R,Vector{Tuple{Tuple{R,R},Tuple{R, R}}}}(lines, z, t, color,
                                                             linewidth, coord_order)
end

function AnnotationLines(lines::Matrix{R}; z = NaN, t = NaN, color=RGB(1,1,1),
                         linewidth=1.0, coord_order="xyxy") where R<:Real
    AnnotationLines{R, Matrix{R}}(lines, z, t, color, linewidth, coord_order)
end

function AnnotationLine(line::Tuple{Tuple{R,R},Tuple{R,R}};
                        z = NaN, t = NaN, color=RGB(1,1,1), linewidth=1.0) where R<:Real
    AnnotationLines{R,Tuple{Tuple{R,R},Tuple{R,R}}}(line, z, t, color, linewidth, "xyxy")
end

AnnotationLine(pt1::Tuple{Real,Real}, pt2::Tuple{Real,Real}; args...) =
    AnnotationLine((pt1, pt2); args...)

function AnnotationLine(c1::Real, c2::Real, c3::Real, c4::Real; coord_order="xyxy", args...)
    ord = sortperm(codeunits(coord_order))
    @assert coord_order[ord] == "xxyy"
    (x1,x2,y1,y2) = [c1,c2,c3,c4][ord]
    AnnotationLine((Float64(x1), Float64(y1)),
                   (Float64(x2), Float64(y2)); args...)
end

## Box annotations

mutable struct AnnotationBox
    left::Float64
    top::Float64
    right::Float64
    bottom::Float64
    z::Float64
    t::Float64
    linecolor::Color
    linewidth::Float64
end

function AnnotationBox(c1::Real, c2::Real, c3::Real, c4::Real; z = NaN, t = NaN,
                       color=RGB(1,1,1), linewidth=1.0, coord_order="xyxy")
    ord = sortperm(codeunits(coord_order))
    @assert coord_order[ord] == "xxyy"
    (x1, x2, y1, y2) = [c1, c2, c3, c4][ord]
    (x1, x2) = minmax(x1, x2)
    (y1, y2) = minmax(y1, y2)
    AnnotationBox(x1, y1, x2, y2, z, t, color, linewidth)
end

function AnnotationBox(pt1::Tuple{Real, Real}, pt2::Tuple{Real, Real};
                       coord_order="xyxy", args...)
    AnnotationBox(pt1..., pt2...; coord_order=coord_order, args...)
end

AnnotationBox(bb::BoundingBox; args...) = AnnotationBox(bb.xmin, bb.ymin, bb.xmax, bb.ymax; args...)

"""
    wnorm, hnorm = normalized_lengths(img, width, height)

Convert absolute `width` and `height` into normalized
variants. Depends on the [`pixelspacing`](@ref) of `img`.
"""
function normalized_lengths(imsl::AbstractMatrix, width, height)
    ps = pixelspacing(imsl)
    inds = axes(imsl)
    w = width/(ps[2]*length(inds[2]))
    h = height/(ps[1]*length(inds[1]))
    w, h
end
normalized_lengths(imsl::Signal, width, height) =
    normalized_lengths(value(imsl), width, height)

"""
    scalebar(guidict::Dict, length; x = 0.8, y = 0.1, color = RGB(1,1,1))

Add a scale bar annotation to the image display controlled by
`guidict` (returned by [`imshow`](@ref)). If the
[`pixelspacing`](@ref) of the image is set using Unitful quantities,
`length` should also be expressed in physical units.

`x` and `y` control the placement of the scalebar, and `color` its rendered color.
"""
function scalebar(guidict::Dict, length; x = 0.8, y = 0.1, color = RGB(1,1,1))
    imsl = guidict["roi"]["image roi"]
    ann = AnnotationScalebarFixed(length/1, length/10, imsl, x, y, color)
    annotate!(guidict, ann, anchored=false)
end

##############

setvalid!(ann::AnchoredAnnotation, z, t) = (ann.valid = annotation_isvalid(ann.data, z, t))

function annotation_isvalid(dat::Union{AnnotationText,
                                       AnnotationPoints,
                                       AnnotationLines,
                                       AnnotationBox}, z, t)
    (isnan(dat.z) || round(dat.z) == z) && (isnan(dat.t) || round(dat.t) == t)
end

annotation_isvalid(x, z, t) = true

function setvalid!(ann::FloatingAnnotation, z, t)
end

function Gtk.draw(c::Gtk.GtkCanvas, ann::AnchoredAnnotation)
    if ann.valid
        ctx = getgc(c)
        Graphics.save(ctx)
        data = ann.data
        set_coordinates(ctx, ann.devicebb(data), ann.userbb(data))
        scale_x = width(ann.userbb(data))/width(ann.devicebb(data))
        scale_y = height(ann.userbb(data))/height(ann.devicebb(data))
        draw_anchored(ctx, data, scale_x, scale_y)
        restore(ctx)
    end
end

function Gtk.draw(c::Gtk.GtkCanvas, ann::FloatingAnnotation{AnnotationScalebarFixed{T}}) where T
    ctx = getgc(c)
    Graphics.save(ctx)
    data = ann.data
    set_coordinates(ctx, ann.devicebb(data), BoundingBox(0,1,0,1))
    set_source(ctx, data.color)
    w, h = data.getsize(data.width, data.height)
    bb = BoundingBox(-w/2+data.centerx, w/2+data.centerx, -h/2+data.centery, h/2+data.centery)
    rectangle(ctx, bb)
    fill(ctx)
    restore(ctx)
end

function draw_anchored(ctx::GraphicsContext, data::AnnotationText, scale_x, scale_y)
    set_source(ctx, data.color)
    if data.scale && scale_x != 1
        fontdesc = fontdescription(data.fontfamily, data.fontoptions, round(Int,data.fontsize/scale_x))
    else
        fontdesc = data.fontdesc
    end
    Cairo.set_font_face(ctx, fontdesc)
    Cairo.text(ctx, data.x-0.5, data.y-0.5, data.string, halign = data.halign, valign = data.valign,
               angle = data.angle, markup = data.markup)
end

function draw_anchored(ctx::GraphicsContext, data::AnnotationPoints, scale_x, scale_y)
    set_line_width(ctx, data.linewidth)
    set_source(ctx, data.linecolor)
    if data.scale
        sz_x = sz_y = data.size
    else
        sz_x =  scale_x * data.size
        sz_y =  scale_y * data.size
    end
    draw_pts(ctx, data.pts, sz_x, sz_y, data.shape, data.color, data.linecolor)
end

draw_pts(ctx::GraphicsContext, pt::NTuple{2}, args...) = draw_pt(ctx, pt, args...)

function draw_pts(ctx::GraphicsContext, pts::Vector{Tuple{R,R}}, args...) where R<:Real
    for pt in pts
        draw_pt(ctx, pt, args...)
    end
end

function draw_pts(ctx::GraphicsContext, pts::Matrix, args...)
    @assert size(pts,1) == 2
    for i in 1:size(pts,2)
        pt = pts[:,i]
        draw_pt(ctx, pt, args...)
    end
end

function draw_pt(ctx::GraphicsContext, pt, sz_x, sz_y, shape::Char, color::Color, linecolor::Color)
    x::Float64,y::Float64 = pt
    hsz_x = sz_x/2
    hsz_y = sz_y/2

    if (shape == '.') | (shape == 'o')
        move_to(ctx, x, y)
        if sz_x == sz_y
            new_sub_path(ctx)
            circle(ctx, x, y, sz_x)
        else
            # draw an ellipse
            Graphics.save(ctx)
            translate(ctx, x, y)
            scale(ctx, sz_x, sz_y)
            new_sub_path(ctx)
            circle(ctx, 0, 0, 1);
            restore(ctx)
        end
        if shape == '.'
            set_source(ctx, color)
            fill_preserve(ctx)
            set_source(ctx, linecolor)
        end
    elseif (shape == 'x') | (shape == '*') | (shape == '+')
        if (shape == 'x') | (shape == '*')
            move_to(ctx, x-hsz_x, y-hsz_y)
            line_to(ctx, x+hsz_x, y+hsz_y)
            move_to(ctx, x-hsz_x, y+hsz_y)
            line_to(ctx, x+hsz_x, y-hsz_y)
        end
        if (shape == '+') | (shape == '*')
            move_to(ctx, x-hsz_x, y)
            line_to(ctx, x+hsz_x, y)
            move_to(ctx, x, y-hsz_y)
            line_to(ctx, x, y+hsz_y)
        end
    end

    stroke(ctx)
end

function draw_anchored(ctx::GraphicsContext, data::AnnotationLines, args...)
    set_line_width(ctx, data.linewidth)
    set_source(ctx, data.linecolor)
    draw_lines(ctx, data.lines, data.coordinate_order)
end

draw_lines(ctx::GraphicsContext, line::Tuple{Tuple{Real, Real},Tuple{Real, Real}}, _) =
    draw_line(ctx, line)

function draw_lines(ctx::GraphicsContext,
                    lines::Vector{Tuple{Tuple{R, R},Tuple{R, R}}}, _) where R<:Real
    for line in lines
        draw_line(ctx, line)
    end
end

function draw_lines(ctx::GraphicsContext, lines::Matrix{R}, coordinate_order) where R<:Real
    for i in 1:size(lines, 2)
        pt = tuple(lines[coordinate_order,i]...)
        draw_line(ctx, pt)
    end
end

function draw_lines(ctx::GraphicsContext, lines::Matrix{R}, _) where R<:Tuple{Real,Real}
    for i in 1:size(lines, 2)
        pt = tuple(lines[:,i]...)
        draw_line(ctx, pt)
    end
end

function draw_line(ctx::GraphicsContext, line::Tuple{Tuple{Real, Real},Tuple{Real, Real}})
    (x1, y1), (x2, y2) = line
    move_to(ctx, x1, y1)
    line_to(ctx, x2, y2)
    stroke(ctx)
end

function draw_line(ctx::GraphicsContext, line::Tuple{Real, Real, Real, Real})
    x1, y1, x2, y2 = line
    move_to(ctx, x1, y1)
    line_to(ctx, x2, y2)
    stroke(ctx)
end

## Box

function draw_anchored(ctx::GraphicsContext, data::AnnotationBox, args...)
    set_line_width(ctx, data.linewidth)
    set_source(ctx, data.linecolor)
    draw_box(ctx, data.top, data.bottom, data.left, data.right)
end

function draw_box(ctx::GraphicsContext, top, bottom, left, right)
    move_to(ctx, left, top)
    line_to(ctx, right, top)
    line_to(ctx, right, bottom)
    line_to(ctx, left, bottom)
    line_to(ctx, left, top)
    stroke(ctx)
end

to_colorant(c::Colorant) = c
to_colorant(str::AbstractString) = parse(Colorant, str)


text:
using Combinatorics
import Base: ==

"""
    ConditionalIndependence

Structure representing conditional independency between two variables given conditioned set of variables.
"""
struct ConditionalIndependence
    x::Symbol
    y::Symbol
    cond::Vector{Symbol}
end

==(a::ConditionalIndependence, b::ConditionalIndependence) = a.x == b.x && a.y == b.y && a.cond == b.cond

"""
    implied_conditional_independencies(dag)

From given DAG find all pair-wise conditional independencies of nodes.
Returns vector of `ConditionalIndependence` structures.

# Examples
```jldoctest
julia> using Dagitty

julia> g = DAG(:A => :C, :C => :B)
DAG: {3, 2} directed simple Int64 graph with labels [:A, :B, :C])

julia> implied_conditional_independencies(g)
1-element Vector{ConditionalIndependence}:
 ConditionalIndependence(:A, :B, [:C])
```
"""
function implied_conditional_independencies(dag::DAG)::Vector{ConditionalIndependence}
    max_set = length(dag.labels) - 2
    result = Vector{ConditionalIndependence}()
    nodes = Base.OneTo(length(dag.labels))
    for (n1, n2) ∈ combinations(nodes, 2)
        rest = [n for n ∈ nodes if n != n1 && n != n2]
        for cond ∈ powerset(rest)
            if is_d_separated(dag, [n1], [n2], cond)
                ci = ConditionalIndependence(dag.labels[n1], dag.labels[n2], dag.labels[cond])
                push!(result, ci)
            end
        end
    end
    result
end

"""
    implied_conditional_independencies_min

From given DAG return all pair-wise conditional independencies of nodes with
minimal condition set.

# Examples
```jldoctest
julia> using Dagitty

julia> plant_dag = Dagitty.DAG(:H_0 => :H_1, :F => :H_1, :T => :F)
DAG: {4, 3} directed simple Int64 graph with labels [:F, :H_0, :H_1, :T])

julia> implied_conditional_independencies_min(plant_dag)
3-element Vector{ConditionalIndependence}:
 ConditionalIndependence(:F, :H_0, Symbol[])
 ConditionalIndependence(:H_0, :T, Symbol[])
 ConditionalIndependence(:H_1, :T, [:F])

```
"""
function implied_conditional_independencies_min(dag::DAG)::Vector{ConditionalIndependence}
    s = implied_conditional_independencies(dag)
    [
        a for a ∈ s
        if !any(b -> b.x == a.x && b.y == a.y && b.cond != a.cond && b.cond ⊆ a.cond, s)
    ]
end

export
    ConditionalIndependence,
    implied_conditional_independencies,
    implied_conditional_independencies_min


text:
export getindex_async

struct GetIndex{T,N} <: ArrayOp{T,N}
    input::ArrayOp
    idx::Tuple
end

function GetIndex(input::ArrayOp, idx::Tuple)
    GetIndex{eltype(input), ndims(input)}(input, idx)
end

function stage(ctx, gidx::GetIndex)
    inp = cached_stage(ctx, gidx.input)

    dmn = domain(inp)
    idxs = [if isa(gidx.idx[i], Colon)
        indexes(dmn)[i]
    else
        gidx.idx[i]
    end for i in 1:length(gidx.idx)]

    # Figure out output dimension
    view(inp, ArrayDomain(idxs))
end

size(x::GetIndex) = Base.index_shape(x.input, x.idx...)

struct GetIndexScalar <: Computation
    input::ArrayOp
    idx::Tuple
end

function stage(ctx, gidx::GetIndexScalar)
    inp = cached_stage(ctx, gidx.input)
    s = view(inp, ArrayDomain(gidx.idx))
    delayed(identity)(collect(s)[1])
end

Base.getindex(c::ArrayOp, idx::ArrayDomain) = GetIndex(c, indexes(idx))
Base.getindex(c::ArrayOp, idx...) = GetIndex(c, idx)
Base.getindex(c::ArrayOp, idx::Integer...) =
   compute(GetIndexScalar(c, idx))


text:
module AFL

using AFLplusplus_jll

export init_target,
       run_target,
       classify_coverage,
       classify_coverage!,
       coverage_stats,
       mark_covered!,
       has_new_coverage

const RPC_RM_ID = 0;
const IPC_CREAT = 0o1000;
const SHM_RW = 0o600;
const MAP_SIZE = 1024 * 64
const EXEC_FAIL_SIG = UInt8[0xad, 0xde, 0xe1, 0xfe]

const CLASS_LOOKUP = vcat(
    [0, 1, 2, 4],
    [8   for _ in     4:7],
    [16  for _ in    8:15],
    [32  for _ in   16:31],
    [64  for _ in  32:127],
    [128 for _ in 128:255]
)

"""
    Result

Enum representing the return state of the running the target with an input.
"""
@enum Result begin
    Ok=0
    Crash=1
    Timeout=2
    Error=3
end

"""
    CoverageMap

An array of bytes used to describe the coverage an input generated. Each byte represents
a specific edge between in the code that can be covered, each bit represents a classification
of counts this edge was taken.
"""
struct CoverageMap
    edges::Vector{UInt8}

    CoverageMap() = new(fill(0x00, MAP_SIZE))
    CoverageMap(edges) = new(edges)
end

Base.copy(src::CoverageMap) = CoverageMap(copy(src.edges))
Base.:(==)(x::CoverageMap, y::CoverageMap) = x.edges == y.edges

"""
    InvCoverageMap

See [`CoverageMap`](@ref). This is an inverted version, which can be faster in some cases. Often used
to describe edges and counts not covered yet.
"""
struct InvCoverageMap
    edges::Vector{UInt8}

    InvCoverageMap() = new(fill(0xFF, MAP_SIZE))
    InvCoverageMap(edges) = new(edges)
end

Base.copy(src::InvCoverageMap) = InvCoverageMap(copy(src.edges))
Base.:(==)(x::InvCoverageMap, y::InvCoverageMap) = x.edges == y.edges

"""
    Target

Represents a running AFL forkserver and a shared memory segment for the branch bitmap. Create one with
[`init_target`](@ref) and close the handle with `close`.
"""
struct Target
    handle::Base.Process
    shm_id::Int
    trace_bits::Vector{UInt8}
    input_io::IOStream
end

function Base.close(target::Target)
    # detach the shared memory segment used for the branch bitmap
    @ccall shmdt(target.trace_bits::Ptr{UInt8})::Int32
    @ccall shmctl(target.shm_id::Int, RPC_RM_ID::Int32, 0::Int32)::Int32

    # kill the forkserver
    kill(target.handle)
end

"""
    init_target(target_path::String; qemu=false, memlimit=200)

Start a forkserver for the given target.
"""
function init_target(target_path::String; qemu::Bool=false, memlimit::Int=200)
    isfile(target_path) || error("Target '$target_path' does not exist")

    # TODO: check qemu supported on current platform

    # flags for the 64kb shared memory segment
    shmflags = IPC_CREAT + SHM_RW

    # create the shared memory segment
    shm_id = @ccall shmget(0::Int, MAP_SIZE::Int, shmflags::Int)::Int32
    if shm_id == -1
        error("Failed to initialise shared memory")
    end

    # and load it in the address space of the current process
    map_ptr = @ccall shmat(shm_id::Int, 0::Int, 0::Int)::Ptr{UInt8}
    if map_ptr == -1
        error("Failed to allocate shared memory")
    end

    # create a julia array covering the shared memory
    trace_bits = unsafe_wrap(Array, map_ptr, MAP_SIZE)

    # temporary file used for the input
    input_file, input_io = mktemp()

    # start the forkserver, passing the shared memory id as env variable
    env = Dict("__AFL_SHM_ID" => shm_id, "LD_BIND_NOW" => 1)
    shim = joinpath(@__DIR__, "../deps/afl-shim")

    # TODO: support cli args
    if qemu
        AFLplusplus_jll.afl_clang_fast() do afl
            qemu_exe = joinpath(dirname(afl), "afl-qemu-trace-x86_64")

            withenv("QEMU_LOG" => "nochain") do
                cmd = Cmd(`$shim $input_file $memlimit $qemu_exe -- $target_path`, env=env)
            end
        end
    else
        cmd = Cmd(`$shim $input_file $memlimit $target_path`, env=env)
    end

    handle = open(cmd, write=true, read=true)

    # read the 4 byte hello message from the AFL trampoline
    res = read(handle, 4)
    if length(res) != 4
        if trace_bits[1:4] == EXEC_FAIL_SIG
            error("Forkserver failed to start properly")
        else
            error("Failed handshake with forkserver")
        end
    end

    Target(handle, shm_id, trace_bits, input_io)
end

"""
    run_target(target::Target, input::Vector{UInt8}; timeout=1)

Run the target with the specified input. Times out after `timeout` seconds. Return value is a Result enum.
"""
function run_target(target::Target, input::Vector{UInt8}; timeout::Int=1)::Result
    # reset the branch bitmap
    fill!(target.trace_bits, 0)

    # write input to the temporary input file
    truncate(target.input_io, 0)
    write(target.input_io, input)
    flush(target.input_io)

    # write 4 bytes to the forkserver to trigger a fork
    write(target.handle, Int32(0))

    # get the pid of the child from the forkserver
    pid = read(target.handle, Int32)
    if pid == 0
        error("Did not receive child pid from forkserver")
    end

    # setup timeout
    timed_out = false
    status = 0xFFFF0000

    timeout_task = @async begin
        sleep(timeout)

        if status == 0xFFFF0000
            timed_out = true
            run(pipeline(`kill -9 $pid`, stdout=devnull, stderr=devnull))
        end
    end

    # get the status of the child from the forkserver, this will not return
    # until the target exits
    status = read(target.handle, UInt32)

    if ((status & 0x7f) + 1 >> 1) > 0
        signal = status & 0x7f

        # check if child timed out
        if signal == Base.SIGKILL && timed_out
            return Timeout
        end

        # check if the forkserver reported a failure
        if target.map[1:4] == EXEC_FAIL_SIG
            return Error
        end

        return Crash
    end

    Ok
end
run_target(target::Target, input::Base.CodeUnits{UInt8, String}; kws...) = run_target(target, Vector{UInt8}(input); kws...)

"""
    classify_coverage!(dst::CoverageMap, target::Target)

In place version of [`classify_coverage`](@ref).
"""
function classify_coverage!(dst::CoverageMap, target::Target)
    map!(dst.edges, target.trace_bits) do x
        CLASS_LOOKUP[x+1]
    end
end

"""
    classify_coverage(target::Target)

Convert the trace bits in the shared memory segment of the target to a classified coverage map.
"""
function classify_coverage(target::Target)
    map(target.trace_bits) do x
        CLASS_LOOKUP[x+1]
    end |> CoverageMap
end

"""
    edges_covered, classes_covered = coverage_stats(map::CoverageMap)
    edges_covered, classes_covered = coverage_stats(map::InvCoverageMap)

Calculate the ratio of edges and classes covered in the give coverage map. The maximum possible
coverage (1024 * 64 edges covered) is represented as 1.0.
"""
function coverage_stats(map::CoverageMap)::Tuple{Float32, Float32}
    edgecount = 0
    classcount = 0

    for edge in map.edges
        if edge != 0x00
            edgecount += 1
            classcount += count_ones(edge)
        end
    end

    edgecount / MAP_SIZE, classcount / (MAP_SIZE * 8)
end

function coverage_stats(map::InvCoverageMap)::Tuple{Float32, Float32}
    edgecount = 0
    classcount = 0

    for edge in map.edges
        if edge != 0xFF
            edgecount += 1
            classcount += count_zeros(edge)
        end
    end

    edgecount / MAP_SIZE, classcount / (MAP_SIZE * 8)
end

"""
    mark_covered!(dst::InvCoverageMap, src::CoverageMap)

Marks the edges and classes covered by `src` as covered in `dst`.
"""
function mark_covered!(dst::InvCoverageMap, src::CoverageMap)
    dst.edges .&= .~(src.edges)
end

"""
    has_new_coverage(dst::InvCoverageMap, src::CoverageMap)

Compares `dst` with `src` and returns `true` when `src` covers edges or classes not yet
marked as covered in `src`, otherwise returns `false`.
"""
function has_new_coverage(dst::InvCoverageMap, src::CoverageMap)::Bool
    any(x -> (x[1] & x[2]) != 0x0, zip(dst.edges, src.edges))
end

end # module


text:
u = 2.0collect(1:10)
t = 1.0collect(1:10)
A = LinearInterpolation(u,t)

@test length(A) == 20
for i in 1:10
  @test u[i] == A[i]
end

for i in 11:20
  @test t[i-10] == A[i]
end

A = LinearInterpolation{false}(u,t)
@test length(A) == 10
for i in 1:10
  @test u[i] == A[i]
end

using Symbolics
u = 2.0collect(1:10)
t = 1.0collect(1:10)
A = LinearInterpolation(u,t)

@variables t x(t)
substitute(A(t), Dict(t => x))


text:
@testset "AlgAssAbsOrdIdl" begin
  QG = group_algebra(FlintQQ, GrpAbFinGen([ 4 ]))

  @testset "Arithmetic" begin
    O = any_order(QG)
    I = 2*O
    J = 4*O

    @test I + J == I
    @test I*J == 8*O
    @test intersect(I, J) == J
    @test I^2 == J
    @test I^fmpz(2) == J
    @test norm(I) == 16
  end

  @testset "Prime ideals" begin
    A = Hecke.quaternion_algebra2(-1, -1)
    OA = maximal_order(A)

    p = prime_ideals_over(OA, 2)
    @test length(p) == 1
    @test p[1] == pradical(OA, 2)

    p = prime_ideals_over(OA, 3)
    @test length(p) == 1
    @test p[1] == 3*OA
  end

  #=
  @testset "Locally free basis" begin
    Qx, x = FlintQQ["x"]
    f = x^4 - 5x^2 + 5
    K, a = number_field(f, "a", cached = false, check = false) # Gal(K/Q) == C_4
    OK = maximal_order(K)

    KtoQG, QGtoK = Hecke._find_isomorphism(K, QG)
    basisOK = [ KtoQG(b.elem_in_nf) for b in basis(OK) ]
    d = lcm([ denominator(b) for b in basisOK ])
    ZG = Order(QG, basis(QG))
    I = Hecke.ideal_from_lattice_gens(QG, ZG, [ d*b for b in basisOK ])

    g = Hecke.locally_free_basis(I, 3)
    ZGg = ZG*g
    t = det(basis_matrix(I, copy = false)*basis_mat_inv(ZGg, copy = false))
    @test valuation(t, 3) == 0

    @test_throws ErrorException  Hecke.locally_free_basis(I, 2)
  end
  =#

  @testset "rand" begin
    Qx, x = FlintQQ["x"]
    A = AlgAss(x^2 - fmpq(1, 5))
    O = any_order(A)
    I = 2*O
    T = elem_type(A)

    @test rand(rng, I, 3) isa T
    @test rand(I, 3) isa T
    m = make(I, 3)
    @test Random.gentype(m) == T
    @test rand(m, 3) isa Vector{T}

    @test reproducible(I, 3)
  end
end


text:
module test_bukdu_plugs_prequisite_plugs

using Test

using Bukdu
@test length(Bukdu.bukdu_env[:prequisite_plugs]) == 1

empty!(Bukdu.bukdu_env[:prequisite_plugs])

using Bukdu
@test length(Bukdu.bukdu_env[:prequisite_plugs]) == 0

plug(Plug.Head)
@test length(Bukdu.bukdu_env[:prequisite_plugs]) == 1

end # module test_bukdu_plugs_prequisite_plugs


text:
using ElasticParallelism
using Test

@testset "ElasticParallelism.jl" begin
    # Write your own tests here.
end


text:
using Documenter, DashiBoard

let dir = joinpath(@__DIR__, "src", "tabs")
    for fn in readdir(joinpath(dir, "src"))
        open(joinpath(dir, fn), "w") do io
            for line in eachline(joinpath(dir, "src", fn), keep=true)
                m = match(r"{{([a-z]*)}}", line)
                if isnothing(m)
                    write(io, line)
                else
                    component = m[1]
                    path = joinpath(dir, "components", m[1] * ".md")
                    write(io, read(path))
                end
            end
        end
    end
end

makedocs(;
    modules=[DashiBoard],
    authors="Pietro Vertechi <pietro.vertechi@protonmail.com>",
    repo="https://github.com/piever/DashiBoard.jl/blob/{commit}{path}#{line}",
    sitename="Data Visualization",
    format=Documenter.HTML(;
        prettyurls=get(ENV, "CI", "false") == "true",
    ),
    pages=Any[
        "Home" => "index.md",
        "Getting Started" => "getting_started.md",
        "Tabs" => [
            "Load" => "tabs/load.md",
            "Filter" => "tabs/filter.md",
            "Predict" => "tabs/predict.md",
            "Cluster" => "tabs/cluster.md",
            "Project" => "tabs/project.md",
            "Visualize" => "tabs/visualize.md",
        ],
        "How to Guides" => [
            "Filter" => "how_to_guides/filter.md",
            "Visualize" => "how_to_guides/visualize.md",
        ],
        "API" => "API.md",
    ],
    strict=false, # FIMXE: change to true once all docstrings are included
)

deploydocs(;
    repo="github.com/piever/DashiBoard.jl",
    push_preview=true,
    devbranch="main",
)


text:
# Autogenerated wrapper script for Tesseract_jll for x86_64-unknown-freebsd11.1-cxx03
export tesseract, libtesseract

using Giflib_jll
using JpegTurbo_jll
using libpng_jll
using Libtiff_jll
using Zlib_jll
using Leptonica_jll
using CompilerSupportLibraries_jll
using Cairo_jll
using Pango_jll
## Global variables
PATH = ""
LIBPATH = ""
LIBPATH_env = "LD_LIBRARY_PATH"

# Relative path to `tesseract`
const tesseract_splitpath = ["bin", "tesseract"]

# This will be filled out by __init__() for all products, as it must be done at runtime
tesseract_path = ""

# tesseract-specific global declaration
function tesseract(f::Function; adjust_PATH::Bool = true, adjust_LIBPATH::Bool = true)
    global PATH, LIBPATH
    env_mapping = Dict{String,String}()
    if adjust_PATH
        if !isempty(get(ENV, "PATH", ""))
            env_mapping["PATH"] = string(PATH, ':', ENV["PATH"])
        else
            env_mapping["PATH"] = PATH
        end
    end
    if adjust_LIBPATH
        if !isempty(get(ENV, LIBPATH_env, ""))
            env_mapping[LIBPATH_env] = string(LIBPATH, ':', ENV[LIBPATH_env])
        else
            env_mapping[LIBPATH_env] = LIBPATH
        end
    end
    withenv(env_mapping...) do
        f(tesseract_path)
    end
end

# Relative path to `libtesseract`
const libtesseract_splitpath = ["lib", "libtesseract.so"]

# This will be filled out by __init__() for all products, as it must be done at runtime
libtesseract_path = ""

# libtesseract-specific global declaration
# This will be filled out by __init__()
libtesseract_handle = C_NULL

# This must be `const` so that we can use it with `ccall()`
const libtesseract = "libtesseract.so.4"

"""
Open all libraries
"""
function __init__()
    global artifact_dir = abspath(artifact"Tesseract")

    # Initialize PATH and LIBPATH environment variable listings
    global PATH_list, LIBPATH_list
    # We first need to add to LIBPATH_list the libraries provided by Julia
    append!(LIBPATH_list, [joinpath(Sys.BINDIR, Base.LIBDIR, "julia"), joinpath(Sys.BINDIR, Base.LIBDIR)])
    # From the list of our dependencies, generate a tuple of all the PATH and LIBPATH lists,
    # then append them to our own.
    foreach(p -> append!(PATH_list, p), (Giflib_jll.PATH_list, JpegTurbo_jll.PATH_list, libpng_jll.PATH_list, Libtiff_jll.PATH_list, Zlib_jll.PATH_list, Leptonica_jll.PATH_list, CompilerSupportLibraries_jll.PATH_list, Cairo_jll.PATH_list, Pango_jll.PATH_list,))
    foreach(p -> append!(LIBPATH_list, p), (Giflib_jll.LIBPATH_list, JpegTurbo_jll.LIBPATH_list, libpng_jll.LIBPATH_list, Libtiff_jll.LIBPATH_list, Zlib_jll.LIBPATH_list, Leptonica_jll.LIBPATH_list, CompilerSupportLibraries_jll.LIBPATH_list, Cairo_jll.LIBPATH_list, Pango_jll.LIBPATH_list,))

    global tesseract_path = normpath(joinpath(artifact_dir, tesseract_splitpath...))

    push!(PATH_list, dirname(tesseract_path))
    global libtesseract_path = normpath(joinpath(artifact_dir, libtesseract_splitpath...))

    # Manually `dlopen()` this right now so that future invocations
    # of `ccall` with its `SONAME` will find this path immediately.
    global libtesseract_handle = dlopen(libtesseract_path)
    push!(LIBPATH_list, dirname(libtesseract_path))

    # Filter out duplicate and empty entries in our PATH and LIBPATH entries
    filter!(!isempty, unique!(PATH_list))
    filter!(!isempty, unique!(LIBPATH_list))
    global PATH = join(PATH_list, ':')
    global LIBPATH = join(LIBPATH_list, ':')

    # Add each element of LIBPATH to our DL_LOAD_PATH (necessary on platforms
    # that don't honor our "already opened" trick)
    #for lp in LIBPATH_list
    #    push!(DL_LOAD_PATH, lp)
    #end
end  # __init__()


text:
import GLFW
import MuJoCo
import OpenNI

using MuJoCo
using OpenNI

using Cxx

include("../openNIMuJoCo.jl")
include("../common.jl")

###Record only once skeleton is detected and waits for the user to put their right hand by torso
g_elapseSinceLastEvent = 0
g_firstTime = true
g_sought = false
g_userFound = false
g_startPlaying = false
g_stopPlaying = false
g_origin = Vector{NIFloat}(3)
g_scale = 1

function mapToSimSpace(mapper::NIMJSimMapper, jointPos)
    #changes orientation of gravity, now z->x, y->z, x->y
    #torso is uwaist
    origin_mj = sim.data.xpos[mj_name2id(sim.model, icxx"mjOBJ_BODY;", "lwaist"), :]

    #adjust kinect joint to axis based at init pose
    mjPos = jointPos - g_origin
    #mjPos[3] *= -1 #mirroring

    #shift gravity to mjc space
    temp = last(mjPos)
    for i=length(mjPos):2
        mjPos[i] = mjPos[i - 1]
    end
    mjPos[1] = temp

    #TODO scale down
    mjPos *= g_scale

    #adjust to axis in mjc
    mjPos += origin_mj

    return mjPos
end

function setMJJointPos(mapper, jointPos, jntID)
    for i=1:3
        sim.data.xpos.mat[i, jntID] = jointPos[i]
    end
end

function setMJJoints(mapper, skeleton, jointIDMap)
    NIids = collect(keys(jointIDMap))
    for i=1:length(NIids)
        setMJJointPos(mapper, mapToSimSpace(mapper, skeleton.jointPos[NIids[i], :]), get(jointIDMap, NIids[i], nothing))
    end
end

println("Setting up OpenNI")

#Init without any preloaded nodes
print("Creating context...")

context = NIContext()
InitContext(context)

println("Done!")
print("Creating Player...")

player = NIPlayer()

OpenContextFileRecording(player, context,  joinpath(@__DIR__,"../../data/$(ARGS[1]).oni"))

println("Done!")
print("Attaching generators...")

#Now create a UserGenerator node
usergen = NIUserGenerator()
CreateUserGenerator(usergen, context)

#Function for callbacks (new and lost user)
function userFound()
    println("User recognized. Waiting for pose.")
end

function userLost()
    g_stopPlaying = true
    println("User lost. Stopping simulation.")
end

RegisterUserCallbacks(usergen, userFound, userLost)

println("Done!")
print("Setting up MuJoCo...")

mj_activate()
sim = MJSimEnv(MJModel(joinpath(@__DIR__,"../../reaching.xml")), s -> (0), s -> (0))

window = GLFW.CreateWindow(640, 480, "demo")
GLFW.MakeContextCurrent(window)
GLFW.SwapInterval(1)

renderer = MJRenderer(sim.data)

width = Int32(0)
height = Int32(0)
mj_step(sim.model, sim.data)

println("Done!")
print("Setting up connection between the two interfaces...")

mapper = NIMJSimMapper(sim, context, usergen, Int32(1), mapToSimSpace)
println(sim.data.xpos[mj_name2id(sim.model, icxx"mjOBJ_BODY;", "target1-1"), :])

println("Done!")
print("Starting playback...")

#Begin generators
StartGeneratingAll(context)

#init array of user IDs
userIDs = Vector{UInt32}(2)
frames = 0
tic()
#start program loop
while (!GLFW.WindowShouldClose(window))
    #each frame update, but wait for usergen to have new data
    WaitOneUpdateAll(context, usergen)

    if g_firstTime && !g_userFound
        frames += 1
    elseif !g_firstTime && !g_userFound && !g_sought
        #SeekToFrame(player, usergen, Int32(frames))
        g_sought = true
    end

    userIDs = GetUsers(usergen, userIDs)

    for i=1:length(userIDs)
        #If tracking, print head coordinates
        if (IsTrackingUser(usergen, userIDs[i]))

            skeleton = NISkeleton(usergen, userIDs[i])

            #Render MuJoCo
            #mj_step??, set positions from skeleton

            width, height = GLFW.GetFramebufferSize(window);
            mjv_updateScene(renderer)
            mjr_render(renderer, width, height)

        	GLFW.SwapBuffers(window)
        	GLFW.PollEvents()

            #PERFORM OPENNI PROCESSING
            jntRightHandID = Int(OpenNI.NI_SKEL_LEFT_HAND) #mirrored
            jntTorsoID = Int(OpenNI.NI_SKEL_TORSO)
            dist = distance(skeleton.jointPos[jntRightHandID, :], skeleton.jointPos[jntTorsoID, :])

            g_elapseSinceLastEvent += toq()
            tic()

            if (!g_userFound && dist < 250)
                g_userFound = true
                print("User struck pose, beginning motion in 2 seconds...")

                #calculate origin
                g_origin = deepcopy(skeleton.jointPos[jntTorsoID, :])
                println("Origin:", g_origin)

                g_scale = .16 / distance(skeleton.jointPos[jntRightHandID, :], skeleton.jointPos[Int(OpenNI.NI_SKEL_RIGHT_ELBOW), :])

                g_elapseSinceLastEvent = 0
                tic()
            end

            if (g_userFound && !g_startPlaying && g_elapseSinceLastEvent > 2)
                println("Starting motion...")
                g_startPlaying = true
                g_elapseSinceLastEvent = 0
                tic()
            end

            if (g_startPlaying)
                convertSkeletonToMJ(sim, skeleton, g_origin)
                mj_forward(sim.model, sim.data)
            end

            if (g_startPlaying && g_stopPlaying)
                println("Finished playback, restarting")
                g_elapseSinceLastEvent = 0
                g_firstTime = false
                g_sought = false
                g_userFound = false
                g_startPlaying = false
                g_stopPlaying = false
                g_origin = Vector{NIFloat}(3)
                g_scale = 1
                ResetEnv(sim)
            end
        end #IsTrackingUser
    end #for
end
GLFW.Terminate()


text:
include(joinpath("..", "src", "simulation.jl"))
include(joinpath("..", "src", "03runeval.jl"))

################################################################################
####                Calculate CSV for results evaluation in R               ####

results = DataFrame(
    BatchName = String[],
    ConfigAgentCount = Int64[],
    ConfigUnfriendThresh = Float64[],
    ConfigAddfriendMethod = String[],
    Densities = Float64[],
    OutdegreeSD = Float64[],
    IndegreeSD = Float64[],
    OutdegreeIndegreeRatioMean = Float64[],
    ClosenessCentralityMean = Float64[],
    BetweennessCentralityMean = Float64[],
    EigenCentralityMean = Float64[],
    ClustCoeff = Float64[],
    CommunityCount = Int64[],
    CommunityCountNontrivial = Int64[],
    ConnectedComponents = Int64[],
    OpinionSD = Float64[],
    OpChangeDeltaMean = Float64[],
    PublOwnOpinionDiff = Float64[],
    SupernodeOutdegree = Int64[],
    SupernodeCloseness = Float64[],
    SupernodeBetweenness = Float64[],
    SupernodeEigen = Float64[],
    SupernodeOpinion = Float64[],
    Supernode1st2ndOpdiff = Float64[],
    CommunityOpMeanSDs = Float64[]
)

for file in readdir("results")
    if (
        (occursin("Netsize", file) || occursin("Addfriends", file) || occursin("Unfriend", file))
        && occursin(".jld2", file) && !occursin("singlerun", file)
    )
        raw = load(joinpath("results", file))
        current_run = raw[first(keys(raw))]
        repcount = length(current_run)
        nodes_ranked = [first.(sort([(i, outdegree(current_run[j].final_state[1], i)) for i in 1:nv(current_run[j].final_state[1])], by=last, rev=true)) for j in 1:repcount]

        opinionsd = [std([agent.opinion for agent in current_run[i].final_state[2]]) for i in 1:repcount]
        opchange_delta_mean = [mean([abs(current_run[j].init_state[2][i].opinion - current_run[j].final_state[2][i].opinion) for i in 1:current_run[j].config.network.agent_count]) for j in 1:repcount]
        densities = [density(current_run[i].final_state[1]) for i in 1:repcount]
        outdegree_sd = [std(outdegree(current_run[i].final_state[1])) for i in 1:repcount]
        outdegree_mean = [mean(outdegree(current_run[i].final_state[1])) for i in 1:repcount]
        indegree_sd = [std(indegree(current_run[i].final_state[1])) for i in 1:repcount]
        outinratio = [mean([outdegree(current_run[i].final_state[1], j) / degree(current_run[i].final_state[1], j) for j in 1:nv(current_run[i].final_state[1]) if degree(current_run[i].final_state[1], j) > 0]) for i in 1:repcount]
        publownopiniondiff = [mean([abs(agent.perceiv_publ_opinion - agent.opinion) for agent in current_run[i].final_state[2]]) for i in 1:repcount]
        closeness_centrality_mean = [mean(closeness_centrality(current_run[i].final_state[1])) for i in 1:repcount]
        betweenness_centrality_mean = [mean(betweenness_centrality(current_run[i].final_state[1])) for i in 1:repcount]
        eigen_centrality_mean = [mean(eigenvector_centrality(current_run[i].final_state[1])) for i in 1:repcount]
        supernode_outdegree = [outdegree(current_run[i].final_state[1], nodes_ranked[i][1]) for i in 1:repcount]
        supernode_closeness = [closeness_centrality(current_run[i].final_state[1])[nodes_ranked[i][1]] for i in 1:repcount]
        supernode_betweenness = [betweenness_centrality(current_run[i].final_state[1])[nodes_ranked[i][1]] for i in 1:repcount]
        supernode_eigen = [eigenvector_centrality(current_run[i].final_state[1])[nodes_ranked[i][1]] for i in 1:repcount]
        supernode_opinion = [current_run[i].final_state[2][nodes_ranked[i][1]].opinion for i in 1:repcount]
        supernode1st2nd_opdiff = [abs(current_run[i].final_state[2][nodes_ranked[i][1]].opinion - current_run[i].final_state[2][nodes_ranked[i][2]].opinion) for i in 1:repcount]
        clust_coeff = [global_clustering_coefficient(current_run[i].final_state[1]) for i in 1:repcount]
        conn_components = [length(connected_components(current_run[i].final_state[1])) for i in 1:repcount]

        # Calc the SD of the opinion means of the identified clusters
        n_communities = Int64[]
        community_opinion_mean_sds = Float64[]
        n_communities_nontrivial = Int64[]
        for i in 1:repcount
            label_prop = label_propagation(current_run[i].final_state[1])[1]
            community_sizes = last.(collect(countmap(label_prop)))
            push!(n_communities_nontrivial, length([i for i in community_sizes if i > 1]))
            push!(n_communities, maximum(label_prop))
            if maximum(label_prop) == 1
                push!(community_opinion_mean_sds, 0)
                continue
            end
            push!(community_opinion_mean_sds, std([mean([agent.opinion for agent in current_run[i].final_state[2] if agent.id in findall(x->x==j, label_prop)]) for j in 1:maximum(label_prop)]))
        end

        append!(
            results,
            DataFrame(
                BatchName = file[1:first(findfirst("_", file)) - 1],
                ConfigAgentCount = current_run[1].config.network.agent_count,
                ConfigUnfriendThresh = current_run[1].config.opinion_threshs.unfriend,
                ConfigAddfriendMethod = current_run[1].config.simulation.addfriends,
                Densities = densities,
                OutdegreeSD = outdegree_sd,
                IndegreeSD = indegree_sd,
                OutdegreeIndegreeRatioMean = outinratio,
                ClosenessCentralityMean = closeness_centrality_mean,
                BetweennessCentralityMean = betweenness_centrality_mean,
                EigenCentralityMean = eigen_centrality_mean,
                ClustCoeff = clust_coeff,
                CommunityCount = n_communities,
                CommunityCountNontrivial = n_communities_nontrivial,
                ConnectedComponents = conn_components,
                OpinionSD = opinionsd,
                OpChangeDeltaMean = opchange_delta_mean,
                PublOwnOpinionDiff = publownopiniondiff,
                SupernodeOutdegree = supernode_outdegree,
                SupernodeCloseness = supernode_closeness,
                SupernodeBetweenness = supernode_betweenness,
                SupernodeEigen = supernode_eigen,
                SupernodeOpinion = supernode_opinion,
                Supernode1st2ndOpdiff = supernode1st2nd_opdiff,
                CommunityOpMeanSDs = community_opinion_mean_sds
            )
        )
    end
end

using CSV

CSV.write("results.csv", results)

####                                                                        ####
################################################################################

################################################################################
####                Generate Prototype Data for batchruns                   ####

for file in readdir("results")
    if (
            (
                occursin("Netsize", file)
                || occursin("Addfriends", file)
                || occursin("Unfriend", file)
            )
            && occursin(".jld2", file)
            && !occursin("singlerun", file)
        )

        raw = load(joinpath("results", file))
        current_run = raw[first(keys(raw))]

        prototype = rerun_single(get_prototype(current_run))

        CSV.write(
            joinpath("results", "$(prototype.name)_prototype_agent_log" * ".csv"),
            prototype.agent_log
        )

        CSV.write(
            joinpath("results", "$(prototype.name)_prototype_agent_communities" * ".csv"),
            prototype.final_state[3]
        )

        savegraph(
            joinpath("results", "$(prototype.name)_prototype_graph.gml"),
            prototype.final_state[1],
            GraphIO.GML.GMLFormat()
        )
    end
end

####                                                                        ####
################################################################################