text:
using DataFrames

### Figure ###
type Figure
    path
    name
    caption
    tex
    width

    function Figure(stream::IO, md::Markdown.MD)
        data = YAML.load(stream)
        push!(md, new(
            get(data, "path", ""),
            get(data, "name", ""),
            Markdown.parseinline(get(data, "caption", ""), md),
            get(data, "tex", ""),
            get(data, "width", "")
        ))
    end
end

# Prototype for future rendering method rendering style is
# specified on a per-field basis
function META(md::Figure)
    return Dict(
        :path => :raw,
        :name => :raw,
        :caption => :interpreted,
        :tex => :raw
    )
end

### Table ###
type Table
    path
    name
    content
    caption
    headers
    alignment

    function Table(stream::IO, md::Markdown.MD)
        data = YAML.load(stream)
        path = data["path"]
        df = DataFrame() # Because the try statement puts it out of scope

        try
            params = convert(Dict{Symbol, Any}, get(data, "parse", Dict()))
            df = readtable(path; params...)
        catch
            warn("Unabel to read `$(path)` into table.")
            return false
        end

        # Get the user specified column headers and alignment info
        col_meta = get(data, "columns", fill(Dict(), ncol(df)))
        if length(col_meta) != ncol(df)
            warn("Number of columns for table does not match number detected in CSV `$(data["path"])`")
            col_meta = fill(Dict(), ncol(df))
        end

        push!(md, new(
            path,
            get(data, "name", ""),
            gettablecontent(data, col_meta, df),
            Markdown.parseinline(get(data, "caption", ""), md),
            getcolumnheaders(col_meta, df),
            getcolumnalignment(col_meta, df)
        ))
    end
end

""" Takes in a dataframe and converst a format easily renderable by Jinja"""
function gettablecontent(data, col_meta, df)
    fmt = getformattingstrings(col_meta)
    return map(eachrow(df)) do row
        # Apply formatting string to each element
        return [format(fmt[i], row[i]) for i in 1:length(row)]
    end
end

""" Returns a list of formatting string (default is "{}")"""
function getformattingstrings(data)
    return map(data) do x
        get(x, "format", "{}")
    end
end

""" Returns a canonical list of column headers"""
function getcolumnheaders(data, df)
    return map(zip(data, names(df))) do x
        return get(x[1], "header", string(x[2]))
    end
end

""" Returns the column alignment based on explicit user input or infered
elignment

Infered Inputs
• String → left
• Int → right
• Float → decimal
• Everything else → left
"""
function getcolumnalignment(data, df)
    col_types = map(names(df)) do cn
        return eltype(df[cn])
    end
    return map(zip(data, col_types)) do col
        return get(col[1], "align", getcolumnalignment(col[2]))
    end
end

""" Given a type, returns the proper table alignment """
function getcolumnalignment(t::Type)
    if t <: Int
        return "right"
    elseif t <: Float64 # There is no AbstractFloat :(
        return "decimal"
    else
        return "left"
    end
end

Base.get(col::Void, key, default) = return default

### Equation ###
type Equation
    name
    content

    function Equation(stream::IO, md::Markdown.MD)
        data = YAML.load(stream)
        push!(md, new(
            get(data, "name", ""),
            get(data, "content", "")
        ))
    end
end

### Tex ###
type Tex
    content

    Tex(s::AbstractString) = new(s)
    function Tex(stream::IO, md::Markdown.MD)
        data=readstring(stream)
        push!(md, new(data))
    end
end

###  Document ###
type Document
    data

    function Document(stream::IO, md::Markdown.MD)
        data = YAML.load(stream)
        push!(md, new(data))
    end
end

function YAMLelement(stream::IO, md::Markdown.MD)
    elements = Dict(
        ".Figure" => Figure,
        ".Table" => Table,
        ".Equation" => Equation,
        ".Tex" => Tex,
        ".Document" => Document,
    )

    # Check if the line starts with one of our keywords
    block_type = ""
    for key in keys(elements)
        if Markdown.startswith(stream, key, padding=false) || Markdown.startswith(stream, lowercase(key), padding=false)
            isempty(strip(readline(stream))) || return false
            block_type = key
            break
        end
    end

    # If nothing, just quit
    if block_type == ""
        return false
    end

    # Now finish the run
    buffer = IOBuffer()
    while !eof(stream)
        line_start = position(stream)

        if rstrip(readline(stream)) == "end"
            elements[block_type](seek(buffer, 0), md)
            return true
        end
        # Now that we've check the line, push it into buffer
        seek(stream, line_start)
        write(buffer, readline(stream))
    end

    return false
end

# –––––
# Lists
# –––––

type List
    items::Vector{Any}
    ordered::Bool
    startval::Int

    List(x::AbstractVector, b::Bool, s::Int) = new(x, b, s)
    List(x::AbstractVector, b::Bool) = new(x, b, 0)
    List(x::AbstractVector) = new(x, false, 0)
    List(b::Bool) = new(Any[], b, 0)
end

List(xs...) = List(vcat(xs...))

const bullets = "*•+-"
const num_or_bullets = r"^(\*|•|\+|-|\d+(\.|\))) "

# Todo: ordered lists, inline formatting
function list(stream::IO, block::Markdown.MD)
    withstream(stream) do
        eatindent(stream) || return false
        b = startswith(stream, num_or_bullets)
        (b === nothing || b == "") && return false
        ordered = !(b[1] in bullets)
        if ordered
            b = b[end - 1] == '.' ? r"^\d+\. " : r"^\d+\) "
            # TODO start value
        end
        the_list = List(ordered)

        buffer = IOBuffer()
        fresh_line = false
        while !eof(stream)
            if fresh_line
                sp = startswith(stream, r"^ {0,3}")
                if !(startswith(stream, b) in [false, ""])
                    push!(the_list.items, parseinline(takebuf_string(buffer), block))
                    buffer = IOBuffer()
                else
                    # TODO write a newline here, and deal with nested
                    write(buffer, ' ', sp)
                end
                fresh_line = false
            else
                c = read(stream, Char)
                if c == '\n'
                    eof(stream) && break
                    next = Char(peek(stream)) # ok since we only compare with ASCII
                    if next == '\n'
                        break
                    else
                        fresh_line = true
                    end
                else
                    write(buffer, c)
                end
            end
        end
        push!(the_list.items, parseinline(takebuf_string(buffer), block))
        push!(block, the_list)
        return true
    end
end


text:
test_folder = "single-artery"
cd(test_folder)

openBF.runSimulation("$test_folder.yml", verbose=true, out_files=false)

p = readdlm("$test_folder"*"_results/A1_P.last")

@test isapprox(minimum(p[:,end]), 9522.0, atol=1)
@test isapprox(mean(p[:,end]), 12712.0, atol=1)
@test isapprox(maximum(p[:,end]), 16772.0, atol=1)

rm("$test_folder"*"_results/", recursive=true)
cd("..")

ext: jl


text:
module ISMRM_nonCartesianReconstruction_Exercises

import Pluto

function run()
    Pluto.run(notebook=joinpath(dirname(pathof(ISMRM_nonCartesianReconstruction_Exercises)), "nonCart_PlutoNotebook.jl"))
end

end # module


text:
"""
    alloc_size(::Type{T}, args...) where {T}

The number of additional bytes needed to allocate `T`, other than `sizeof(T)` itself.

Defaults to 0.
"""
alloc_size(::Type{T}) where T = 0

"""
    init(man::Manual{T}, args...) where T

Initialize `man`.
"""
function init(man::Manual{T}, args...) where T
    init(man.ptr + sizeof(T), man, args...)
    nothing
end

"""
    init(ptr::Ptr{Void}, man::Manual{T}, args...)::Ptr{Void} where T

Initialize `man`, where `ptr` is the beginning of the remaining free space. Must return `ptr + alloc_size(T, args...)`. Override this method to add custom initializers for your types.

The default implementation where `alloc_size(T) == 0` does nothing.
"""
function init(ptr::Ptr{Void}, man::Manual{T}) where T
    @assert alloc_size(T) == 0 "Default init cannot be used for types for which alloc_size(T) != 0"
    # TODO should we zero memory?
    ptr
end

alloc_size(::Type{Manual{T}}, args...) where T = sizeof(T) + alloc_size(T, args...)

function init(ptr::Ptr{Void}, man::Manual{Manual{T}}, args...) where T
    @v man = Manual{T}(ptr)
    t = Manual{T}(ptr)
    t_ptr = ptr + sizeof(T)
    init(t_ptr, t, args...)
end

alloc_size(::Type{ManualVector{T}}, length::Int64) where {T} = sizeof(T) * length

function init(ptr::Ptr{Void}, pv::Manual{ManualVector{T}}, length::Int64) where T
    @v pv.ptr = Manual{T}(ptr)
    @v pv.length = length
    ptr + alloc_size(ManualVector{T}, length)
end

alloc_size(::Type{ManualBitVector}, length::Int64) = UInt64(ceil(length / sizeof(UInt64)))

function init(ptr::Ptr{Void}, pv::Manual{ManualBitVector}, length::Int64)
    @v pv.ptr = Manual{UInt64}(ptr)
    @v pv.length = length
    ptr + alloc_size(ManualBitVector, length)
end

alloc_size(::Type{ManualString}, length::Int64) = length

function init(ptr::Ptr{Void}, ps::Manual{ManualString}, length::Int64)
    @v ps.ptr = Manual{UInt8}(ptr)
    @v ps.len = length
    ptr + alloc_size(ManualString, length)
end

alloc_size(::Type{ManualString}, string::Union{String, ManualString}) = string.len

function init(ptr::Ptr{Void}, ps::Manual{ManualString}, string::Union{String, ManualString})
    ptr = init(ptr, ps, string.len)
    unsafe_copy!((@v ps), string)
    ptr
end

"""
    malloc(::Type{T}, args...)::Manual{T} where T

Allocate and initialize a new `Manual{T}`.
"""
function malloc(::Type{T}, args...)::Manual{T} where T
    size = sizeof(T) + alloc_size(T, args...)
    ptr = Libc.malloc(size)
    man = Manual{T}(ptr)
    end_ptr = init(ptr + sizeof(T), man, args...)
    @assert end_ptr - ptr == size
    man
end


text:
using Reexport

@reexport module BinningSchemes

import CausalityToolsBase: RectangularBinningScheme

VALIDRECTBINS = Union{Int, Float64, Vector{Int}, Vector{Float64}, Tuple{Vector{Tuple{Float64,Float64}},Int64}}

"""
InducedRectangularBinning

Instructions for creating a rectangular target partition and a rectangular source partition.

## Fields

- **`ϵ::Union{Int, Float64, Vector{Int}, Vector{Float64}}`**: The instructions for deciding
the edge lengths of the rectangular boxes. The following `ϵ` are valid:
    1. `ϵ::Int` divides each axis into `ϵ` intervals of the same size.
    2. `ϵ::Float` divides each axis into intervals of size `ϵ`.
    3. `ϵ::Vector{Int}` divides the i-th axis into `ϵᵢ` intervals of the same size.
    4. `ϵ::Vector{Float64}` divides the i-th axis into intervals of size `ϵᵢ`.
"""
struct InducedRectangularBinning <: RectangularBinningScheme
    ϵ_target_partition::VALIDRECTBINS
    ϵ_source_partition::VALIDRECTBINS
end

"""
AverageRectangularBinning

Instructions for constructing a rectangular target partition and multiple source
partitions.

## Fields

- **`ϵ_target_partition`::Union{Int, Float64, Vector{Int}, Vector{Float64}}`**: The
instructions for deciding the edge lengths of the rectangular boxes of the target
partition. The following `ϵ` are valid:
    1. `ϵ::Int` divides each axis into `ϵ` intervals of the same size.
    2. `ϵ::Float` divides each axis into intervals of size `ϵ`.
    3. `ϵ::Vector{Int}` divides the i-th axis into `ϵᵢ` intervals of the same size.
    4. `ϵ::Vector{Float64}` divides the i-th axis into intervals of size `ϵᵢ`.

- **`ϵs_source_partitions::Vector{Union{Int, Float64, Vector{Int}, Vector{Float64}}}`**: The
instructions for deciding the edge lengths of the rectangular boxes of the source
partitions. The following `ϵ` are valid:
    1. `ϵ::Int` divides each axis into `ϵ` intervals of the same size.
    2. `ϵ::Float` divides each axis into intervals of size `ϵ`.
    3. `ϵ::Vector{Int}` divides the i-th axis into `ϵᵢ` intervals of the same size.
    4. `ϵ::Vector{Float64}` divides the i-th axis into intervals of size `ϵᵢ`.
"""
struct AverageRectangularBinning <: RectangularBinningScheme
    ϵ_target_partition::VALIDRECTBINS
    ϵs_source_partitions::VALIDRECTBINS
end

export
InducedRectangularBinning,
AverageRectangularBinning

end # module

"""
    BinningSchemes

Defines rectangular binning schemes used in the PerronFrobenius package not present
in CausalityToolsBase.
"""
BinningSchemes


text:
# To use the solution, the input data is required

mutable struct Action
    id::String
    location_id::String
    operation_type::Int # 0- Depot, 1 - Pickup, 2 - Delivery, 3 - otherOperation # should be picked quantity
    request_id::String # if any request is linked to a request the operation
    scheduled_start_time::Float64 # post-compute
end

mutable struct Route
    id::String
    vehicle_set_id::String
    sequence::Vector{Action}
    end_status::Int # 0 returnToStartDepot, 1 returnToOtherDepot, 2 ongoing # post-compute
    # path::OSRMpath     # TODO: add OSRM path here
end

mutable struct RvrpSolution
    id::String
    instance_id::String
    cost::Float64 # post-compute
    routes::Vector{Route}
    unassigned_request_ids::Vector{String} # among semi-mandatory or optional request # post-compute
end


text:
#= Read and write plain-text edgelists

This source code borrows the general parsing scheme from `GraphIO.jl`. =#

const DELIM_REGEX = raw"\s,;|"

function read_edgelist_ids!(io::IO, g::Graph, delim::String, start_id::Integer)
    re = Regex(raw"(\d+)[" * delim * raw"]+(\d+)")
    Δid = 1 - start_id
    for line in eachline(io)
        line = strip(line)
        if length(line) > 0 && line[1] != '#'
            m = match(re, line).captures
            m == nothing && return line
            src = parse(Int, m[1]) + Δid
            tgt = parse(Int, m[2]) + Δid
            while nodecount(g) < max(src, tgt)
                addnode!(g)
            end
            addedge!(g, src, tgt)
        end
    end
end

function read_edgelist_strings!(io::IO, g::Graph, delim::String)
    re = Regex(raw"(\w+)[" * delim * raw"]+(\w+)")
    addnodeattr!(g, :id, String[])
    id_map = Dict{String,Int}()
    create = (x) -> id_map[x] = addnode!(g, id=String(x))
    for line in eachline(io)
        line = strip(line)
        if length(line) > 0 && line[1] != '#'
            m = match(re, line).captures
            m == nothing && return line
            src, tgt = m
            haskey(id_map, src) || create(src)
            haskey(id_map, tgt) || create(tgt)
            addedge!(g, id_map[src], id_map[tgt])
        end
    end
end

"""
    read_edgelist(io::IO[; delim, kvargs...])

Read graph from a plain text file where each line specifies a single edge.
Lines should have the format `source<delims...>target`.
Set the possible delimiters as a string `delim`.

Keyword argument `mode` specifies how to treat the parsed node names:
* `:auto` — try both of the following two options (default),
* `:int` — try to parse numerical ids with the offset `start_id`,
* `:str` — treat node ids as strings (slower and the ordering of resulting
  node ids can be arbitrary).

If `:int` mode is chosen, it is assumed that node ids in the file start
with `start_id`, which is zero by default.
If `:str` mode is chosen, the resulting graph has a `String` attribute `:id`
associated with its nodes.
"""
function read_edgelist(io::IO; delim=DELIM_REGEX, mode=:auto, start_id=0, kwargs...)
    if mode == :int || mode == :auto
        pos = position(io)
        g = Graph(; kwargs...)
        res = read_edgelist_ids!(io, g, delim, start_id)
        if res == nothing
            return g
        elseif mode == :int
            error("can't parse line\"$res\"")
        end
        seek(io, pos)
    end
    if mode == :str || mode == :auto
        g = Graph(; kwargs...)
        res = read_edgelist_strings!(io, g, delim)
        if res == nothing
            return g
        else
            error("can't parse line\"$res\"")
        end
    end
end

"""
    write_edgelist(io::IO, g::Graph[; delim, ids])

Write the list of graph's edges, one per line.
If `ids` is not customized, default node ids are used.
"""
function write_edgelist(io::IO, g::Graph; delim='\t', ids=nodes(g) - 1)
    for e = edges(g)
        println(io, repr(ids[e.source]), delim, repr(ids[e.target]))
    end
end


text:
import InteractiveUtils

g_cached_subtypes = Dict{DataType, Vector{DataType}}()

"""
Returns an array of all concrete subtypes of T.
Note that this does not find parameterized types.
"""
function get_all_concrete_subtypes(::Type{T}) where {T}
    if haskey(g_cached_subtypes, T)
        return g_cached_subtypes[T]
    end

    sub_types = Vector{DataType}()
    _get_all_concrete_subtypes(T, sub_types)
    g_cached_subtypes[T] = sub_types
    return sub_types
end

"""Recursively builds a vector of subtypes."""
function _get_all_concrete_subtypes(::Type{T}, sub_types::Vector{DataType}) where {T}
    for sub_type in InteractiveUtils.subtypes(T)
        if isconcretetype(sub_type)
            push!(sub_types, sub_type)
        elseif isabstracttype(sub_type)
            _get_all_concrete_subtypes(sub_type, sub_types)
        end
    end

    return nothing
end

"""Returns an array of concrete types that are direct subtypes of T."""
function get_concrete_subtypes(::Type{T}) where {T}
    return [x for x in InteractiveUtils.subtypes(T) if isconcretetype(x)]
end

"""Returns an array of abstract types that are direct subtypes of T."""
function get_abstract_subtypes(::Type{T}) where {T}
    return [x for x in InteractiveUtils.subtypes(T) if isabstracttype(x)]
end

"""Returns an array of all super types of T."""
function supertypes(::Type{T}, types = []) where {T}
    super = supertype(T)
    push!(types, super)
    if super == Any
        return types
    end

    supertypes(super, types)
end

"""Converts a DataType to a Symbol, stripping off the module name(s)."""
function type_to_symbol(data_type::DataType)
    return Symbol(strip_module_name(string(data_type)))
end

"""Strips the module name off of a type."""
function strip_module_name(name::String)
    index = findfirst(".", name)
    # Account for the period being part of a parametric type.
    parametric_index = findfirst("{", name)

    if isnothing(index) ||
       (!isnothing(parametric_index) && index.start > parametric_index.start)
        basename = name
    else
        basename = name[(index.start + 1):end]
    end

    return basename
end

function strip_module_name(::Type{T}) where {T}
    return strip_module_name(string(T))
end

function strip_parametric_type(name::AbstractString)
    index = findfirst("{", name)
    if !isnothing(index)
        # Ignore the parametric type.
        name = name[1:(index.start - 1)]
    end

    return name
end

"""
Return a symbol parsed from a serialized string. Sanitizes the input first and attempts to
ensure that the string does not contain code. The caller can call `eval` on the returned
symbol.

Throws ErrorException if the string contains invalid characters or code.

"""
function parse_serialized_type(serialized_type::Union{Symbol, String})
    if serialized_type isa Symbol
        serialized_type = string(serialized_type)
    end

    _check_expression_characters(serialized_type)
    val = Meta.parse(serialized_type)
    if val isa Symbol
        return val
    elseif val isa Expr
        _check_parametric_expression(val)
    else
        error("invalid type: $val")
    end

    return val
end

function _check_expression_characters(serialized_type::String)
    # This will return false if the char is any symbol or operator other than
    # '{', '}', and ',', which should be the only non-alphanumeric characters allowed
    # in a type that we are handling during serialization (as of now).
    # Look up an ASCII table to interpret these.
    for char in serialized_type
        is_valid = false
        value = codepoint(char)
        if value < 32
            is_valid = false
        elseif value >= 33 && value <= 47 && value != 44
            is_valid = false
        elseif value >= 58 && value <= 64
            is_valid = false
        elseif value >= 91 && value <= 94
            is_valid = false
        elseif value == 96 || value == 124 || value == 126
            is_valid = false
        elseif value == 124
            is_valid = false
        else
            is_valid = true
        end

        if !is_valid
            error("$char is not allowed in $serialized_type")
        end
    end
end

function _check_parametric_expression(expr::Expr)
    # Recursively check the expression to make sure it only contains :curly and Symbols.
    if expr.head != :curly
        error("invalid expr: $expr")
    end

    for arg in expr.args
        if arg isa Symbol
            continue
        elseif arg isa Expr
            _check_parametric_expression(arg)
        else
            error("invalid expr: $arg")
        end
    end
end

"""Converts an object deserialized from JSON into a Julia type, such as NamedTuple,
to an instance of T. Similar to Base.convert, but not a viable replacement.
"""
function convert_type(::Type{T}, data::Any) where {T}
    # Improvement: implement the conversion logic. Need to recursively convert fieldnames
    # to fieldtypes, collect the values, and pass them to T(). Also handle literals.
    # The JSON2 library already handles almost all of the cases.
    #if data isa AbstractString && T <: AbstractString
    if T <: AbstractString
        return T(data)
    end
    return JSON2.read(JSON2.write(data), T)
end

"""
Return true if all publicly exported names in mod are defined.
"""
function validate_exported_names(mod::Module)
    is_valid = true
    for name in names(mod)
        if !isdefined(mod, name)
            is_valid = false
            @error "module $mod exports $name but does not define it"
        end
    end

    return is_valid
end

"""
Recursively compares struct values by performing == on each field in the struct.
When performing == on values of immutable structs Julia will perform === on
each field.  This will return false if any field is mutable even if the
contents are the same.  So, comparison of any InfrastructureSystems type with an array
will fail.

This is an unresolved Julia issue. Refer to
https://github.com/JuliaLang/julia/issues/4648.

An option is to overload == for all subtypes of PowerSystemType. That may not be
appropriate in all cases. Until the Julia developers decide on a solution, this
function is provided for convenience for specific comparisons.

"""
function compare_values(x::T, y::T)::Bool where {T}
    match = true
    fields = fieldnames(T)
    if isempty(fields)
        match = x == y
    else
        for fieldname in fields
            if T <: Forecasts && fieldname == :time_series_storage
                # This gets validated at SystemData. Don't repeat for each component.
                continue
            end
            val1 = getfield(x, fieldname)
            val2 = getfield(y, fieldname)
            if !isempty(fieldnames(typeof(val1)))
                if !compare_values(val1, val2)
                    @debug "values do not match" T fieldname val1 val2
                    match = false
                    break
                end
            elseif val1 isa AbstractArray
                if !compare_values(val1, val2)
                    match = false
                end
            else
                if val1 != val2
                    @debug "values do not match" T fieldname val1 val2
                    match = false
                    break
                end
            end
        end
    end

    return match
end

function compare_values(x::Vector{T}, y::Vector{T})::Bool where {T}
    if length(x) != length(y)
        @debug "lengths do not match" T length(x) length(y)
        return false
    end

    for i in range(1, length = length(x))
        if !compare_values(x[i], y[i])
            @debug "values do not match" typeof(x[i]) i x[i] y[i]
            return false
        end
    end

    return true
end

function compare_values(x::Dict, y::Dict)::Bool
    keys_x = Set(keys(x))
    keys_y = Set(keys(y))
    if keys_x != keys_y
        @debug "keys don't match" keys_x keys_y
        return false
    end

    for key in keys_x
        if !compare_values(x[key], y[key])
            @debug "values do not match" typeof(x[key]) key x[key] y[key]
            return false
        end
    end

    return true
end

function compare_values(x::T, y::U)::Bool where {T, U}
    # This is a catch-all for where where the types may not be identical but are close
    # enough.
    return x == y
end

"""
Macro to wrap Enum in a baremodule to keep the top level scope clean.
The macro name should be singular. The macro will create a module for access that is plural.

# Examples
```julia
@scoped_enum Fruit begin
    APPLE
    ORANGE
end

value = Fruits.APPLE

# Usage as a function parameter
foo(value::Fruits.Fruit) = nothing
```

"""
macro scoped_enum(T, args...)
    blk = esc(:(baremodule $(Symbol("$(T)s"))
    using Base: @enum
    @enum $T $(args...)
    end))
    return blk
end

function compose_function_delegation_string(
    sender_type::String,
    sender_symbol::String,
    argid::Vector{Int},
    method::Method,
)
    s = "p" .* string.(1:(method.nargs - 1))
    s .*= "::" .* string.(fieldtype.(Ref(method.sig), 2:(method.nargs)))
    s[argid] .= "p" .* string.(argid) .* "::$sender_type"

    m = string(method.module.eval(:(parentmodule($(method.name))))) * "."
    l = "$m:(" * string(method.name) * ")(" * join(s, ", ")

    m = string(method.module) * "."
    l *= ") = $m:(" * string(method.name) * ")("
    s = "p" .* string.(1:(method.nargs - 1))

    s[argid] .= "getfield(" .* s[argid] .* ", :$sender_symbol)"
    l *= join(s, ", ") * ")"
    l = join(split(l, "#"))
    return l
end

function forward(sender::Tuple{Type, Symbol}, receiver::Type, method::Method)
    # Assert that function is always just one argument
    @assert method.nargs < 4 "`forward` only works for one and two argument functions"
    # Assert that function name always starts with `get_*`
    "`forward` only works for accessor methods that are defined as `get_*` or `set_*`"
    @assert startswith(string(method.name), r"set_|get_")
    sender_type = "$(parentmodule(sender[1])).$(nameof(sender[1]))"
    sender_symbol = string(sender[2])
    code_array = Vector{String}()
    # Search for receiver type in method arguments
    argtype = fieldtype(method.sig, 2)
    (sender[1] == argtype) && (return code_array)
    if string(method.name)[1] == '@'
        @warn "Forwarding macros is not yet supported."
        display(method)
        println()
        return code_array
    end

    # first argument only
    push!(
        code_array,
        compose_function_delegation_string(sender_type, sender_symbol, [1], method),
    )

    tmp = split(string(method.module), ".")[1]
    code =
        "@eval " .* tmp .* " " .* code_array .* " # " .* string(method.file) .* ":" .*
        string(method.line)
    if (tmp != "Base") && (tmp != "Main")
        pushfirst!(code, "using $tmp")
    end
    code = unique(code)
    return code
end

function forward(sender::Tuple{Type, Symbol}, receiver::Type)
    code = Vector{String}()
    active_methods = getfield.(InteractiveUtils.methodswith(sender[1]), :name)
    for m in InteractiveUtils.methodswith(receiver)
        m.name ∈ active_methods && continue
        if startswith(string(m.name), "get_") && m.nargs == 2
            # forwarding works for functions with 1 argument and starts with `get_`
            append!(code, forward(sender, receiver, m))
        elseif startswith(string(m.name), "set_") && m.nargs == 3
            # forwarding works for functions with 2 argument and starts with `set_`
            append!(code, forward(sender, receiver, m))
        end
    end
    return code
end

macro forward(sender, receiver)
    out = quote
        list = InfrastructureSystems.forward($sender, $receiver)
        for line in list
            eval(Meta.parse("$line"))
        end
    end
    return esc(out)
end


text:
using JSON2, Parsers, Test, Dates
include("json.jl")
include("custom.jl")
include("options.jl")

# builtins
# Any
@test JSON2.read("") == NamedTuple()
@test JSON2.read("{\"hey\":1}") == (hey=1,)
@test JSON2.read("[\"hey\",1]") == ["hey",1]
@test JSON2.read("1.0") === 1
@test JSON2.read("1") === 1
@test JSON2.read("1.1") === 1.1
@test JSON2.read("+1.1") === 1.1
@test JSON2.read("-1.1") === -1.1
@test JSON2.read("\"hey\"") == "hey"
@test JSON2.read("null") === nothing
@test JSON2.read("true") === true
@test JSON2.read("false") === false

# Union
@test JSON2.read("1.0", Union{Float64, Int}) === 1.0
@test JSON2.read("1.1", Union{Float64, Int}) === 1.1
@test JSON2.read("1.1", Union{Float64, String}) === 1.1
@test JSON2.read("\"1.1\"", Union{Float64, String}) === "1.1"
@test JSON2.read("1.1", Union{Nothing, Float64}) === 1.1
@test JSON2.read("null", Union{Nothing, Float64}) === nothing

# Enum
@enum FRUIT apple orange banana
@test JSON2.read(JSON2.write(apple), FRUIT) === apple

# NamedTuple
@test JSON2.read("{\"hey\":1}", NamedTuple) == (hey=1,)
@test JSON2.read("{\"hey\":1,\"ho\":2}", NamedTuple) == (hey=1,ho=2)

@test JSON2.write(Dict("name"=>1)) == "{\"name\":1}"
@test JSON2.read(JSON2.write(Dict("name"=>1)), Dict) == Dict("name"=>1)
@test JSON2.write(Dict()) == "{}"
@test JSON2.read(JSON2.write(Dict()), Dict) == Dict()

@test JSON2.write([]) == "[]"
@test JSON2.read(JSON2.write([]), Array) == []
@test JSON2.write([1, 2, 3]) == "[1,2,3]"
@test JSON2.read(JSON2.write([1, 2, 3]), Array) == [1, 2, 3]
@test JSON2.write(["hey", "there", "sailor"]) == "[\"hey\",\"there\",\"sailor\"]"
@test JSON2.read(JSON2.write(["hey", "there", "sailor"]), Array) == ["hey", "there", "sailor"]
@test JSON2.write([1, 2, 3, "hey", "there", "sailor"]) == "[1,2,3,\"hey\",\"there\",\"sailor\"]"
@test JSON2.read(JSON2.write([1, 2, 3, "hey", "there", "sailor"]), Array) == [1, 2, 3, "hey", "there", "sailor"]
@test JSON2.write([split("hey there sailor", ' ')...]) == "[\"hey\",\"there\",\"sailor\"]"
@test JSON2.read(JSON2.write([split("hey there sailor", ' ')...]), Array) == [split("hey there sailor", ' ')...]

@test JSON2.write(()) == "[]"
@test JSON2.read(JSON2.write(()), Tuple) == ()
@test JSON2.write((1, 2, 3)) == "[1,2,3]"
@test JSON2.read(JSON2.write((1, 2, 3)), Tuple) == (1, 2, 3)

@test JSON2.read(JSON2.write((1, 2, 3)), Set) == Set([1, 2, 3])

@test JSON2.write(1) == "1"
@test JSON2.read(JSON2.write(1), Int) == 1
for i in rand(Int, 1000000) # takes about 0.8 seconds
    @test JSON2.read(JSON2.write(i), Int) == i
end
@test JSON2.write(1.0) == "1.0"
@test JSON2.read(JSON2.write(1.0), Float64) == 1.0

include("floatparsing.jl")

@test JSON2.write("") == "\"\""
@test JSON2.read(JSON2.write(""), String) == ""
@test JSON2.write("hey") == "\"hey\""
@test JSON2.read(JSON2.write("hey"), String) == "hey"
let tmp = tempname()
    open(tmp, "w") do f
        write(f, "\"hey\"")
    end
    io = open(tmp)
    @test JSON2.read(io, String) == "hey"
    close(io)
    rm(tmp)
end
@test JSON2.read(JSON2.write('h'), Char) == 'h'
@test JSON2.write(Symbol()) == "\"\""
@test JSON2.read(JSON2.write(Symbol()), Symbol) == Symbol()
@test JSON2.write(:hey) == "\"hey\""
@test JSON2.read(JSON2.write(:hey), Symbol) == :hey

@test JSON2.write(Date(2017, 1, 1)) == "\"2017-01-01\""
@test JSON2.read(JSON2.write(Date(2017, 1, 1)), Date) == Date(2017, 1, 1)
df = dateformat"mm/dd/yyyy"
@test JSON2.write(Date(2017, 1, 1); dateformat=df) == "\"01/01/2017\""
@test JSON2.read(JSON2.write(Date(2017, 1, 1); dateformat=df), Date; dateformat=df) == Date(2017, 1, 1)

@test JSON2.write(nothing) == "null"
@test JSON2.read(JSON2.write(nothing), Nothing) === nothing

@test JSON2.write(missing) == "null"
@test JSON2.read(JSON2.write(missing), Missing) === missing

@test JSON2.write(true) == "true"
@test JSON2.read(JSON2.write(true), Bool) == true
@test JSON2.write(false) == "false"
@test JSON2.read(JSON2.write(false), Bool) == false

@test JSON2.read("function (data) {}") == JSON2.Function("function (data) {}")
@test JSON2.read("function (data) {}", JSON2.Function) == JSON2.Function("function (data) {}")
@test JSON2.read(JSON2.write(JSON2.Function("function (data) {}"))) == JSON2.Function("function (data) {}")

mutable struct A
    int8::Int8
    int::Int
    float::Float64
    str::String
    nullint::Union{Nothing, Int}
    nullnullint::Union{Nothing, Int}
    nullstr::Union{Nothing, String}
    nullnullstr::Union{Nothing, String}
    void::Nothing
    truebool::Bool
    falsebool::Bool
    b::B

    ints::Vector{Int}
    emptyarray::Vector{Int}
    bs::Vector{B}
    dict::Dict{String,Int}
    emptydict::Dict{String,Int}
end

a = A(0, -1, 3.14, "string \\\" w/ escaped double quote", 4, nothing,
        "null string", nothing, nothing, true, false, b1, [1,2,3], Int[], [b2, b3],
        Dict("1"=>1, "2"=>2), Dict{String,Int}())

json = JSON2.write(a)
a2 = JSON2.read(json, A)

str = "{\n          \"int8\": 0,\n           \"int\": -1,\n         \"float\": 3.14,\n           \"str\": \"string \\\\\\\" w/ escaped double quote\",\n       \"nullint\": 4,\n   \"nullnullint\": null,\n       \"nullstr\": \"null string\",\n   \"nullnullstr\": null,\n          \"void\": null,\n      \"truebool\": true,\n     \"falsebool\": false,\n             \"b\": {\n                       \"id\": 1,\n                     \"name\": \"harry\"\n                  },\n          \"ints\": [\n                    1,\n                    2,\n                    3\n                  ],\n    \"emptyarray\": [],\n            \"bs\": [\n                    {\n                         \"id\": 2,\n                       \"name\": \"hermione\"\n                    },\n                    {\n                         \"id\": 3,\n                       \"name\": \"ron\"\n                    }\n                  ],\n          \"dict\": {\n                     \"1\": 1,\n                     \"2\": 2\n                  },\n     \"emptydict\": {}\n}"
io = IOBuffer()
JSON2.pretty(io, json)
@test String(take!(io)) == str

# 230
@test a.int8 == a2.int8
@test a.int == a2.int
@test a.float == a2.float
@test a.str == a2.str
@test a.nullint == a2.nullint
@test a.nullnullint === nothing && a2.nullnullint === nothing
@test a.nullstr == a2.nullstr
@test a.nullnullstr === nothing && a2.nullnullstr === nothing
@test a.void == a2.void
@test a.truebool == a2.truebool
@test a.falsebool == a2.falsebool
@test a.b == a2.b
@test a.ints == a2.ints
@test a.emptyarray == a2.emptyarray
@test a.bs == a2.bs
@test a.dict == a2.dict
@test a.emptydict == a2.emptydict

# test invalid handling
@test_throws ArgumentError JSON2.read("trua")
@test_throws ArgumentError JSON2.read("tru")
@test_throws ArgumentError JSON2.read("fals")
@test_throws ArgumentError JSON2.read("falst")
@test_throws ArgumentError JSON2.read("f")
@test_throws ArgumentError JSON2.read("a", Bool)

@test_throws ArgumentError JSON2.read("nul", Nothing)
@test_throws ArgumentError JSON2.read("nule", Nothing)
@test_throws ArgumentError JSON2.read("abcd", Nothing)

@test_throws ArgumentError JSON2.read("nule", Union{Nothing, Int})
@test_throws Parsers.Error JSON2.read("abc", Union{Nothing, Int})

@test_throws Parsers.Error JSON2.read("abc", Int)

@test_throws ArgumentError JSON2.read("a", Char)
@test_throws ArgumentError JSON2.read("\"abc\"", Char)

@test JSON2.read(IOBuffer("\"\\u003e\\u003d\$1B\""), String) == ">=\$1B"

# Default DateTime format
@test JSON2.read("\"2019-03-25T23:12:51.191\"", DateTime) == DateTime(2019, 3, 25, 23, 12, 51, 191)

# Unions which both read strings
@test JSON2.read("\"foo\"", Union{DateTime, String}) == "foo"

@test_nowarn JSON2.mergedefaultkwargs(NamedTuple)


text:
# This file is a part of Julia. License is MIT: http://julialang.org/license

# raytracer.jl
# This is a translation from Java/C++ of the raytracer located at
#   http://www.ffconsultancy.com/languages/ray_tracer/
# It mostly keeps the structure of the code of these other languages, but is
# still fairly Julian.
# This code was discussed at
#   https://groups.google.com/forum/#!topic/julia-users/UkeV1H9fct4
# It is most likely GC-bound.

const delta = sqrt(eps(Float64))

struct Vec
    x::Float64
    y::Float64
    z::Float64
end
import Base: +, -, *
+(a::Vec, b::Vec) = Vec(a.x+b.x, a.y+b.y, a.z+b.z)
-(a::Vec, b::Vec) = Vec(a.x-b.x, a.y-b.y, a.z-b.z)
*(a::Float64, b::Vec) = Vec(a*b.x, a*b.y, a*b.z)
*(a::Int, b::Vec) = Vec(a*b.x, a*b.y, a*b.z)
*(a::Vec, b::Float64) = *(b,a)
dot(a::Vec, b::Vec) = (a.x*b.x + a.y*b.y + a.z*b.z)
unitize(a::Vec) = (1. / sqrt(dot(a, a)) * a)

mutable struct Ray
    orig::Vec
    dir::Vec
end

mutable struct Hit
    lambda::Float64
    normal::Vec
end

abstract type Scene end

struct Sphere <: Scene
    center::Vec
    radius::Float64
end

function ray_sphere(s::Sphere, ray::Ray)
    v = s.center - ray.orig
    b = dot(v, ray.dir)
    disc = b*b - dot(v, v) + s.radius*s.radius
    if disc >= 0
        d = sqrt(disc)
        t2 = b + d
        if t2 >= 0
            t1 = b - d
            return t1 > 0 ? t1 : t2
        end
    end
    return Inf
end

function intersect(s::Sphere, i::Hit, ray::Ray)
    l = ray_sphere(s, ray)
    if l >= i.lambda
        return i
    else
        n = ray.orig + l * ray.dir - s.center
        return Hit(l, unitize(n))
    end
end

struct Group <: Scene
    bound::Sphere
    objs::Array{Scene}
end

Group(b::Sphere) = Group(b, Scene[])

function intersect(g::Group, i::Hit, ray::Ray)
    l = ray_sphere(g.bound, ray)
    if l >= i.lambda
        return i
    else
        for j in g.objs
            i = intersect(j, i, ray)
        end
        return i
    end
end

function ray_trace(light::Vec, ray::Ray, scene::Scene)
    i = intersect(scene, Hit(Inf, Vec(0.,0.,0.)), ray)
    if i.lambda == Inf
        return 0
    end
    o = ray.orig + i.lambda*ray.dir + delta*i.normal
    g = dot(i.normal, light)
    if g >= 0
        return 0
    end
    sray = Ray(o, -1*light)
    si = intersect(scene, Hit(Inf, Vec(0.,0.,0.)), sray)
    return si.lambda == Inf ? -g : 0
end

function create(level, c::Vec, r)
    sphere = Sphere(c, r)
    if level == 1
        return sphere
    end
    group = Group(Sphere(c, 3*r))
    push!(group.objs, sphere)
    rn = 3*r/sqrt(12)
    for dz = -1:2:1
        for dx = -1:2:1
            c2 = c + Vec(dx*rn, rn, dz*rn)
            push!(group.objs, create(level-1, c2, r/2))
        end
    end
    return group
end

function Raytracer(levels, n, ss)
    scene = create(levels, Vec(0., -1., 0.), 1.)
    light = unitize(Vec(-1., -3., 2.))
    # f = open("output.pgm", "w")
    # write(f,string("P5\n",n," ",n,"\n",255,"\n"))
    for y in (n-1):-1:0
        for x in 0:1:(n-1)
            g = 0.
            for dx in 0:1:(ss-1)
                for dy in 0:1:(ss-1)
                    d = Vec(x+dx*1./ss-n/2., y+dy*1./ss-n/2., n*1.0)
                    ray = Ray(Vec(0., 0., -4.0), unitize(d))
                    g += ray_trace(light, ray, scene)
                end
            end
            # write(f, trunc(UInt8, 0.5 + 255. * g / (ss*ss)))
        end
    end
    # close(f)
end


text:
macro publish_gridapodes(mod,name)
  quote
    using Gridap.ODEs.$mod: $name; export $name
  end
end

# Mostly used from ODETools
@publish_gridapodes ODETools BackwardEuler
@publish_gridapodes ODETools ForwardEuler
@publish_gridapodes ODETools MidPoint
@publish_gridapodes ODETools ThetaMethod
@publish_gridapodes ODETools RungeKutta
@publish_gridapodes ODETools Newmark
@publish_gridapodes ODETools ∂t
@publish_gridapodes ODETools ∂tt

# Mostly used from TransientFETools
@publish_gridapodes TransientFETools TransientTrialFESpace
@publish_gridapodes TransientFETools TransientMultiFieldTrialFESpace
@publish_gridapodes TransientFETools TransientMultiFieldFESpace
@publish_gridapodes TransientFETools TransientFEOperator
@publish_gridapodes TransientFETools TransientAffineFEOperator
@publish_gridapodes TransientFETools TransientConstantFEOperator
@publish_gridapodes TransientFETools TransientConstantMatrixFEOperator


text:
# include("../datasets/Vic120MM.jl")

function addLandmarksFactoGraph!(fg::FactorGraph, f, idx, prevn, nextn;
                    lcmode=:mmodal, lsrNoise=diagm([0.1;1.0]), N::Int=100, MM=Union{})
    I = intersect(keys(f[idx-1]),keys(f[idx]))
    for i in I
      pfez = f[idx-1][i]
      fez = f[idx][i]
      if abs(fez[2]) < (pi/2.0+5.0/180.0*pi)   # only add those recently seen by the laser, and not purely propagated way behind car
        lsy = string("l",i)
        if !haskey(MM,i)
          if !haskey(fg.IDs, lsy)    # has landmark
            # add from previous and latest factor here
            projNewLandm!(fg, prevn, lsy, [pfez[2];pfez[1]], lsrNoise , N=N )
            addBRFG!(fg, nextn, lsy, [fez[2];fez[1]], lsrNoise)
          else
            # previous already added, only add the new factor here
            addBRFG!(fg, nextn, lsy, [fez[2];fez[1]], lsrNoise)
          end
        else
          lsymm = string("l",MM[i])
          if lcmode == :mmodal
            println("Adding bimodal factor")
            if !haskey(fg.IDs, lsy)
              vlm = projNewLandm!(fg, prevn, lsy, [pfez[2];pfez[1]], lsrNoise, addfactor=false)
              addMMBRFG!(fg, prevn, [lsymm;lsy], [pfez[2];pfez[1]], lsrNoise, w=[0.5;0.5] )
            end
            addMMBRFG!(fg, nextn, [lsymm;lsy], [fez[2];fez[1]], lsrNoise, w=[0.5;0.5] )
          elseif lcmode == :unimodal
            println("adding unimodal loop closure")
            addBRFG!(fg, nextn, lsymm, [fez[2];fez[1]], lsrNoise)
          end
        end
      end
    end

    # error("addLandmarksFactoGraph! -- not implemented yet")
    nothing
end

#@time d,f,DBG = advOdoByRules(DRS[1:2000,:],LsrFeats,distrule=15.0,yawrule=pi/6.0);
#progressExamplePlot(dOdo, LsrFeats, toT=100)
#plotParVicPrk(DRS)

function appendFactorGraph!(fg::FactorGraph, d, f;
                  toT=Inf, fgpdf=false, lcmode=:mmodal,
                  lsrNoise=diagm([0.1;1.0]), P0=diagm([0.01;0.01;0.001]), Podo=diagm([0.5;0.5;0.005]),
                  idx::Int=1, N::Int=100, MM=Union{})

  len = length(d)
  T = d[idx][4]
  if idx==1
    # init pose
    prevn = initFactorGraph!(fg, init=d[idx][1:3])
  else
    v,X,nextn = getLastPose2D(fg)
    @show prevn = String(v.label)
  end

  while T < toT && idx <= len
    idx += 1
    T = idx <= len ? d[idx][4] : break
    if T > toT
      break
    end

    # add new poses via odom
    prev, X, nextn = getLastPose2D(fg)
    vp, fp = addOdoFG!(fg, nextn, d[idx][1:3], Podo, N=N)

    # add landmarks
    addLandmarksFactoGraph!(fg, f, idx, prevn, nextn, lcmode=lcmode, lsrNoise=lsrNoise, N=N, MM=MM)
    prevn = nextn
  end
  if fgpdf   writeGraphPdf(fg); end
  return idx
end

function doBatchRun(d, f; toT=30)
  fg = initfg()
  appendFactorGraph!(fg, d, f; toT=toT);
  p = drawPosesLandms(fg)
  tree = prepBatchTree!(fg);
  writeGraphPdf(fg); # make pdf of factor graph so we can see
  inferOverTree!(fg, tree)
  return fg, tree, p
end

function saveImgSeq(d::Dict{Int,Dict{Int,Feature}}, lsrFeats::Dict{Int,LaserFeatures}; from::Int=1,to::Int=10,step::Int=1)
  for i in from:step:to
    p = drawFeatTrackers(d[i], lsrFeats[i].feats);
    Gadfly.draw(PNG(string("imgs/img",i,".png"),35cm,25cm),p)
  end
  nothing
end

function drawIROSVicPrkFig(fgl::FactorGraph, d, f, T, isamdict, fgu)
  p1 = progressExamplePlot(d,f,toT=T);
  p2 = drawCompPosesLandm(fg,isamdict, fgu, lbls=false,drawunilm=false);

  vstack(p1,p2)
end


text:
using Documenter, PiCraft
using Literate

load_dir(x) = map(file -> joinpath("lib", x, file), readdir(joinpath(Base.source_dir(), "src", "lib", x)))

Literate.markdown("../example/safeFeet.jl", "src/example"; documenter=true)
Literate.markdown("../example/turnToGold.jl", "src/example"; documenter=true)
Literate.markdown("../example/turtle.jl", "src/example"; documenter=true)
Literate.markdown("../example/skyscraperBasic.jl", "src/example"; documenter=true)
Literate.markdown("../example/GameOfLife.jl", "src/example"; documenter=true)
Literate.markdown("../example/platform9_75.jl", "src/example"; documenter=true)
Literate.markdown("../example/GameOfLife.jl", "src/example"; documenter=true)

makedocs(
   modules = [PiCraft],
   clean = false,
   sitename = "PiCraft",
   pages = Any[
       "Home" => "index.md",
       "Quick Start" => Any[
            "Installation" => "installation.md",
            "Connecting" => "connecting.md",
            "Coordinate System" => "coordinateSystem.md",
            "Blocks and Models" => "blocksAndModels.md",
            "Events, Entities and Camera" => "eventsEntitiesCamera.md"
       ],
       "Examples" => Any[
            "Safe Feet" => "example/safeFeet.md",
            "Turn to Gold" => "example/turnToGold.md",
            "Turtle" => "example/turtle.md",
            "Sky Scraper" => "example/skyscraperBasic.md",
            "Game Of Life" => "example/GameOfLife.md",
            "Platform 9¾" => "example/platform9_75.md"
            "Whac-a-Block" => "whacABlock.md"
       ],
       "Block Reference" => "blocks.md",
       "API Reference" => "api.md"
   ],
   assets = ["assets/custom.css"]
)

deploydocs(
    repo = "github.com/aviks/PiCraft.jl.git",
    target = "build",
    deps = nothing,
    make = nothing,
)


text:
include("../CODE/ds.jl")
include("../CODE/distributions/niw.jl")

using LinearAlgebra

#Global Setting
use_gpu = false
use_darrays = false #Only relevant if use_gpu = false

random_seed = nothing

#Data Loading specifics
data_path = "../DATA/Bees/"
data_prefix = "XXX"
groups_count = 4
global_preprocessing = nothing
local_preprocessing = nothing

#Model Parameters
iterations = 100
hard_clustering = false

total_dim = 10
local_dim = 7

α = 10.0
γ = 1000000000000.0
global_weight = 1.0
local_weight= 1.0

initial_global_clusters = 1
initial_local_clusters = 1

use_dict_for_global = false

ignore_local = true

split_stop = 5
argmax_sample_stop = 5

glob_dim = 6
global_hyper_params = niw_hyperparams(1.0,
    zeros(glob_dim),
    glob_dim+3,
    Matrix{Float64}(I, glob_dim, glob_dim)*0.1)

local_mult = 0.1

count_list = [1,1,1,1]

local_hyper_params = [niw_hyperparams(1.0, zeros(i),i+3,Matrix{Float64}(I, i, i)*local_mult) for i in count_list]
#local_hyper_params = [niw_hyperparams(1.0, zeros(5),8+3,Matrix{Float64}(I, 5, 5)*local_mult) for i in count_list]

# local_hyper_params = [niw_hyperparams(1.0,
#     zeros(3),
#     6,
#     Matrix{Float64}(I, 3, 3)*local_mult),
#     niw_hyperparams(1.0,
#         zeros(6),
#         9.0,
#         Matrix{Float64}(I, 6, 6)*local_mult),
#     niw_hyperparams(1.0,
#         zeros(9),
#         12.0,
#         Matrix{Float64}(I, 9, 9)*local_mult),
#     niw_hyperparams(1.0,
#         zeros(12),
#         15.0,
#         Matrix{Float64}(I, 12, 12)*local_mult),
#     niw_hyperparams(1.0,
#         zeros(15),
#         18.0,
#         Matrix{Float64}(I, 15, 15)*local_mult),
#     niw_hyperparams(1.0,
#         zeros(18),
#         21.0,
#         Matrix{Float64}(I, 18, 18)*local_mult),
#     niw_hyperparams(1.0,
#         zeros(21),
#         24.0,
#         Matrix{Float64}(I, 21, 21)*local_mult),
#     niw_hyperparams(1.0,
#         zeros(24),
#         27.0,
#         Matrix{Float64}(I, 24, 24)*local_mult),
#     niw_hyperparams(1.0,
#         zeros(27),
#         30.0,
#         Matrix{Float64}(I, 27, 27)*local_mult)]

# local_hyper_params = [niw_hyperparams(1.0,
#     zeros(3),
#     100.0,
#     Matrix{Float64}(I, 3, 3)*10.0),
#     niw_hyperparams(1.0,
#         zeros(6),
#         100.0,
#         Matrix{Float64}(I, 6, 6)*10.0),
#     niw_hyperparams(1.0,
#         zeros(9),
#         100.0,
#         Matrix{Float64}(I, 9, 9)*10.0),
#     niw_hyperparams(1.0,
#         zeros(12),
#         100.0,
#         Matrix{Float64}(I, 12, 12)*10.0),
#     niw_hyperparams(1.0,
#         zeros(15),
#         100.0,
#         Matrix{Float64}(I, 15, 15)*10.0),
#     niw_hyperparams(1.0,
#         zeros(18),
#         100.0,
#         Matrix{Float64}(I, 18, 18)*10.0),
#     niw_hyperparams(1.0,
#         zeros(21),
#         100.0,
#         Matrix{Float64}(I, 21, 21)*10.0),
#     niw_hyperparams(1.0,
#         zeros(24),
#         100.0,
#         Matrix{Float64}(I, 24, 24)*10.0),
#     niw_hyperparams(1.0,
#         zeros(27),
#         100.0,
#         Matrix{Float64}(I, 27, 27)*10.0)]


text:
#=
Run test locally using
$ julia test/runtest.jl /dev/ttyXYZ

/dev/ttyXYZ can be:
/dev/ttyS0  (for Travis)
/dev/ttyS4
/dev/ttyUSB0
=#

using LibSerialPort
using Test

if haskey(ENV, "CI")
    @testset "LibSerialPort CI port listing" begin
        list_ports()
    end
else
    if length(ARGS) == 0
        port = "/dev/ttyS0"  # /dev/ttyS4 /dev/ttyUSB0
    else
        port = ARGS[1]
    end

    baudrate = length(ARGS) >= 2 ? ARGS[2] : "115200"

    @testset "LibSerialPort" begin
        @testset "Low level API" begin
            include("test-low-level-api.jl")
            @test test_low_level_api() == nothing
            @test test_low_level_api(port, baudrate) == nothing
        end

        @testset "High level API" begin
            include("test-high-level-api.jl")
            @test test_high_level_api() == nothing
            @test test_high_level_api(port, baudrate) == nothing
        end

        # console.jl runs forever, thus isn't amenable to unit testing
        # @testset "Examples" begin
        #     include("../examples/console.jl")
        #     @test console() == nothing
        #     @test console(port, baudrate) == nothing
        # end
    end
end


text:
function render_image_op(x1, x2, image, transform_op, widgets)
    slider_val  = GtkReactive.value(widgets[:slider])
    θ           = slider_val*x1 + (1 - slider_val)*x2
    idx         = GtkReactive.value(widgets[:player])
    img_trans   = transform_op(image[:,:,idx], θ)
end

function render_video_op(x1, x2, image, transform_op, widgets)
    slider_val  = GtkReactive.value(widgets[:slider])
    θ           = slider_val*x1 + (1 - slider_val)*x2
    video_trans = [transform_op(image[:,:,idx], θ) for idx = 1:size(image,3)]
end

function render_loop!(x1, x2, image, widgets, signals, transform_op)
    block        = Gtk.Condition()
    render_image = GtkReactive.Signal(image[:,:,1])
    sig_draw = GtkReactive.draw(widgets[:canvas], render_image) do canvas, ren
        copy!(canvas, ren)
        Gtk.notify(block)
        nothing
    end

    signals[:file_export_best_der] = map(signals[:file_export_best]) do sig
        if(sig)
            idx       = GtkReactive.value(widgets[:player])
            img_trans = transform_op(image[:,:,idx], x1)
            menu_export_dialog(img_trans)
            nothing
        end
    end

    signals[:file_export_der] = map(signals[:file_export_image]) do sig
        if(sig)
            data = render_image_op(x1, x2, image, transform_op, widgets)
            menu_export_dialog(data)
            nothing
        end
    end

    signals[:button_done].value = false
    while(!GtkReactive.value(signals[:button_done]))
        sleep(0.005)
        img_trans = render_image_op(x1, x2, image, transform_op, widgets)
        push!(render_image, img_trans)
        Gtk.wait(block)
    end
end

function opt_loop!(prng, image, dims, widgets, signals, transform_op, settings)
    state              = Dict{Symbol, Any}()
    state[:best_param] = Array{Float64}[]
    state[:data_x]     = zeros(Float64, dims, 0)
    state[:data_c]     = zeros(Int64, 0, 3)

    signals[:action_restart].value = false

    x1 = rand(prng, dims)
    x2 = rand(prng, dims)

    # signals[:file_export_der] = map(signals[:file_export_best]) do sig
    #     if(sig)
    #         fname = Gtk.open_dialog(
    #             "Load an image or video",
    #             Gtk.GtkNullContainer(),
    #             ("*.png",
    #              "*.jpg",
    #              Gtk.GtkFileFilter("*.png, *.jpg",
    #                                name="All supported formats")))
    #         if(fname[end-3:end] == "png")
    #             idx = GtkReactive.value(widgets[:player])
    #             FileIO.save(image[:,:,idx], fname)
    #         end
    #     end
    # end

    signals[:action_start_der] = map(signals[:action_start]) do sig
        @info("pressed button start", sig)
        if(sig)
            @info("pressed button")
        end
    end

    signals[:file_export_gp_der] = map(signals[:file_export_gp]) do sig
        @info("pressed button export gp", sig)
        if(sig)
            JLD.save("gp_state.jld", "gp", state)
        end
    end

    for i = 1:settings[:n_initial]
        x1[:] = rand(prng, dims)
        x2[:] = rand(prng, dims)

        render_loop!(x1, x2, image, widgets, signals, transform_op)
        r = GtkReactive.value(widgets[:slider])
        append_choice!(r, x1, x2, state)
        push!(widgets[:slider], 0.5)
    end

    @info("training gp")
    train_gp!(prng,
              state,
              settings[:n_mcmc_samples],
              settings[:n_mcmc_burnin],
              settings[:n_mcmc_thin],
              settings[:preference_scale],
              settings[:marginalize])

    while(!GtkReactive.value(signals[:action_restart]))
        @info("finding query")
        x1, x1_idx, x2 = prefbo_next_query(prng,
                                           state,
                                           settings[:search_budget];
                                           verbose=settings[:verbose])
        push!(state[:best_param], x1)
        @info("waiting")
        push!(widgets[:slider], 0.5)

        render_loop!(x1, x2, image, widgets, signals, transform_op)
        r = GtkReactive.value(widgets[:slider])
        append_choice!(r, x1, x1_idx, x2, state)

        @info("train GP")
        train_gp!(prng,
                  state,
                  settings[:n_mcmc_samples],
                  settings[:n_mcmc_burnin],
                  settings[:n_mcmc_thin],
                  settings[:preference_scale],
                  settings[:marginalize])

        @info("done")
    end
end

function create_ui(prng, dims, transform_op)
    widgets, signals = create_window("Ultrasound Visual Gallery", (512, 360))
    dct  = Dict(:gui=>widgets, :signals=>signals)
    win  = widgets[:window]
    GtkReactive.gc_preserve(win, dct)
    Gtk.showall(win)

    #image = zeros(300, 200)
    #image = rand(200,300,100)

    f   = ImageCore.scaleminmax(0.0, 1.0)
    image = FileIO.load(DrWatson.datadir("image", "forearm.png"))
    image = Float32.(Colors.Gray.(image))
    image = image[1:976, 1:1024]
    image = f.(image)
    image = convert(Array{Float32}, image)
    image = reshape(image, (size(image,1), size(image,2), 1))

    sig_menu = map(signals[:file_open]; init=false) do fname
        image = FileIO.load(fname)

        video_frames = size(image, 3)
        Gtk.empty!(widgets[:grid])

        widgets[:player]      = GtkReactive.player(signals[:player],
                                                    1:video_frames)
        widgets[:grid][1:4,1] = widgets[:player]
        widgets[:grid][1:3,2] = widgets[:slider]
        widgets[:grid][4,  2] = widgets[:button]
        nothing
    end

    settings = Dict{Symbol, Any}()
    settings[:n_initial]        = 4
    settings[:marginalize]      = true
    settings[:search_budget]    = 30.0
    settings[:n_mcmc_samples]   = 2000
    settings[:n_mcmc_burnin]    = 1000
    settings[:n_mcmc_thin]      = 20
    settings[:preference_scale] = 1.0
    settings[:verbose]          = true

    # foreach(signals[:file_open]) do fname
    # end

    while(true)
        opt_loop!(prng, image, dims, widgets, signals, transform_op, settings)
    end
end


text:
abstract type Angle <: Number end

struct Radian <: Angle
    radians::Float64
end

struct DMS <: Angle
    seconds::Int
end

begin
    Degree(degrees::Integer) = Minute(degrees * 60)
    Degree(deg::Integer, min::Integer) = Degree(deg) + Minute(min)
    Degree(deg::Integer, min::Integer, secs::Integer) = Degree(deg, min) + Second(secs)

    function Minute(minutes::Integer)
        DMS(minutes * 60)
    end

    function Second(seconds::Integer)
        DMS(seconds)
    end

    import Base: -, +, show, convert, *, /, promote_rule
    +(Θ::DMS, α::DMS) = DMS(Θ.seconds + α.seconds)
    -(Θ::DMS, α::DMS) = DMS(Θ.seconds - α.seconds)

    +(Θ::Radian, α::Radian) = Radian(Θ.radians + α.radians)
    -(Θ::Radian, α::Radian) = Radian(Θ.radians - α.radians)

    function degrees(dms::DMS)
        minutes = dms.seconds ÷ 60
        minutes ÷ 60
    end

    function minutes(dms::DMS)
        minutes = dms.seconds ÷ 60
        minutes % 60
    end

    seconds(dms::DMS) = dms.seconds % 60

    function show(io::IO, dms::DMS)
    print(io, degrees(dms), "° ", minutes(dms), "' ", seconds(dms), "''")
    end

    function show(io::IO, rad::Radian)
    print(io, rad.radians, "rad")
    end

    # convert constructors
    Radian(dms::DMS) = Radian(deg2rad(dms.seconds/3600))
    DMS(rad::Radian) = DMS(floor(Int, rad2deg(rad.radians) * 3600))

    convert(::Type{Radian},  dms::DMS)    = Radian(dms)
    convert(::Type{DMS},     rad::Radian) = DMS(rad)

    sin(rad::Radian) = Base.sin(rad.radians)
    cos(rad::Radian) = Base.cos(rad.radians)

    sin(dms::DMS) = sin(Radian(dms))
    cos(dms::DMS) = cos(Radian(dms))

    *(coeff::Number, dms::DMS) = DMS(coeff * dms.seconds)
    *(dms::DMS, coeff::Number) = coeff * dms
    /(dms::DMS, denom::Number) = DMS(dms.seconds/denom)

    *(coeff::Number, rad::Radian) = Radian(coeff * rad.radians)
    *(rad::Radian, coeff::Number) = coeff * rad
    /(rad::Radian, denom::Number) = Radian(rad.radians/denom)

    const ° = Degree(1)
    const rad = Radian(1)

    Base.promote_rule(::Type{Radian}, ::Type{DMS}) = Radian
end
# Examples
# α = Degree(90, 30, 45)
# β = α + Degree(89, 29, 15)
# sin(Degree(90))
# sin(Radian(π/2))
# sin(90°)
# sin(1.5rad)

# Problem
# While this works:
# +(promote(90°,3.14rad/2)...)
# 3.140796326794897rad
# Doing this
# 90°+ 3.14rad/2
# gives this error
# ERROR: MethodError: no method matching +(::DMS, ::Radian)
# Closest candidates are:
#   +(::Any, ::Any, ::Any, ::Any...) at operators.jl:560
#   +(::DMS, ::DMS) at REPL[10]:1
#   +(::Radian, ::Radian) at REPL[12]:1
# Stacktrace:
#  [1] top-level scope
#    @ REPL[38]:1
# Solution
# For the solution to the problem see the discussion here
# https://discourse.julialang.org/t/type-promotion-not-working-as-expected/65944
# one solution to get the promotion to work is to subtype Angle from Number as above
# Adding +(Angle, Angle) is probably more in the spirit of what Engheim is trying to do

max_stars_repo_name: FourMInfo/JuliaforBeginners

max_issues_repo_name: FourMInfo/JuliaforBeginners

max_forks_repo_name: FourMInfo/JuliaforBeginners


text:
export
    reflect_bps!,
    reflect_zz!,
    refresh_global!,
    refresh_restricted!,
    refresh_partial!,
    reflect_gbps

# ------------------------------------------------------------------------------
# BPS KERNELS

"""
    reflect_bps!(n, v)

BPS specular reflection (in place) of a velocity `v` against a plane defined by
its normal `n`.
"""
function reflect_bps!(n::Vector{<:Real}, v::Vector{<:Real})
    v .-= 2.0dot(n, v) * n / dot(n, n)
    return v
end

"""
    reflect_gbps(n, v)

(Generalized) BPS specular reflection - flip normal component and resample
orthogonal https://arxiv.org/abs/1706.04781
"""
function reflect_gbps(n::Vector{<:Real}, v::Vector{<:Real})
    v2 = randn(length(n))
    v2 .-= dot(n, v2 + v) * n / dot(n, n)
    return v2
end

# """
#     reflect_gbps_sphere!(n, v)
#
# (Generalized) BPS specular reflection flip normal component and resample orthogonal https://arxiv.org/abs/1706.04781
#
# """
# function reflect_gbps_sphere!{T<:Vector{Real}}(n::T, v::T)::T
#     p = dot(n, v)*n/norm(n)^2
#     v -= dot(n, v)*n/norm(n)^2
#     v2 = rnorm(length(d))
#     v2 -= dot(n, v2)*n/norm(n)^2
#     v=-p+v2*norm(v)/norm(v2)
# end

"""
    reflect_bps!(n, v, mass)

BPS specular reflection (in place) of a velocity `v` against a plane defined by
its normal `n` and a mass matrix `mass`.
"""
function reflect_bps!(n::Vector{<:Real}, v::Vector{<:Real},
                      mass::Matrix{<:Real})
    v .-= 2.0dot(n, v) * (mass * n) / dot(mass * n, n)
    return v
end

# ----------------------------------------------------------------------------
# ZZ KERNELS

"""
    reflect_zz!(mask, v)

ZigZag reflection (in place) of v according to a mask on its indeces `mask`.
"""
reflect_zz!(mask::Vector{Int}, v::Vector{<:Real}) = (v[mask] .*= -1.0; v)

reflect_zz!(mask::Int, v::Vector{<:Real}) = reflect_zz!([mask], v)

# --------------------------------------------------------------------------
# Refreshment kernels

refresh_global!(v::Vector{<:Real}) = (v .= randn(length(v)); v)

function refresh_restricted!(v::Vector{<:Real})
    v  = refresh_global!(v)
    v /= norm(v)
    return v
end

function refresh_partial!(v::Vector{<:Real}, beta::Beta{<:Real})
    # sample a vector with norm 1
    w = randn(length(v))
    w /= norm(w)
    # sample an angle
    angle = rand(beta) * 2 * pi
    # scale it by tan(angle):
    #   /|
    # /__|
    # square triangle with base 1,
    # (angle) on left => opposite side=tan(angle)
    w *= tan(angle)
    # take vector on the cone
    v += w
    # normalise
    v /= norm(v)
end
refresh_partial!(beta::Beta{<:Real}) = v -> refresh_partial!(v, beta)


text:
module ThreeJS

import Patchwork
import Patchwork.Elem
using Colors

export outerdiv, initscene

include("render.jl")
include("properties.jl")

"Outer div to keep the three-js tag in."
function outerdiv(w::AbstractString="100%", h::AbstractString="600px")
    Elem(:div, style=Dict(:width=>w, :height=>h))
end

"Initiates a three-js scene"
function initscene(;bgcolor::Color=colorant"white")
    Elem(:"three-js", attributes = Dict(:bgcolor => "#"*hex(bgcolor)))
end

if isdefined(Main, :IJulia)
    assetpath = joinpath(dirname(@__FILE__),"..","assets","bower_components")
    polymermicro = readall(joinpath(assetpath,"polymer","polymer-micro.html"))
    polymermini = readall(joinpath(assetpath,"polymer","polymer-mini.html"))
    polymer = readall(joinpath(assetpath,"polymer","polymer.html"))
    three= readall(joinpath(assetpath,"three-js","threejs","three.js"))
    trackball = readall(
        joinpath(assetpath,"three-js","threejs","TrackballControls.js")
        )
    threejs = readall(joinpath(assetpath,"three-js","three-js.html"))
    display(
        MIME"text/html"(),
        "$polymermicro$polymermini$polymer
        <script>$three</script>
        <script>$trackball</script>
        $threejs"
    )
end

end # module


text:
#=
JoiceHelpFile:
- Julia version: 1.6
- Author: connorforsythe
- Date: 2021-11-05
=#

function checkModelInfo(modelInfo::ModelInfo)

    print(modelInfo.Name)

end

max_stars_repo_name: crforsythe/Joice-Releases

max_issues_repo_name: crforsythe/Joice-Releases

max_forks_repo_name: crforsythe/Joice-Releases


text:
__precompile__()

module DictFiles
using Blosc, FunctionalData, Reexport, Compat
using HDF5
@reexport using JLD

export DictFile, dictopen, dictread, dictwrite, close, compact
export getindex, get, getkey, at, setindex!, delete!, blosc, deblosc, serialized, deserialize
export mmap
export haskey, isdict, keys, values, exists

import Base: getindex, get, getkey, setindex!, delete!, haskey, keys, values

macro onpid(pid, a)
    quote
        r = @fetchfrom $pid try
            $a
        catch e
            e
        end
        isa(r, Exception) ? rethrow(r) : r
    end
end

function blosc(a; kargs...)
    io = IOBuffer()
    serialize(io, a)
    Any[:blosc_compressed, compress(takebuf_array(io); kargs...)]
end

function deblosc(a)
    if isa(a, Array) && length(a) > 0 && a[1] == :blosc_compressed
		Base.deserialize(IOBuffer(decompress(UInt8,a[2])))
    else
        a
    end
end

function serialized(a; kargs...)
    io = IOBuffer()
    serialize(io, a)
    Any[:dictfiles_serializeditem, takebuf_array(io)]
end

function deserialize(a)
    if (isa(a, Array) || isa(a, Tuple)) && length(a) > 0 && a[1] == :dictfiles_serializeditem
		Base.deserialize(IOBuffer(snd(a)))
    else
        a
    end
end

#####################################################
##   DictFile, dictfile

defaultmode(filename) = !existsfile(filename) || (uperm(filename) & 0x2 > 0) ? "r+" : "r"

type DictFile
    jld::JLD.JldFile
    ref::@compat(Future)
    basekey::Tuple
    pid
    function DictFile(filename::AbstractString, mode::AbstractString = defaultmode(filename); compress = false)
        exists(f) = (s = stat(filename); s.inode != 0 && s.size > 0)
        if mode == "r" && !exists(filename)
            error("DictFile: file $filename does not exist")
        end

        if mode == "r+" && !exists(filename)
            mode = "w"
        end

        try
            ref = @spawnat myid() jldopen(filename, mode, compress = false, mmaparrays = false)
            a = new(fetch(ref),ref,(), myid())
            return a
        catch e
            println("DictFile: error while trying to open file $filename")
            Base.display_error(e, catch_backtrace())
            rethrow(e)
        end
    end
    function DictFile(fid::JLD.JldFile, basekey::Tuple)
        ref = @spawnat myid() fid
        r = new(fid, ref, basekey, myid()); finalizer(r, x -> close(x))
        r
    end
end

DictFile(filename::AbstractString, mode::AbstractString = defaultmode(filename), k...) = DictFile(DictFile(filename, mode), k...)
function DictFile(a::DictFile, k...)
    d = a.jld[makekey(a,k)]
    if !(typeof(d) <: JLD.JldGroup)
        error("DictFile: Try to get proxy DictFile for key $k but that is not a JldGroup")
    end
    DictFile(a.jld, tuple(a.basekey..., k...))
end

function dictread(filename, key...)
    dictopen(filename) do a
        a[key...]
    end
end

function dictwrite(v::Dict, args...)
    dictopen(args...) do a
        a[] = v
    end
end

function dictopen(f::Function, args...)
    fid = DictFile(args...)
    try
        f(fid)
    finally
        close(fid)
    end
end

#####################################################
##   close

import Base.close
function close(a::DictFile)
    if isempty(a.basekey)
        @onpid a.pid close(a.jld)
    end
end

#####################################################
##   getindex, setindex!

function makekey(a::DictFile, k::Tuple)
    if any(map(x->isa(x,Function), k))
        error("DictFiles.makekey: keys cannot contains functions. Key tuple was: $k")
    end
    reprs = [Base.map(repr, a.basekey)..., Base.map(repr, k)...]
    reprs = @p map reprs replace "/" "{{__Dictfiles_slash}}"
    key = "/"*join(reprs, "/")
    #@show key
    key
end

function getindex(a::DictFile, k...)
    @onpid a.pid begin
        key = makekey(a, k)
        if !isempty(k) && !exists(a.jld, key)
            error("DictFile: key $k does not exist")
        end
        if isempty(k)
            k2 = keys(a)
            return Dict(zip(k2, [getindex(a,x) for x in k2]))
        elseif typeof(a.jld[key]) <: JLD.JldGroup
            k2 = keys(a, k...)
            d2 = DictFile(a, k...)
            return Dict(zip(k2, map(x->getindex(d2,x), k2)))
        else
            return deblosc(DictFiles.deserialize(deblosc(read(a.jld, key))))
        end
    end
end

function setindex!(a::DictFile, v::Dict, k...; kargs...)
    @onpid a.pid begin
        if isempty(k)
            map(x->delete!(a,x), keys(a))
            flush(a.jld.plain)
        end
        map(x->setindex!(a, v[x], tuple(k...,x)...), keys(v); kargs...)
    end
end

function setindex!(a::DictFile, v::Void, k...; kargs...)
end

function setindex!(a::DictFile, v, k...; kargs...)
    @onpid a.pid begin

        if isempty(k)
            error("DictFile: cannot use empty key $k here")
        end

        key = makekey(a, k)
        #@show "in setindex" k key
        for i in 1:length(k)
            subkey = makekey(a, k[1:i])
            if exists(a.jld, subkey) && !(typeof(a.jld[subkey]) <: JLD.JldGroup)
                delete!(a, k[1:i]...)
                flush(a.jld.plain)
                break
            end
          end

        if exists(a.jld, key)
            #@show "in setindex, deleting" key
            delete!(a, k...)
            flush(a.jld.plain)
            if exists(a.jld, key)
                error("i thought we deleted this?")
            end
        end

        # map(showinfo, v)

        write(a.jld, key, v; kargs...)
        flush(a.jld.plain)
    end
end

#####################################################
##   get, getkey

get(a::DictFile, default, k...)    = haskey(a, k...) ? a[k...] : default
getkey(a::DictFile, default, k...) = haskey(a, k...) ? k : default
import FunctionalData.at
at(a::DictFile, args...) = getkey(a, args...)

#####################################################
##   delete!

import Base.delete!
function delete!(a::DictFile, k...)
    @onpid a.pid begin
        key = makekey(a,k)
        #@show "deleting" key
        if exists(a.jld, key)
          HDF5.o_delete(a.jld, key)
          #HDF5.o_delete(a.jld,"/_refs"*key)
          flush(a.jld.plain)
        end
    end
end

#####################################################
##   mmap

function mmap(a::DictFile, k...)
    @onpid a.pid begin
        dataset = a.jld[makekey(a, k)]
        if ismmappable(dataset.plain)
            return readmmap(dataset.plain)
        else
            error("DictFile: The dataset for $k does not support mmapping")
        end
    end
end

#####################################################
##   haskey, keys, values

import Base.haskey
function haskey(a::DictFile, k...)
    @onpid a.pid exists(a.jld, makekey(a, k))
end

function isdict(a::DictFile, k...)
    @onpid a.pid begin
        key = makekey(a,k);
        e = exists(a.jld, key)
        e && typeof(a.jld[key]) <: JLD.JldGroup
    end
end

import Base.keys
function parsekey(a)
    a = @p replace a "{{__Dictfiles_slash}}" "/"
    r = parse(a)
    r = isa(r,QuoteNode) ? Base.unquoted(r) : r
    try
        if !isa(r, Symbol)
            r2 = eval(r)
            if isa(r2, Tuple)
                r = r2
            end
        end
    catch e
        Base.display_error(e, catch_backtrace())
    end
    r
end

function sortkeys(a)
    if all(x -> isa(x, Real), a)
        ind = sortperm(a)
    else
        ind = sortperm(map(string, a));
    end
    a[ind]
end

function keys(a::DictFile)
    @onpid a.pid begin
        b = isempty(a.basekey) ? a.jld : a.jld[makekey(a,())]
        sortkeys([parsekey(x) for x in names(b)])
    end
end

function keys(a::DictFile, k...)
    @onpid a.pid begin
        key = makekey(a,k)
        if  !exists(a.jld, key)
            return Any[]
        end
        g = a.jld[key]
        if !(isa(g,JLD.JldGroup))
            return Any[]
        end
        sortkeys([parsekey(x) for x in setdiff(names(a.jld[key]), [:id, :file, :plain])])
    end
end

import Base.values
values(a::DictFile, k...) = [a[k..., x] for x in keys(a, k...)]

#####################################################
##   dump

import Base.dump
dump(a::DictFile) = dump(STDOUT, a)
function dump(io::IO, a::DictFile, maxdepth::Int = typemax(Int))
    function printkey(k, maxdepth, indent = 0)
        #@show k makekey(k) indent keys(a, k...)
        subkeys = sort(keys(a, k...))
        println(repeat("  ",indent), k[end], length(subkeys)>0 ? ":" : "")
        if indent<maxdepth
            Base.map(x-> printkey(tuple(k...,x), maxdepth, indent+1), subkeys)
        end
    end
    Base.map(x->printkey(tuple(x), maxdepth), sort(keys(a)))
end

#####################################################
##   compact

function compact(filename::AbstractString)
    tmpfilename = tempname()
    dictopen(filename) do from
        dictopen(tmpfilename,"w") do to
            function copykey(k)
                if isdict(from, k...)
                    map(x->copykey(tuple(k..., x)), keys(from, k...))
                    assert(isempty(setdiff(keys(from, k...), keys(to, k...))))
                else
                    to[k...] = from[k...]
                end
          end
          [copykey(tuple(x)) for x in keys(from)]
        end
    end
    mv(tmpfilename, filename, remove_destination=true)
end

include("snapshot.jl")

end


text:
function arc_deck(cur_T_bar::AbstractSymbol=symbols(:T_bar); cur_kwargs...)
  cur_dict = Dict(
    :deck => :arc,
    :T_bar => cur_T_bar,
    :is_pulsed => false,
    :H => 1.8,
    :Q => 13.6,
    :epsilon => 0.3333,
    :kappa_95 => 1.84,

    :delta_95 => 0.333,

    :nu_n => 0.385,
    :nu_T => 0.929,
    :Z_eff => 1.2,

    :f_D => 0.9,
    :A => 2.5,

    :l_i => 0.67,
    :N_G => 0.67,
    :eta_T => 0.4,
    :eta_RF => 0.5,

    :max_beta_N => 0.0259,
    :max_q_95 => 2.5,
    :max_P_E => 1500.0,
    :max_P_W => 2.5,
    :max_q_DV => 10.0,

    :B_CS => 12.77,
    :k => 0.333,
    :sigma_CS => 660,
    :sigma_TF => 88888888,
    :J_CS => 50,
    :J_TF => 88888888,
    :C_ejima => 0.3,
    :tau_FT => 1.6e9,

    :eta_CD => 0.321,
    :wave_theta => 135.0,
    :eta_LH => 0.6
  )

  merge!(cur_dict, Dict(cur_kwargs))

  BaseReactor(cur_dict)
end


text:
# Test flexible load model using a multiperiod optimization

# - Model: `_FP.BFARadPowerModel` is used to be able to test loads in both active and
#   reactive power, while keeping the model linear. It requires a distribution network.
# - Problems: both `flex_tnep` and `simple_stoch_flex_tnep` are used because they have
#   different flexible load models.

## Settings

file = normpath(@__DIR__,"..","test","data","case2","case2_d_flex.m") # Input case. Here 2-bus distribution network having 1 generator and 1 load, both on bus 1 (bus 2 is empty).
number_of_hours = 24 # Number of time periods

## Plot function

# Uncomment this part and the commented lines further down to display a nice plot when manually editing a testset
#=
using StatsPlots
function plot_flex_load(mn_data, result)
    res_load(i,key) = [result["solution"]["nw"]["$n"]["load"]["$i"][key] for n in 1:number_of_hours]
    data_load(i,key) = [mn_data["nw"]["$n"]["load"]["$i"][key] for n in 1:number_of_hours]
    load_matrix = hcat(res_load.(1,["pshift_up" "pshift_down" "pred" "pcurt" "pflex"])...) # Rows: hours; columns: power categories
    load_matrix[:,5] -= load_matrix[:,1] # min(pd,pflex) == pflex-pshift_up
    plt = groupedbar(load_matrix;
        yguide = "Power [p.u.]",
        xguide = "Time [h]",
        framestyle = :zerolines,
        bar_position = :stack,
        bar_width = 1,
        linecolor = HSLA(0,0,1,0),
        legend_position = :topleft,
        label = ["pshift_up" "pshift_down" "pred" "pcurt" :none],
        seriescolor = [HSLA(210,1,0.5,0.5) HSLA(0,0.75,0.75,0.5) HSLA(0,0.5,0.5,0.5) HSLA(0,0.75,0.25,0.5) HSLA(0,0,0,0.1)],
    )
    plot!(plt, data_load(1,"pd"); label="pd", seriestype=:stepmid, linecolor=:black, linewidth=2, linestyle=:dot)
    plot!(plt, res_load(1,"pflex"); label="pflex", seriestype=:stepmid, linecolor=:black)
    display(plt)
end
=#

## Test results

@testset "Load model" begin

    # Case where there is a flexible load and it is activated. As demand exceeds by far
    # available generation in the second half of the time horizon, demand shifting and
    # voluntary reduction are exploited to their maximum extent. Involuntary curtailment
    # covers the remaining excess of demand.
    @testset "Flex load - active" begin
        data = _FP.parse_file(file)
        _FP.add_dimension!(data, :hour, number_of_hours)
        _FP.add_dimension!(data, :year, 1; metadata = Dict{String,Any}("scale_factor"=>1))
        _FP.scale_data!(data; cost_scale_factor=1e-6)
        loadprofile = collect(reshape(range(0,2;length=number_of_hours),:,1)) # Create a load profile: ramp from 0 to 2 times the rated value of load
        time_series = _FP.make_time_series(data; loadprofile) # Compute time series by multiplying the rated value by the profile
        mn_data = _FP.make_multinetwork(data, time_series)
        result = _FP.flex_tnep(mn_data, _FP.BFARadPowerModel, cbc)
        #plot_flex_load(mn_data, result)

        @test result["solution"]["nw"][ "1"]["load"]["1"]["flex"]            ≈   1.0     atol=1e-3
        @test result["solution"]["nw"]["24"]["load"]["1"]["eshift_up"]       ≈   6.957   rtol=1e-3
        @test result["solution"]["nw"]["24"]["load"]["1"]["eshift_down"]     ≈   6.957   rtol=1e-3
        @test result["solution"]["nw"]["24"]["load"]["1"]["ered"]            ≈  12.0     rtol=1e-3
        for n in 1 : number_of_hours÷2
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pshift_down"] ≈   0.0     atol=1e-3
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pred"]        ≈   0.0     atol=1e-3
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pcurt"]       ≈   0.0     atol=1e-3
        end
        for n in number_of_hours÷2+1 : number_of_hours
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pshift_up"]   ≈   0.0     atol=1e-3
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pflex"]       ≈  10.0     rtol=1e-3
            @test result["solution"]["nw"]["$n"]["load"]["1"]["qflex"]       ≈   2.0     rtol=1e-3
        end
        @test result["objective"]                                            ≈ 163.2     rtol=1e-3
    end

    # Case where there is a flexible load but it is not activated. Demand exceeds available
    # generation in the second half of the time horizon; involuntary curtailment is the only
    # option to decrease the demand.
    @testset "Flex load - not active" begin
        data = _FP.parse_file(file)
        data["load"]["1"]["cost_inv"] = 1e10 # Increase the cost of flexibility-enabling equipment so that flexibility is not enabled in optimal solution
        _FP.add_dimension!(data, :hour, number_of_hours)
        _FP.add_dimension!(data, :year, 1; metadata = Dict{String,Any}("scale_factor"=>1))
        _FP.scale_data!(data; cost_scale_factor=1e-6)
        loadprofile = collect(reshape(range(0,2;length=number_of_hours),:,1)) # Create a load profile: ramp from 0 to 2 times the rated value of load
        time_series = _FP.make_time_series(data; loadprofile) # Compute time series by multiplying the rated value by the profile
        mn_data = _FP.make_multinetwork(data, time_series)
        result = _FP.flex_tnep(mn_data, _FP.BFARadPowerModel, cbc)
        #plot_flex_load(mn_data, result)

        @test result["solution"]["nw"][ "1"]["load"]["1"]["flex"]            ≈   0.0     atol=1e-3
        @test result["solution"]["nw"]["24"]["load"]["1"]["eshift_up"]       ≈   0.0     atol=1e-3
        @test result["solution"]["nw"]["24"]["load"]["1"]["eshift_down"]     ≈   0.0     atol=1e-3
        @test result["solution"]["nw"]["24"]["load"]["1"]["ered"]            ≈   0.0     atol=1e-3
        @test result["solution"]["nw"]["24"]["load"]["1"]["pcurt"]           ≈  10.0     rtol=1e-3
        for n in 1 : number_of_hours
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pshift_up"]   ≈   0.0     atol=1e-3
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pshift_down"] ≈   0.0     atol=1e-3
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pred"]        ≈   0.0     atol=1e-3
        end
        for n in 1 : number_of_hours÷2
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pcurt"]       ≈   0.0     atol=1e-3
        end
        for n in number_of_hours÷2+1 : number_of_hours
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pflex"]       ≈  10.0     rtol=1e-3
            @test result["solution"]["nw"]["$n"]["load"]["1"]["qflex"]       ≈   2.0     rtol=1e-3
        end
        @test result["objective"]                                            ≈ 231.8     rtol=1e-3
    end

    # Case where there is a fixed load. Demand exceeds available generation in the second
    # half of the time horizon; involuntary curtailment is the only option to decrease the
    # demand.
    @testset "Fixed load" begin
        data = _FP.parse_file(file)
        data["load"]["1"]["flex"] = 0 # State that the load cannot be made flexible
        _FP.add_dimension!(data, :hour, number_of_hours)
        _FP.add_dimension!(data, :year, 1; metadata = Dict{String,Any}("scale_factor"=>1))
        _FP.scale_data!(data; cost_scale_factor=1e-6)
        loadprofile = collect(reshape(range(0,2;length=number_of_hours),:,1)) # Create a load profile: ramp from 0 to 2 times the rated value of load
        time_series = _FP.make_time_series(data; loadprofile) # Compute time series by multiplying the rated value by the profile
        mn_data = _FP.make_multinetwork(data, time_series)
        result = _FP.flex_tnep(mn_data, _FP.BFARadPowerModel, cbc)
        #plot_flex_load(mn_data, result)

        @test result["solution"]["nw"][ "1"]["load"]["1"]["flex"]            ≈   0.0     atol=1e-3
        @test result["solution"]["nw"]["24"]["load"]["1"]["eshift_up"]       ≈   0.0     atol=1e-3
        @test result["solution"]["nw"]["24"]["load"]["1"]["eshift_down"]     ≈   0.0     atol=1e-3
        @test result["solution"]["nw"]["24"]["load"]["1"]["ered"]            ≈   0.0     atol=1e-3
        @test result["solution"]["nw"]["24"]["load"]["1"]["pcurt"]           ≈  10.0     rtol=1e-3
        for n in 1 : number_of_hours
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pshift_up"]   ≈   0.0     atol=1e-3
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pshift_down"] ≈   0.0     atol=1e-3
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pred"]        ≈   0.0     atol=1e-3
        end
        for n in 1 : number_of_hours÷2
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pcurt"]       ≈   0.0     atol=1e-3
        end
        for n in number_of_hours÷2+1 : number_of_hours
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pflex"]       ≈  10.0     rtol=1e-3
            @test result["solution"]["nw"]["$n"]["load"]["1"]["qflex"]       ≈   2.0     rtol=1e-3
        end
        @test result["objective"]                                            ≈ 231.8     rtol=1e-3
    end

    # Same case as "Flex load - active", with different load model:
    # - there are no integral (energy) bounds on voluntary reduction and on demand shifting;
    # - demand shifting has a periodic constraint that imposes a balance between upward and
    #   downward shifts.
    @testset "Flex load - shifting periodic balance" begin
        data = _FP.parse_file(file)
        _FP.add_dimension!(data, :hour, number_of_hours)
        _FP.add_dimension!(data, :scenario, Dict(1 => Dict{String,Any}("probability"=>1)))
        _FP.add_dimension!(data, :year, 1; metadata = Dict{String,Any}("scale_factor"=>1))
        _FP.scale_data!(data; cost_scale_factor=1e-6)
        loadprofile = collect(reshape(range(0,2;length=number_of_hours),:,1)) # Create a load profile: ramp from 0 to 2 times the rated value of load
        time_series = _FP.make_time_series(data; loadprofile) # Compute time series by multiplying the rated value by the profile
        mn_data = _FP.make_multinetwork(data, time_series)
        setting = Dict("demand_shifting_balance_period" => 9) # Not a divisor of 24, to verify that the balance constraint is also applied to the last period, which is not full length.
        result = _FP.simple_stoch_flex_tnep(mn_data, _FP.BFARadPowerModel, cbc; setting)
        #plot_flex_load(mn_data, result)

        @test result["solution"]["nw"][ "1"]["load"]["1"]["flex"]            ≈   1.0     atol=1e-3
        for n in 1 : number_of_hours÷2
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pshift_down"] ≈   0.0     atol=1e-3
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pred"]        ≈   0.0     atol=1e-3
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pcurt"]       ≈   0.0     atol=1e-3
        end
        for n in number_of_hours÷2+1 : number_of_hours
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pshift_up"]   ≈   0.0     atol=1e-3
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pflex"]       ≈  10.0     rtol=1e-3
            @test result["solution"]["nw"]["$n"]["load"]["1"]["qflex"]       ≈   2.0     rtol=1e-3
        end
        for n in 1 : 9
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pshift_up"]   ≈   0.0     atol=1e-3
        end
        @test result["solution"]["nw"]["10"]["load"]["1"]["pshift_up"]       ≈   2.174   rtol=1e-3
        @test result["solution"]["nw"]["11"]["load"]["1"]["pshift_up"]       ≈   1.304   rtol=1e-3
        @test result["solution"]["nw"]["12"]["load"]["1"]["pshift_up"]       ≈   0.4348  rtol=1e-3
        for n in 19 : number_of_hours
            @test result["solution"]["nw"]["$n"]["load"]["1"]["pshift_up"]   ≈   0.0     atol=1e-3
        end
        @test result["objective"]                                            ≈  78.53    rtol=1e-3
    end

end;


text:
# Skipping MacroDefinition: imcdCanvasPutImage(_canvas,_image,_x,_y,_w,_h,_xmin,_xmax,_ymin,_ymax){if(_image->color_space==IM_RGB){if(_image->has_alpha)cdCanvasPutImageRectRGBA(_canvas,_image->width,_image->height,(unsignedchar*)_image->data[0],(unsignedchar*)_image->data[1],(unsignedchar*)_image->data[2],(unsignedchar*)_image->data[3],_x,_y,_w,_h,_xmin,_xmax,_ymin,_ymax);elsecdCanvasPutImageRectRGB(_canvas,_image->width,_image->height,(unsignedchar*)_image->data[0],(unsignedchar*)_image->data[1],(unsignedchar*)_image->data[2],_x,_y,_w,_h,_xmin,_xmax,_ymin,_ymax);}elsecdCanvasPutImageRectMap(_canvas,_image->width,_image->height,(unsignedchar*)_image->data[0],_image->palette,_x,_y,_w,_h,_xmin,_xmax,_ymin,_ymax);}
# Skipping MacroDefinition: imImageGamma(_image,_gamma){floatparams[1];params[0]=_gamma;imProcessToneGamut(_image,_image,IM_GAMUT_POW,params);}
# Skipping MacroDefinition: imImageBrightnessContrast(_image,_bright_shift,_contrast_factor){float_params[2];_params[0]=bright_shift;_params[1]=contrast_factor;imProcessToneGamut(_image,_image,IM_GAMUT_BRIGHTCONT,_params);}
# Skipping MacroDefinition: imImageLevel(_image,_start,_end){float_params[2];_params[0]=_start;_params[1]=_end;imProcessToneGamut(_image,_image,IM_GAMUT_EXPAND,_params);}
# Skipping MacroDefinition: imImageEqualize(_image)imProcessEqualizeHistogram(_image,_image)
# Skipping MacroDefinition: imImageNegative(_image)imProcessNegative(_image,_image)
# Skipping MacroDefinition: imImageAutoLevel(_image,_percent)imProcessExpandHistogram(_image,_image,_percent)
typealias imUnaryPointOpFunc Ptr{Void}
typealias imUnaryPointColorOpFunc Ptr{Void}
typealias imMultiPointOpFunc Ptr{Void}
typealias imMultiPointColorOpFunc Ptr{Void}
# begin enum imUnaryOp
typealias imUnaryOp UInt32
const IM_UN_EQL = 0
const IM_UN_ABS = 1
const IM_UN_LESS = 2
const IM_UN_INV = 3
const IM_UN_SQR = 4
const IM_UN_SQRT = 5
const IM_UN_LOG = 6
const IM_UN_EXP = 7
const IM_UN_SIN = 8
const IM_UN_COS = 9
const IM_UN_CONJ = 10
const IM_UN_CPXNORM = 11
const IM_UN_POSITIVES = 12
const IM_UN_NEGATIVES = 13
# end enum imUnaryOp
# begin enum imBinaryOp
typealias imBinaryOp UInt32
const IM_BIN_ADD = 0
const IM_BIN_SUB = 1
const IM_BIN_MUL = 2
const IM_BIN_DIV = 3
const IM_BIN_DIFF = 4
const IM_BIN_POW = 5
const IM_BIN_MIN = 6
const IM_BIN_MAX = 7
# end enum imBinaryOp
# begin enum imLogicOp
typealias imLogicOp UInt32
const IM_BIT_AND = 0
const IM_BIT_OR = 1
const IM_BIT_XOR = 2
# end enum imLogicOp
typealias imRenderFunc Ptr{Void}
typealias imRenderCondFunc Ptr{Void}
# begin enum imToneGamut
typealias imToneGamut UInt32
const IM_GAMUT_NORMALIZE = 0
const IM_GAMUT_POW = 1
const IM_GAMUT_LOG = 2
const IM_GAMUT_EXP = 3
const IM_GAMUT_INVERT = 4
const IM_GAMUT_ZEROSTART = 5
const IM_GAMUT_SOLARIZE = 6
const IM_GAMUT_SLICE = 7
const IM_GAMUT_EXPAND = 8
const IM_GAMUT_CROP = 9
const IM_GAMUT_BRIGHTCONT = 10
# end enum imToneGamut
# begin enum imToneGamutFlags
typealias imToneGamutFlags UInt32
const IM_GAMUT_MINMAX = 256
# end enum imToneGamutFlags
type imStats
    max::Cfloat
    min::Cfloat
    positive::Culong
    negative::Culong
    zeros::Culong
    mean::Cfloat
    stddev::Cfloat
end


text:
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# Description
# ==============================================================================
#
#   Functions related to the conversion between Euler angles.
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

export angle_to_angle

"""
    angle_to_angle(θ₁::Number, θ₂::Number, θ₃::Number, rot_seq_orig::Symbol, rot_seq_dest::Symbol)
    angle_to_angle(Θ::EulerAngles, rot_seq_dest::Symbol)

Convert the Euler angles `θ₁`, `θ₂`, and `θ₃` [rad] with the rotation sequence
`rot_seq_orig` to a new set of Euler angles with rotation sequence
`rot_seq_dest`.

The input values of the origin Euler angles can also be passed inside the
structure `Θ` (see [`EulerAngles`](@ref)).

The rotation sequence is defined by a `:Symbol`. The possible values are:
`:XYX`, `XYZ`, `:XZX`, `:XZY`, `:YXY`, `:YXZ`, `:YZX`, `:YZY`, `:ZXY`, `:ZXZ`,
`:ZYX`, and `:ZYZ`.

# Example

```jldoctest
julia> angle_to_angle(-pi / 2, -pi / 3, -pi / 4, :ZYX, :XYZ)
EulerAngles{Float64}:
  R(X) : -1.0472   rad  (-60.0°)
  R(Y) :  0.785398 rad  ( 45.0°)
  R(Z) : -1.5708   rad  (-90.0°)

julia> angle_to_angle(-pi / 2, 0, 0, :ZYX, :XYZ)
EulerAngles{Float64}:
  R(X) :  0.0    rad  ( 0.0°)
  R(Y) :  0.0    rad  ( 0.0°)
  R(Z) : -1.5708 rad  (-90.0°)

julia> Θ = EulerAngles(1, 2, 3, :XYX)
EulerAngles{Int64}:
  R(X) :  1 rad  ( 57.2958°)
  R(Y) :  2 rad  ( 114.592°)
  R(X) :  3 rad  ( 171.887°)

julia> angle_to_angle(Θ, :ZYZ)
EulerAngles{Float64}:
  R(Z) : -2.70239 rad  (-154.836°)
  R(Y) :  1.46676 rad  ( 84.0393°)
  R(Z) : -1.05415 rad  (-60.3984°)
```
"""
@inline function angle_to_angle(
    θ₁::Number,
    θ₂::Number,
    θ₃::Number,
    rot_seq_orig::Symbol,
    rot_seq_dest::Symbol
)
    return dcm_to_angle(angle_to_dcm(θ₁, θ₂, θ₃, rot_seq_orig), rot_seq_dest)
end

@inline function angle_to_angle(Θ::EulerAngles, rot_seq_dest::Symbol)
    return angle_to_angle(Θ.a1, Θ.a2, Θ.a3, Θ.rot_seq, rot_seq_dest)
end


text:
################################################################################
# This is the Generic implementation of an AbstractState. More documentation
# can be found on the specific types and the README.
################################################################################
abstract type AbstractState end

mutable struct GenericState <: AbstractState

    x :: Iterate

    #Starting time
    start_time :: FloatVoid

    function GenericState(x          :: Iterate;
                          start_time :: FloatVoid = NaN)

      return new(x, start_time)
   end
end

function update!(stateatx :: AbstractState;
                 x        :: Iterate    = nothing,
                 tmps     :: FloatVoid  = nothing)

 stateatx.x          = x      == nothing ? stateatx.x : x
 stateatx.start_time = tmps   == nothing ? stateatx.start_time : tmps

 return stateatx
end