text:
export DARTStrain1st!, DARTStrain2nd!, DARTSevaltrain1st!, all_ws_sansbn, all_αs

using Flux
using Flux: onehotbatch, onecold
using Juno
using Base.Iterators
using StatsBase: mean
using Zygote
using Zygote: @nograd
using LinearAlgebra
using CUDA

function accuracy(m, x, y)
    mx = m(x)
    showmx = mx |>cpu
    showy = y|>cpu
    for i in 1:size(showmx,2)
        @show collect(zip(softmax(showmx[:,i]), showy[:,i]))
    end
    mean(onecold(mx, 1:10)|>cpu .== onecold(y|>cpu, 1:10))
end

function DARTStrain1st!(loss, model, train, val, opt_α, opt_w, losses=[0f0,0f0], epoch = 1; cbepoch = () -> (), cbbatch = () -> ())
    local train_loss
    local val_loss
    w = all_ws_sansbn(model)
    α = all_αs(model)
    opt_w.os[2].t = epoch - 1
    for (train_batch, val_batch) in zip(TrainCuIterator(train), TrainCuIterator(val))
        if epoch == 29 || epoch == 30
            @show accuracy(model, train_batch...)
            @show accuracy(model, val_batch...)
        end
        display("grad weights")
        @time begin
            gsw = gradient(w) do
                train_loss = loss(model, train_batch...)
                return train_loss
            end
            losses[1] = train_loss
        end
        foreach(CUDA.unsafe_free!, train_batch)
        Flux.Optimise.update!(opt_w, w, gsw)
        CUDA.reclaim()
        display("grad alpha")
        @time begin
            gsα = gradient(α) do
                val_loss = loss(model, val_batch...)
                return val_loss
            end
            losses[2] = val_loss
            if epoch == 29 || epoch == 30
                @show losses
            end
        end
        foreach(CUDA.unsafe_free!, val_batch)
        Flux.Optimise.update!(opt_α, α, gsα)
        CUDA.reclaim()
        cbbatch()
    end
    cbepoch()
end

all_ws(model::DARTSEvalModel) = Flux.params([model.stem, model.cells..., model.global_pooling, model.classifier])

function DARTSevaltrain1st!(loss, model, train, opt_w, losses=[0f0,0f0], epoch = 1; cbepoch = () -> (), cbbatch = () -> ())
    w = all_ws(model)
    local train_loss
    opt_w.os[2].t = epoch - 1
    for train_batch in EvalCuIterator(train)
        gsw = gradient(w) do
            train_loss = loss(model, train_batch...)
            return train_loss
        end
        losses[1] = train_loss
        CUDA.reclaim()
        GC.gc()
        Flux.Optimise.update!(opt_w, w, gsw)
        cbbatch()
    end
    cbepoch()
end

function update_all!(opt, ps::Params, gs)
    for (p, g) in zip(ps, gs)
        g == nothing && continue
        Flux.Optimise.update!(opt, p, g)
    end
end

function DARTStrain2nd!(loss, model, train, val, opt; cb = () -> ())
    function grad_loss(model, ps, batch, verbose = false)
        gs = gradient(ps) do
            loss(model, batch...)
        end
    end

    ξ = opt.eta

    w = all_ws(model)
    α = all_αs(model)

    for (train_batch, val_batch) in zip(CuIterator(train), CuIterator(val))
        gsα = grad_loss(model, α, val_batch)
        model_prime = deepcopy(model)
        model_prime_α = deepcopy(model_prime)
        w_prime = all_ws(model_prime_α)

        gsw_prime = grad_loss(model_prime, w_prime, val_batch)

        Flux.Optimise.update!(Descent(ξ), w_prime, gsw_prime)

        model_prime_minus = deepcopy(model_prime)

        w_prime_minus = all_ws(model_prime_minus)

        gsw_prime_minus = grad_loss(model_prime_minus, w_prime_minus, val_batch)

        model_minus = deepcopy(model)
        model_plus = deepcopy(model)

        w_minus = all_ws(model_minus)
        w_plus = all_ws(model_plus)

        epsilon = 0.01 ./ norm([gsw_prime_minus[w_] for w_ in w_prime_minus.order])
        update_all!(
            Descent(epsilon),
            w_minus,
            [gsw_prime_minus[w_] for w_ in w_prime_minus.order],
        )
        update_all!(
            Descent(-1 * epsilon),
            w_plus,
            [gsw_prime_minus[w_] for w_ in w_prime_minus.order],
        )

        gsα_prime = grad_loss(model_prime_α, all_αs(model_prime_α), val_batch)

        gsα_plus = grad_loss(model_plus, all_αs(model_plus), train_batch)
        gsα_minus = grad_loss(model_minus, all_αs(model_minus), train_batch)

        update_all!(opt, α, [gsα_prime[a] for a in all_αs(model_prime_α).order])
        update_all!(
            Descent(-1 * ξ^2 / (2 * epsilon)),
            α,
            [gsα_plus[a] for a in all_αs(model_plus).order],
        )
        update_all!(
            Descent(ξ^2 / (2 * epsilon)),
            α,
            [gsα_minus[a] for a in all_αs(model_minus).order],
        )

        gsw = grad_loss(model, w, train_batch)
        Flux.Optimise.update!(opt, w, gsw)

        cb()
    end
end

max_stars_repo_name: SuReLI/DifferentiableNAS

max_issues_repo_name: SuReLI/DifferentiableNAS

max_forks_repo_name: SuReLI/DifferentiableNAS


text:
a = 5
b = 7
da = 0.1
db = 0.3

dc_max = da + db

println("|(a+b)-(a+da)+(b+db)|: ", abs((a+b)-((a+da)+(b+db))), "<=", dc_max)
println("|(a+b)-(a-da)+(b+db)|: ", abs((a+b)-((a-da)+(b+db))), "<=", dc_max)
println("|(a+b)-(a+da)+(b-db)|: ", abs((a+b)-((a+da)+(b-db))), "<=", dc_max)
println("|(a+b)-(a-da)+(b-db)|: ", abs((a+b)-((a-da)+(b-db))), "<=", dc_max)
println("|(a-b)-(a+da)+(b+db)|: ", abs((a-b)-((a+da)-(b+db))), "<=", dc_max)
println("|(a-b)-(a-da)+(b+db)|: ", abs((a-b)-((a-da)-(b+db))), "<=", dc_max)
println("|(a-b)-(a+da)+(b-db)|: ", abs((a-b)-((a+da)-(b-db))), "<=", dc_max)
println("|(a-b)-(a-da)+(b-db)|: ", abs((a-b)-((a-da)-(b-db))), "<=", dc_max)

ext: jl


text:
__precompile__()

################################################################################
#
#     Hecke.jl : Hecke main file
#
# This file is part of Hecke.
#
# Copyright (c) 2015: Claus Fieker, Tommy Hofmann
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
#   this list of conditions and the following disclaimer in the documentation
#   and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# (C) 2015, 2016 Claus Fieker, Tommy Hofmann
#
################################################################################

module Hecke

using Nemo

################################################################################
#
#  Load FPlll if available
#
################################################################################

if isdir(joinpath(Pkg.dir(),"FPlll"))
  using FPlll
end

################################################################################
#
#  Make Hecke compatible for julia 0.4
#
################################################################################

include("compat.jl")

################################################################################
#
#  Import/export
#
################################################################################

import Nemo: nf_elem, PariIdeal, AnticNumberField, degree,
             den, num, lg, prime_decomposition, parent, length,
             norm, real, imag, inv, rows, getindex!, lll, hnf, cols, basis,
             trace, factor, mod, zero, pari_load, PariPolyRing,
             PariRationalField, PariQQ, pari_vec, hash, PolynomialRing, coeff,
             var, abs, min, iszero, one, sqrt, isone, deepcopy, rank, in,
             discriminant, log, sub, lift, FlintQQ, FlintZZ, elem_type,
             elem_from_mat_row, elem_to_mat_row!, order, signature,
             base_ring, compose, root, arf_struct, fmpq, valuation,
             Ring, prec, conj, mul!, gen, divexact, derivative, zero!, divrem,
             resultant, evaluate, setcoeff!, div, isodd, iseven, max, floor,
             ceil, //, setindex!, transpose, colon, nf_elem, isreal,
             MatrixSpace, contains, overlaps, solve, unique_integer, gcd,
             minpoly, charpoly, det,
             howell_form, needs_parentheses, is_negative, parent_type,
             intersect, lcm, strong_echelon_form, strong_echelon_form!,
             howell_form!, add!, mul!, fmpq_poly, FmpzPolyRing,
             FlintFiniteField, addeq!, acb_vec, array, acb_struct,
             acb_vec_clear, lufact!

export AnticNumberField, hash, update, nf, next_prime, dot, maximal_order

import Base: show, minimum, rand, prod, copy, rand!, call, rand, ceil, round,
             size, dot, in, powermod, ^, getindex, ==, <, >, +, *, /, \, -, !=
             getindex, setindex!, transpose, getindex, //, colon, exp, div,
             floor, max, BigFloat, promote_rule, precision, dot
             first, StepRange, show, one, zero, inv, iseven, isodd

# To make all exported Nemo functions visible to someone using "using Hecke"
# we have to export everything again

for i in names(Nemo)
  eval(Expr(:export, i))
end

export @vprint, @hassert, @vtime, add_verbose_scope, get_verbose_level,
       set_verbose_level, add_assert_scope, get_assert_level, set_assert_level,
       update, @timeit, show, StepRange, domain, codomain, image, preimage,
       modord, resultant, @test_and_infer

###############################################################################
#
#   Library initialisation
#
###############################################################################

const pkgdir = realpath(joinpath(dirname(@__FILE__), ".."))
const libhecke = joinpath(pkgdir, "local", "lib", "libhecke")
const libdir = joinpath(pkgdir, "local", "lib")

function __init__()

  on_windows = @windows ? true : false
  on_linux = @linux ? true : false

  println("")
  print("Welcome to \n")
  print_with_color(:red, "
  _    _           _
 | |  | |         | |
 | |__| | ___  ___| | _____
 |  __  |/ _ \\\/ __| |/ / _ \\
 | |  | |  __/ (__|   <  __/
 |_|  |_|\\___|\\___|_|\\_\\___|
  ")

  println()
  print("Version")
  print_with_color(:green, " $VERSION_NUMBER ")
  print("... \n ... which comes with absolutely no warrant whatsoever")
  println()
  println("(c) 2015, 2016 by Claus Fieker and Tommy Hofmann")
  println()

  if "HOSTNAME" in keys(ENV) && ENV["HOSTNAME"] == "juliabox"
    push!(Libdl.DL_LOAD_PATH, "/usr/local/lib")
  elseif on_linux
    push!(Libdl.DL_LOAD_PATH, libdir)
    Libdl.dlopen(libhecke)
  else
    push!(Libdl.DL_LOAD_PATH, libdir)
	ENV["PATH"] = ENV["PATH"] * ";" * joinpath(Pkg.dir("Nemo"), "local", "lib")
  end

  t = create_accessors(AnticNumberField, acb_root_ctx, get_handle())
  global _get_nf_conjugate_data_arb = t[1]
  global _set_nf_conjugate_data_arb = t[2]

  t = create_accessors(AnticNumberField,
                       Tuple{Array{nf_elem, 1}, nf_elem},
                       get_handle())
  global _get_nf_torsion_units = t[1]
  global _set_nf_torsion_units = t[2]

  t = create_accessors(AnticNumberField, NfMaxOrd, get_handle())

  global _get_maximal_order_of_nf = t[1]
  global _set_maximal_order_of_nf = t[2]

  t = create_accessors(NfMaxOrd, ClassGrpCtx, get_handle())

  global _get_ClassGrpCtx_of_order = t[1]
  global _set_ClassGrpCtx_of_order = t[2]

  global R = _RealRing()
end

function conjugate_data_arb(K::AnticNumberField)
  try
    c = _get_nf_conjugate_data_arb(K)::acb_root_ctx
    return c
  catch
    c = acb_root_ctx(K.pol)
    _set_nf_conjugate_data_arb(K, c)
    return c
  end
end

function _torsion_units(K::AnticNumberField)
  try
    c = _get_nf_torsion_units(K)::Tuple{Array{nf_elem, 1}, nf_elem}
    return c
  catch
    O = maximal_order(K)
    tor, gen = _torsion_units(O)
    tornf = [ elem_in_nf(x) for x in tor]
    gennf = elem_in_nf(gen)
    _set_nf_torsion_units(K, (tornf, gennf))
    return tornf, gennf
  end
end

function torsion_units(K::AnticNumberField)
  ar, g = _torsion_units(K)
  return ar
end

function torsion_units_gen(K::AnticNumberField)
  ar, g = _torsion_units(K)
  return g
end

################################################################################
#
#  Version number
#
################################################################################

global VERSION_NUMBER = v"0.1.3"

################################################################################
#
#  Verbose printing
#
################################################################################

global hecke = Hecke

global VERBOSE_SCOPE = Symbol[]

global VERBOSE_LOOKUP = Dict{Symbol, Int}()

global VERBOSE_PRINT_INDENT = [ 0 ]

function add_verbose_scope(s::Symbol)
  !(s in VERBOSE_SCOPE) && push!(VERBOSE_SCOPE, s)
  nothing
end

function pushindent()
  a = VERBOSE_PRINT_INDENT[1]
  VERBOSE_PRINT_INDENT[1] = a + 1
  nothing
end

function popindent()
  a = VERBOSE_PRINT_INDENT[1]
  VERBOSE_PRINT_INDENT[1] = a - 1
  nothing
end

function _global_indent()
  s = "  "^VERBOSE_PRINT_INDENT[1]
  return s
end

macro vprint(args...)
  if length(args) == 2
    quote
      if get_verbose_level($(args[1])) >= 1
        print(_global_indent())
        print($(args[2]))
      end
    end
  elseif length(args) == 3
    quote
      if get_verbose_level($(args[1])) >= $(args[2])
        print(_global_indent())
        print($(args[3]))
      end
    end
  end
end

macro v_do(args...)
  if length(args) == 2
    quote
      if get_verbose_level($(args[1])) >= 1
       $(args[2])
      end
    end
  elseif length(args) == 3
    quote
      if get_verbose_level($(args[1])) >= $(args[2])
        $(args[3])
      end
    end
  end
end

function set_verbose_level(s::Symbol, l::Int)
  !(s in VERBOSE_SCOPE) && error("Not a valid symbol")
  VERBOSE_LOOKUP[s] = l
end

function get_verbose_level(s::Symbol)
  !(s in VERBOSE_SCOPE) && error("Not a valid symbol")
  return get(VERBOSE_LOOKUP, s, 0)::Int
end

################################################################################
#
#  Assertions
#
################################################################################

global ASSERT_SCOPE = Symbol[]

global ASSERT_LOOKUP = Dict{Symbol, Int}()

function add_assert_scope(s::Symbol)
  !(s in ASSERT_SCOPE) && push!(ASSERT_SCOPE, s)
  nothing
end

function set_assert_level(s::Symbol, l::Int)
  !(s in ASSERT_SCOPE) && error("Not a valid symbol")
  ASSERT_LOOKUP[s] = l
end

function get_assert_level(s::Symbol)
  !(s in ASSERT_SCOPE) && error("Not a valid symbol")
  return get(ASSERT_LOOKUP, s, 0)::Int
end

macro hassert(args...)
  if length(args) == 2
    quote
      if get_assert_level($(args[1])) >= 1
        @assert $(args[2])
      end
    end
  elseif length(args) == 3
    quote
      if get_assert_level($(args[1])) >= $(args[2])
        @assert $(args[3])
      end
    end
  end
end

macro test_and_infer(f,args,res)
  quote
    if isa($(esc(args)), Tuple)
      Base.Test.@inferred $(esc(f))($(esc(args))...)
      Base.Test.@test $(esc(f))($(esc(args))...) == $(esc(res))
    else
      Base.Test.@inferred $(esc(f))($(esc(args)))
      local t = $(esc(res))
      Base.Test.@test $(esc(f))($(esc(args))) == t
    end
  end
end

################################################################################
#
#  Verbose time printing
#
################################################################################

macro vtime(args...)
  if length(args) == 2
    msg = string(args[2])
    quote
      if get_verbose_level($(args[1])) >= 1
        local t0 = time_ns()
        local val = $(esc(args[2]))
        println((time_ns()-t0)/1e9, " @ ", $msg)
        val
      else
        local val2 = $(esc(args[2]))
        val2
      end
    end
  elseif length(args) == 3
    msg = string(args[3])
    quote
      if get_verbose_level($(args[1])) >= $(args[2])
        local t0 = time_ns()
        local val = $(esc(args[3]))
        println((time_ns()-t0)/1e9, " @ ", $msg)
        val
      else
        local val2 = $(esc(args[3]))
        val2
      end
    end
  end
end

################################################################################
#
#  Functions for timings
#
################################################################################

macro timeit(args...)
  loops = 50
  if length(args) == 2
    loops = args[2]
  end

  quote
    gc_enable(false)
    # warm-up
    local val = $(esc(args[1]))

    local min = Inf
    local max = 0
    local sum = 0.0
    local t0, diff
    local i
    for i in 1:$(loops)
      t0 = time_ns()
      local val = $(esc(args[1]))
      diff = time_ns() - t0
      if diff > max
        max = diff
      end
      if diff < min
        min = diff
      end
      sum += diff
    end
    sum = sum/$(loops)
    print("max: $(max/1e9)\nmin: $(min/1e9)\nsum: $(sum/1e9)\n")
    gc_enable(true)
    nothing
  end
end

function timeit(expr::Expr)
  @timeit expr
end

################################################################################
#
#  Exception types
#
################################################################################

type LowPrecisionCholesky <: Exception end

Base.showerror(io::IO, e::LowPrecisionCholesky) =
    print(io, e.var, """
    Negative diagonal in Cholesky decomposition, probably a precision issue""")

type LowPrecisionLLL <: Exception end

Base.showerror(io::IO, e::LowPrecisionLLL) =
    print(io, e.var, """
    Transformation matrix has too large entries relative to precision in LLL""")

# what is this function doing here?
function checkbounds(a::Int, b::Int) nothing; end;

################################################################################
#
#  "Submodules"
#
################################################################################

include("HeckeTypes.jl")
include("Misc.jl")
include("LinearAlgebra.jl")
include("BigComplex.jl")
include("conjugates.jl")
#include("NfMaxOrd/NfOrdCls.jl")
include("NfOrd.jl")
include("analytic.jl")
include("NfMaxOrd.jl")
include("Map.jl")
include("basis.jl")
include("helper.jl")
include("misc2.jl")

for T in subtypes(Map)
  Base.call(M::T, a) = image(M, a)
end

################################################################################
#
#  Verbose printing
#
################################################################################

doc"""
***
    vshow(A) -> Void

> Prints all fields of $A$.
"""
function vshow(A)
  for i in fieldnames(typeof(A))
    if isdefined(A, i)
      println("$i: ")
      println(getfield(A, i), "\n")
    else
      println("$i: Not definied")
    end
  end
end

################################################################################
#
#  Element types for parent types
#
################################################################################

# Nemo only provides element_types for parent objects

elem_type(::NfMaxOrd) = NfOrdElem{NfMaxOrd}

elem_type(::Type{NfMaxOrd}) = NfOrdElem{NfMaxOrd}

elem_type(::NfOrdGen) = NfOrdElem{NfOrdGen}

elem_type(::Type{NfOrdGen}) = NfOrdElem{NfOrdGen}

elem_type{T}(::Type{FacElemMon{T}}) = FacElem{T}

elem_type(::Type{AnticNumberField}) = nf_elem

elem_type(::Type{FqNmodFiniteField}) = fq_nmod

elem_type{T}(::Type{GenResRing{T}}) = GenRes{T}

################################################################################
#
#  Parent types for element types
#
################################################################################

parent_type(::Type{NfOrdElem{NfMaxOrd}}) = NfMaxOrd

################################################################################
#
#  An update function
#
################################################################################

function update()

  olddir = pwd()

  println("Updating Hecke ... ")
  cd(Pkg.dir("Hecke"))
  run(`git pull`)

  pkgdir = Pkg.dir("Nemo")

  println("Updating Nemo ... ")
  cd("$pkgdir")
  run(`git pull`)

  println("Updating antic ... ")
  cd("$pkgdir/deps/antic")
  run(`git pull`)

  println("Updating arb ... ")
  cd("$pkgdir/deps/arb")
  run(`git pull`)
  run(`make -j`)
  run(`make install`)

  println("Updating flint ... ")
  cd("$pkgdir/deps/flint2")
  run(`git pull`)
  run(`make -j`)
  run(`make install`)

  cd(olddir)
end

function whos(io::IO=STDOUT, m::Module=current_module(), pattern::Regex=r"")
    maxline = Base.tty_size()[2]
    line = zeros(UInt8, maxline)
    head = PipeBuffer(maxline + 1)
    for v in sort!(names(m, true)) # show also NON exported stuff!
        s = string(v)
        if isdefined(m, v) && ismatch(pattern, s)
            value = getfield(m, v)
            @printf head "%30s " s
            try
                bytes = Base.summarysize(value)
                if bytes < 10_000
                    @printf(head, "%6d bytes  ", bytes)
                else
                    @printf(head, "%6d KB     ", bytes ÷ (1024))
                end
                print(head, Base.summary(value))
            catch e
                print(head, "#=ERROR: unable to show value=#")
                println(e)
            end

            newline = search(head, UInt8('\n')) - 1
            if newline < 0
                newline = nb_available(head)
            end
            if newline > maxline
                newline = maxline - 1 # make space for ...
            end
            line = resize!(line, newline)
            line = read!(head, line)

            Base.write(io, line)
            if nb_available(head) > 0 # more to read? replace with ...
                print(io, '\u2026') # hdots
            end
            println(io)
            seekend(head) # skip the rest of the text
        end
    end
end

whos(m::Module, pat::Regex=r"") = whos(STDOUT, m, pat)
whos(pat::Regex) = whos(STDOUT, current_module(), pat)

#
# stuff for 0.5
#

if VERSION > v"0.5.0-"
  @inline __get_rounding_mode() = Base.MPFR.rounding_raw(BigFloat)
end

if VERSION < v"0.5.0-"
  @inline __get_rounding_mode() = Base.MPFR.ROUNDING_MODE[end]
end

end


text:
#=================================================================#
# utils.jl
# authors : Florian DELAVERNHE, Guillaume LEGRU
# date : 2nd of November 2016
#
# A simple compilation of utility functions for the 2016 MOMH Project.
#
#=================================================================#

#=================================================================#
# naturalArray function
# args : range::UnitRange{Int}
# out : A::Int[rangeMax]
function naturalArray(range)
  A = []
  for i in range
    push!(A, i)
  end
  return A
end

#=================================================================#
# filledArray function
# args : value::Int, dim::Int
# out : A::Int[dim]
function filledArray(value, dim)
  A = []
  for i in 1:dim
    push!(A, value)
  end
  return A
end

#=================================================================#
# removeAt! function
# args A::Any[]
# out : nothing
function removeAt!(A, index)
  if index >= length(A)
    pop!(A)
  else
    A[index] = pop!(A)
  end
end


text:
using RoME

##

cb(fg_, lp) = @show lp, length(ls(fg_))

Qd = diagm( [0.1;0.1;0.05].^2 )
fg = generateCanonicalFG_Helix2DSlew!(46, slew_x=2/3, posesperturn=15, radius=10,
                                      useMsgLikelihoods=false, Qd=Qd, postpose_cb=cb)
#

##

##

using TensorCast
using Gadfly
Gadfly.set_default_plot_size(35cm,25cm)

##

vals = getPPE.(fg, (ls(fg) |> sortDFG), :simulated) .|> x-> x.suggested
@cast XYT[d,p] := vals[p][d]
Gadfly.plot(x=XYT[1,:],y=XYT[2,:], Geom.path)

##


text:
#Adapted from https://github.com/github/developer.github.com/blob/master/Rakefile#L21-L48

#Run this file from its current directory to build the documentation and push the result into gh-pages

last_commit=readchomp(`git --no-pager log -1 --pretty=format:"%h:%s"`)

ENV["GIT_DIR"]=abspath(chomp(String(read(`git rev-parse --git-dir`))))

old_sha = chomp(String(read(`git rev-parse refs/remotes/origin/gh-pages`)))

include("make.jl")

cd("build") do

    gif="/tmp/dev.gh.i"
    ENV["GIT_INDEX_FILE"]=gif
    ENV["GIT_WORK_TREE"]=pwd()
    run(`git add -A`)
    tsha=chomp(String(read(`git write-tree`)))
    mesg="Deploy docs for master@$last_commit"

    if length(old_sha) == 40
        csha = chomp(String(read(`git commit-tree $tsha -p $old_sha -m $(mesg)`)))
    else
        csha = chomp(String(read(`git commit-tree $tsha -m $(mesg)`)))
    end

     println("Created commit $csha")

     run(`git --no-pager show $csha --stat`)

     run(`git update-ref refs/heads/gh-pages $csha `)

     run(`git push origin gh-pages `)

end


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

# parsing tests
@test v"2" == VersionNumber(2)
@test v"3.2" == VersionNumber(3, 2)
@test v"4.3.2" == VersionNumber(4, 3, 2)

@test v"2-" == VersionNumber(2, 0, 0, ("",), ())
@test v"3.2-" == VersionNumber(3, 2, 0, ("",), ())
@test v"4.3.2-" == VersionNumber(4, 3, 2, ("",), ())

@test v"2-1" == VersionNumber(2, 0, 0, (1,), ())
@test v"3.2-1" == VersionNumber(3, 2, 0, (1,), ())
@test v"4.3.2-1" == VersionNumber(4, 3, 2, (1,), ())

@test v"2-a" == VersionNumber(2, 0, 0, ("a",), ()) == v"2a"
@test v"3.2-a" == VersionNumber(3, 2, 0, ("a",), ()) == v"3.2a"
@test v"4.3.2-a" == VersionNumber(4, 3, 2, ("a",), ()) == v"4.3.2a"

@test v"2-a1" == VersionNumber(2, 0, 0, ("a1",), ()) == v"2a1"
@test v"3.2-a1" == VersionNumber(3, 2, 0, ("a1",), ()) == v"3.2a1"
@test v"4.3.2-a1" == VersionNumber(4, 3, 2, ("a1",), ()) == v"4.3.2a1"

@test v"2-1a" == VersionNumber(2, 0, 0, ("1a",), ())
@test v"3.2-1a" == VersionNumber(3, 2, 0, ("1a",), ())
@test v"4.3.2-1a" == VersionNumber(4, 3, 2, ("1a",), ())

@test v"2-a.1" == VersionNumber(2, 0, 0, ("a", 1), ()) == v"2a.1"
@test v"3.2-a.1" == VersionNumber(3, 2, 0, ("a", 1), ()) == v"3.2a.1"
@test v"4.3.2-a.1" == VersionNumber(4, 3, 2, ("a", 1), ()) == v"4.3.2a.1"

@test v"2-1.a" == VersionNumber(2, 0, 0, (1, "a"), ())
@test v"3.2-1.a" == VersionNumber(3, 2, 0, (1, "a"), ())
@test v"4.3.2-1.a" == VersionNumber(4, 3, 2, (1, "a"), ())

@test v"2+" == VersionNumber(2, 0, 0, (), ("",))
@test v"3.2+" == VersionNumber(3, 2, 0, (), ("",))
@test v"4.3.2+" == VersionNumber(4, 3, 2, (), ("",))

@test v"2+1" == VersionNumber(2, 0, 0, (), (1,))
@test v"3.2+1" == VersionNumber(3, 2, 0, (), (1,))
@test v"4.3.2+1" == VersionNumber(4, 3, 2, (), (1,))

@test v"2+a" == VersionNumber(2, 0, 0, (), ("a",))
@test v"3.2+a" == VersionNumber(3, 2, 0, (), ("a",))
@test v"4.3.2+a" == VersionNumber(4, 3, 2, (), ("a",))

@test v"2+a1" == VersionNumber(2, 0, 0, (), ("a1",))
@test v"3.2+a1" == VersionNumber(3, 2, 0, (), ("a1",))
@test v"4.3.2+a1" == VersionNumber(4, 3, 2, (), ("a1",))

@test v"2+1a" == VersionNumber(2, 0, 0, (), ("1a",))
@test v"3.2+1a" == VersionNumber(3, 2, 0, (), ("1a",))
@test v"4.3.2+1a" == VersionNumber(4, 3, 2, (), ("1a",))

@test v"2+a.1" == VersionNumber(2, 0, 0, (), ("a", 1))
@test v"3.2+a.1" == VersionNumber(3, 2, 0, (), ("a", 1))
@test v"4.3.2+a.1" == VersionNumber(4, 3, 2, (), ("a", 1))

@test v"2+1.a" == VersionNumber(2, 0, 0, (), (1, "a"))
@test v"3.2+1.a" == VersionNumber(3, 2, 0, (), (1, "a"))
@test v"4.3.2+1.a" == VersionNumber(4, 3, 2, (), (1, "a"))

# ArgumentErrors in constructor
@test_throws ArgumentError VersionNumber(4, 3, 2, ("nonalphanumeric!",), ())
@test_throws ArgumentError VersionNumber(4, 3, 2, ("nonalphanumeric!", 1), ())
@test_throws ArgumentError VersionNumber(4, 3, 2, (1, "nonalphanumeric!"), ())

@test_throws ArgumentError VersionNumber(4, 3, 2, ("", 1), ())
@test_throws ArgumentError VersionNumber(4, 3, 2, (1, ""), ())
@test_throws ArgumentError VersionNumber(4, 3, 2, ("",), ("",))
@test_throws ArgumentError VersionNumber(4, 3, 2, ("",), ("nonempty", 1))

@test_throws ArgumentError VersionNumber(4, 3, 2, (), ("nonalphanumeric!",))
@test_throws ArgumentError VersionNumber(4, 3, 2, (), ("nonalphanumeric!", 1))
@test_throws ArgumentError VersionNumber(4, 3, 2, (), (1, "nonalphanumeric!"))

@test_throws ArgumentError VersionNumber(4, 3, 2, (), ("", 1))

# show
io = IOBuffer()
show(io,v"4.3.2+1.a")
@test length(String(take!(io))) == 12

# conversion from Int
@test convert(VersionNumber, 2) == v"2.0.0"

# conversion from Tuple
@test convert(VersionNumber, (2,)) == v"2.0.0"
@test convert(VersionNumber, (3, 2)) == v"3.2.0"

# conversion from AbstractString
@test convert(VersionNumber, "4.3.2+1.a") == v"4.3.2+1.a"

# typemin and typemax
@test typemin(VersionNumber) == v"0-"
@test typemax(VersionNumber) ==
  VersionNumber(typemax(Int), typemax(Int), typemax(Int), (), ("",))

# issupbuild
import Base.issupbuild
@test issupbuild(v"4.3.2+")
@test ~issupbuild(v"4.3.2")
@test ~issupbuild(v"4.3.2-")
@test ~issupbuild(v"4.3.2-a")
@test ~issupbuild(v"4.3.2-a1")
@test ~issupbuild(v"4.3.2-1")
@test ~issupbuild(v"4.3.2-a.1")
@test ~issupbuild(v"4.3.2-1a")
@test ~issupbuild(v"4.3.2+a")
@test ~issupbuild(v"4.3.2+a1")
@test ~issupbuild(v"4.3.2+1")
@test ~issupbuild(v"4.3.2+a.1")
@test ~issupbuild(v"4.3.2+1a")

# basic comparison
VersionNumber(2, 3, 1) == VersionNumber(Int8(2), UInt32(3), Int32(1)) == v"2.3.1"
@test v"2.3.0" < v"2.3.1" < v"2.4.8" < v"3.7.2"
@test v"0.6.0-" < v"0.6.0-dev" < v"0.6.0-dev.123" < v"0.6.0-dev.unknown" < v"0.6.0-pre" < v"0.6.0"

#lowerbound and upperbound
import Base: lowerbound, upperbound
@test lowerbound(v"4.3.2") == v"4.3.2-"
@test lowerbound(v"4.3.2-") == v"4.3.2-"
@test lowerbound(v"4.3.2+") == v"4.3.2-"
@test upperbound(v"4.3.2") == v"4.3.2+"
@test upperbound(v"4.3.2-") == v"4.3.2+"
@test upperbound(v"4.3.2+") == v"4.3.2+"

# advanced comparison & manipulation
import Base: thispatch, thisminor, thismajor,
             nextpatch, nextminor, nextmajor, check_new_version
@test v"1.2.3" == thispatch(v"1.2.3-")
@test v"1.2.3" == thispatch(v"1.2.3-pre")
@test v"1.2.3" == thispatch(v"1.2.3")
@test v"1.2.3" == thispatch(v"1.2.3+post")
@test v"1.2.3" == thispatch(v"1.2.3+")

@test v"1.2" == thisminor(v"1.2.3-")
@test v"1.2" == thisminor(v"1.2.3-pre")
@test v"1.2" == thisminor(v"1.2.3")
@test v"1.2" == thisminor(v"1.2.3+post")
@test v"1.2" == thisminor(v"1.2.3+")

@test v"1" == thismajor(v"1.2.3-")
@test v"1" == thismajor(v"1.2.3-pre")
@test v"1" == thismajor(v"1.2.3")
@test v"1" == thismajor(v"1.2.3+post")
@test v"1" == thismajor(v"1.2.3+")

@test v"1.2.3" == nextpatch(v"1.2.3-")
@test v"1.2.3" == nextpatch(v"1.2.3-pre")
@test v"1.2.4" == nextpatch(v"1.2.3")
@test v"1.2.4" == nextpatch(v"1.2.3+post")
@test v"1.2.4" == nextpatch(v"1.2.3+")

@test v"1.2" == nextminor(v"1.2-")
@test v"1.2" == nextminor(v"1.2-pre")
@test v"1.3" == nextminor(v"1.2")
@test v"1.3" == nextminor(v"1.2+post")
@test v"1.3" == nextminor(v"1.2+")

@test v"1.3" == nextminor(v"1.2.3-")
@test v"1.3" == nextminor(v"1.2.3-pre")
@test v"1.3" == nextminor(v"1.2.3")
@test v"1.3" == nextminor(v"1.2.3+post")
@test v"1.3" == nextminor(v"1.2.3+")

@test v"1" == nextmajor(v"1-")
@test v"1" == nextmajor(v"1-pre")
@test v"2" == nextmajor(v"1")
@test v"2" == nextmajor(v"1+post")
@test v"2" == nextmajor(v"1+")

@test v"2" == nextmajor(v"1.2-")
@test v"2" == nextmajor(v"1.2-pre")
@test v"2" == nextmajor(v"1.2")
@test v"2" == nextmajor(v"1.2+post")
@test v"2" == nextmajor(v"1.2+")

@test v"2" == nextmajor(v"1.2.3-")
@test v"2" == nextmajor(v"1.2.3-pre")
@test v"2" == nextmajor(v"1.2.3")
@test v"2" == nextmajor(v"1.2.3+post")
@test v"2" == nextmajor(v"1.2.3+")

for major=0:3, minor=0:3, patch=0:3
    a = VersionNumber(major,minor,patch,("",),())
    b = VersionNumber(major,minor,patch,("pre",),())
    c = VersionNumber(major,minor,patch,(),())
    d = VersionNumber(major,minor,patch,(),("post",))
    e = VersionNumber(major,minor,patch,(),("",))
    @test a < b < c < d < e
    for x in [a,b,c,d,e]
        @test thispatch(x) == VersionNumber(major,minor,patch)
        @test thisminor(x) == VersionNumber(major,minor,0)
        @test thismajor(x) == VersionNumber(major,0,0)
        @test x < nextpatch(x) <= nextminor(x) <= nextmajor(x)
        @test x < thispatch(x) ? nextpatch(x) == thispatch(x) : thispatch(x) < nextpatch(x)
        @test x < thisminor(x) ? nextminor(x) == thisminor(x) : thisminor(x) < nextminor(x)
        @test x < thismajor(x) ? nextmajor(x) == thismajor(x) : thismajor(x) < nextmajor(x)
    end
end

# check_new_version
import Base.check_new_version
@test check_new_version([v"1", v"2"], v"3") === nothing
@test_throws AssertionError check_new_version([v"2", v"1"], v"3")
@test_throws ErrorException check_new_version([v"1", v"2"], v"2")
@test check_new_version(VersionNumber[], v"0") === nothing
@test check_new_version(VersionNumber[], v"0.0.1") === nothing
@test_throws ErrorException check_new_version(VersionNumber[], v"0.0.2")
@test check_new_version(VersionNumber[], v"0.1") === nothing
@test_throws ErrorException check_new_version(VersionNumber[], v"0.2")
@test check_new_version(VersionNumber[], v"1") === nothing
@test_throws ErrorException check_new_version(VersionNumber[], v"2")
@test_throws ErrorException check_new_version(VersionNumber[v"1", v"2", v"3"], v"2")
@test_throws ErrorException check_new_version([v"1", v"2"], v"4")
@test_throws ErrorException check_new_version([v"1", v"2"], v"2-rc")
@test check_new_version([v"1", v"2"], v"2.0.1") === nothing
@test check_new_version([v"1", v"2"], v"2.1") === nothing
@test check_new_version([v"1", v"2"], v"3") === nothing

# banner
import Base.banner
io = IOBuffer()
@test banner(io) === nothing
@test length(String(take!(io))) > 50

# julia_version.h version test
@test VERSION.major == ccall(:jl_ver_major, Cint, ())
@test VERSION.minor == ccall(:jl_ver_minor, Cint, ())
@test VERSION.patch == ccall(:jl_ver_patch, Cint, ())

# test construction with non-Int and non-String components
@test_throws MethodError VersionNumber()
@test VersionNumber(true) == v"1"
@test VersionNumber(true, 0x2) == v"1.2"
@test VersionNumber(true, 0x2, Int128(3)) == v"1.2.3"
@test VersionNumber(true, 0x2, Int128(3)) == v"1.2.3"
@test VersionNumber(true, 0x2, Int128(3), (GenericString("rc"), 0x1)) == v"1.2.3-rc.1"
@test VersionNumber(true, 0x2, Int128(3), (GenericString("rc"), 0x1)) == v"1.2.3-rc.1"
@test VersionNumber(true, 0x2, Int128(3), (), (GenericString("sp"), 0x2)) == v"1.2.3+sp.2"


text:
include("../utils.jl")
include("group_utils.jl")

@testset "Translation action" begin
    M = Euclidean(2,3)
    G = TranslationGroup(2,3)
    A = TranslationAction(Euclidean(2,3), G)

    @test repr(A) == "TranslationAction($(repr(M)), $(repr(G)), LeftAction())"
    @test repr(switch_direction(A)) == "TranslationAction($(repr(M)), $(repr(G)), RightAction())"

    types_a = [
        Matrix{Float64},
    ]

    types_m = [
        Matrix{Float64},
    ]

    @test g_manifold(A) == M
    @test base_group(A) == G
    @test base_manifold(G) == M

    for (T_A, T_M) in zip(types_a, types_m)
        a_pts = convert.(T_A, [[0.0 1.0 2.0; 2.0 4.0 1.0], [-1.0 0.0 2.0; -2.0 3.0 3.0], [1.0 1.0 2.0; 3.0 2.0 1.0]])
        m_pts = convert.(T_M, [[0.0 1.0 2.0; 2.0 4.0 1.0], [-1.0 0.0 2.0; -2.0 3.0 3.0], [1.0 1.0 2.0; 3.0 2.0 1.0]])
        v_pts = convert.(T_M, [[0.0 1.0 2.0; 2.0 4.0 1.0], [-1.0 0.0 2.0; -2.0 3.0 3.0], [1.0 1.0 2.0; 3.0 2.0 1.0]])

        atol = if eltype(T_M) == Float32
            1e-7
        else
            1e-15
        end
        @test apply_diff(A, a_pts[1], m_pts[1], v_pts[1]) === v_pts[1]
        @test inverse_apply_diff(A, a_pts[1], m_pts[1], v_pts[1]) === v_pts[1]
        test_action(A, a_pts, m_pts, v_pts;
            test_optimal_alignment = false,
            test_diff = true,
            atol = atol)
    end

end


text:
getoutputlength(version::Int32, x::Integer) = version < FEATHER_VERSION ? x : padding(x)

function validatefile(filename::AbstractString, data::AbstractVector{UInt8})
    if length(data) < MIN_FILE_LENGTH
        throw(ArgumentError("'$file' is not in feather format: total length of file: $(length(data))"))
    end
    header = data[1:4]
    footer = data[(end-3):end]
    if header ≠ FEATHER_MAGIC_BYTES || footer ≠ FEATHER_MAGIC_BYTES
        throw(ArgumentError(string("'$filename' is not in feather format: header = $header, ",
            "footer = $footer.")))
    end
end

function loadfile(filename::AbstractString; use_mmap::Bool=true)
    isfile(filename) || throw(ArgumentError("'$filename' is not a valid file."))
    data = use_mmap ? Mmap.mmap(filename) : read(filename)
    validatefile(filename, data)
    data
end

function metalength(data::AbstractVector{UInt8})
    read(IOBuffer(data[(length(data)-7):(length(data)-4)]), Int32)
end

function metaposition(data::AbstractVector{UInt8}, metalen::Integer=metalength(data))
    length(data) - (metalen+7)
end

function rootposition(data::AbstractVector{UInt8}, mpos::Integer=metaposition(data))
    read(IOBuffer(data[mpos:(mpos+4)]), Int32)
end

function getctable(data::AbstractVector{UInt8})
    metapos = metaposition(data)
    rootpos = rootposition(data, metapos)
    ctable = FlatBuffers.read(Metadata.CTable, data, metapos + rootpos - 1)
    if ctable.version < FEATHER_VERSION
        @warn("This feather file is old and may not be readable.")
    end
    ctable
end


text:
export BoltzmannPolicy

"Boltzmann policy with softmax action noise."
struct BoltzmannPolicy{P <: PolicySolution, R <: AbstractRNG} <: PolicySolution
    policy::P
    temperature::Float64
    rng::R
end

BoltzmannPolicy(policy, temperature) =
    BoltzmannPolicy(policy, temperature, Random.GLOBAL_RNG)

"Convert vector of scores to probabiities."
function softmax(scores)
    ws = exp.(scores .- maximum(scores))
    z = sum(ws)
    return isnan(z) ? ones(length(scores)) ./ length(scores) : ws ./ z
end

get_action(sol::BoltzmannPolicy, state::State) =
    rand_action(sol, state)
best_action(sol::BoltzmannPolicy, state::State) =
    best_action(sol.policy, state)
get_value(sol::BoltzmannPolicy, state::State) =
    get_value(sol.policy, state)
get_value(sol::BoltzmannPolicy, state::State, action::Term) =
    get_value(sol.policy, state, action)
get_action_values(sol::BoltzmannPolicy, state::State) =
    get_action_values(sol.policy, state)

unzip_pairs(ps::AbstractDict) = unzip_pairs(collect(ps))
unzip_pairs(ps::AbstractArray{<:Pair}) = first.(ps), last.(ps)

function rand_action(sol::BoltzmannPolicy, state::State)
    actions, q_values = unzip_pairs(get_action_values(sol, state))
    if sol.temperature == 0
        probs = zeros(length(actions))
        probs[argmax(q_values)] = 1.0
    else
        probs = softmax(q_values ./ sol.temperature)
    end
    return sample(sol.rng, actions, Weights(probs, 1.0))
end


text:
# Automatically generated using Clang.jl

const RS2_API_MAJOR_VERSION = 2
const RS2_API_MINOR_VERSION = 31
const RS2_API_PATCH_VERSION = 0
const RS2_API_BUILD_VERSION = 0

# Skipping MacroDefinition: STRINGIFY ( arg ) # arg
# Skipping MacroDefinition: VAR_ARG_STRING ( arg ) STRINGIFY ( arg )
# Skipping MacroDefinition: RS2_API_VERSION ( ( ( RS2_API_MAJOR_VERSION ) * 10000 ) + ( ( RS2_API_MINOR_VERSION ) * 100 ) + ( RS2_API_PATCH_VERSION ) )
# Skipping MacroDefinition: RS2_API_VERSION_STR ( VAR_ARG_STRING ( RS2_API_MAJOR_VERSION . RS2_API_MINOR_VERSION . RS2_API_PATCH_VERSION ) )

struct STDepthControlGroup
    plusIncrement::UInt32
    minusDecrement::UInt32
    deepSeaMedianThreshold::UInt32
    scoreThreshA::UInt32
    scoreThreshB::UInt32
    textureDifferenceThreshold::UInt32
    textureCountThreshold::UInt32
    deepSeaSecondPeakThreshold::UInt32
    deepSeaNeighborThreshold::UInt32
    lrAgreeThreshold::UInt32
end

struct STRsm
    rsmBypass::UInt32
    diffThresh::Cfloat
    sloRauDiffThresh::Cfloat
    removeThresh::UInt32
end

struct STRauSupportVectorControl
    minWest::UInt32
    minEast::UInt32
    minWEsum::UInt32
    minNorth::UInt32
    minSouth::UInt32
    minNSsum::UInt32
    uShrink::UInt32
    vShrink::UInt32
end

struct STColorControl
    disableSADColor::UInt32
    disableRAUColor::UInt32
    disableSLORightColor::UInt32
    disableSLOLeftColor::UInt32
    disableSADNormalize::UInt32
end

struct STRauColorThresholdsControl
    rauDiffThresholdRed::UInt32
    rauDiffThresholdGreen::UInt32
    rauDiffThresholdBlue::UInt32
end

struct STSloColorThresholdsControl
    diffThresholdRed::UInt32
    diffThresholdGreen::UInt32
    diffThresholdBlue::UInt32
end

struct STSloPenaltyControl
    sloK1Penalty::UInt32
    sloK2Penalty::UInt32
    sloK1PenaltyMod1::UInt32
    sloK2PenaltyMod1::UInt32
    sloK1PenaltyMod2::UInt32
    sloK2PenaltyMod2::UInt32
end

struct STHdad
    lambdaCensus::Cfloat
    lambdaAD::Cfloat
    ignoreSAD::UInt32
end

struct STColorCorrection
    colorCorrection1::Cfloat
    colorCorrection2::Cfloat
    colorCorrection3::Cfloat
    colorCorrection4::Cfloat
    colorCorrection5::Cfloat
    colorCorrection6::Cfloat
    colorCorrection7::Cfloat
    colorCorrection8::Cfloat
    colorCorrection9::Cfloat
    colorCorrection10::Cfloat
    colorCorrection11::Cfloat
    colorCorrection12::Cfloat
end

struct STAEControl
    meanIntensitySetPoint::UInt32
end

struct STDepthTableControl
    depthUnits::UInt32
    depthClampMin::Int32
    depthClampMax::Int32
    disparityMode::UInt32
    disparityShift::Int32
end

struct STCensusRadius
    uDiameter::UInt32
    vDiameter::UInt32
end

struct STAFactor
    amplitude::Cfloat
end

const RS2_DEFAULT_TIMEOUT = 15000
const RS2_PRODUCT_LINE_ANY = Float32(0x0f)
const RS2_PRODUCT_LINE_ANY_INTEL = 0xfe
const RS2_PRODUCT_LINE_NON_INTEL = 0x01
const RS2_PRODUCT_LINE_D400 = 0x02
const RS2_PRODUCT_LINE_SR300 = 0x04
const RS2_PRODUCT_LINE_L500 = 0x08
const RS2_PRODUCT_LINE_T200 = 0x10
const RS2_PRODUCT_LINE_DEPTH = (RS2_PRODUCT_LINE_L500 | RS2_PRODUCT_LINE_SR300) | RS2_PRODUCT_LINE_D400
const RS2_PRODUCT_LINE_TRACKING = RS2_PRODUCT_LINE_T200
const RS2_UNSIGNED_UPDATE_MODE_UPDATE = 0
const RS2_UNSIGNED_UPDATE_MODE_READ_ONLY = 1
const RS2_UNSIGNED_UPDATE_MODE_FULL = 2

@cenum rs2_timestamp_domain::UInt32 begin
    RS2_TIMESTAMP_DOMAIN_HARDWARE_CLOCK = 0
    RS2_TIMESTAMP_DOMAIN_SYSTEM_TIME = 1
    RS2_TIMESTAMP_DOMAIN_GLOBAL_TIME = 2
    RS2_TIMESTAMP_DOMAIN_COUNT = 3
end

@cenum rs2_frame_metadata_value::UInt32 begin
    RS2_FRAME_METADATA_FRAME_COUNTER = 0
    RS2_FRAME_METADATA_FRAME_TIMESTAMP = 1
    RS2_FRAME_METADATA_SENSOR_TIMESTAMP = 2
    RS2_FRAME_METADATA_ACTUAL_EXPOSURE = 3
    RS2_FRAME_METADATA_GAIN_LEVEL = 4
    RS2_FRAME_METADATA_AUTO_EXPOSURE = 5
    RS2_FRAME_METADATA_WHITE_BALANCE = 6
    RS2_FRAME_METADATA_TIME_OF_ARRIVAL = 7
    RS2_FRAME_METADATA_TEMPERATURE = 8
    RS2_FRAME_METADATA_BACKEND_TIMESTAMP = 9
    RS2_FRAME_METADATA_ACTUAL_FPS = 10
    RS2_FRAME_METADATA_FRAME_LASER_POWER = 11
    RS2_FRAME_METADATA_FRAME_LASER_POWER_MODE = 12
    RS2_FRAME_METADATA_EXPOSURE_PRIORITY = 13
    RS2_FRAME_METADATA_EXPOSURE_ROI_LEFT = 14
    RS2_FRAME_METADATA_EXPOSURE_ROI_RIGHT = 15
    RS2_FRAME_METADATA_EXPOSURE_ROI_TOP = 16
    RS2_FRAME_METADATA_EXPOSURE_ROI_BOTTOM = 17
    RS2_FRAME_METADATA_BRIGHTNESS = 18
    RS2_FRAME_METADATA_CONTRAST = 19
    RS2_FRAME_METADATA_SATURATION = 20
    RS2_FRAME_METADATA_SHARPNESS = 21
    RS2_FRAME_METADATA_AUTO_WHITE_BALANCE_TEMPERATURE = 22
    RS2_FRAME_METADATA_BACKLIGHT_COMPENSATION = 23
    RS2_FRAME_METADATA_HUE = 24
    RS2_FRAME_METADATA_GAMMA = 25
    RS2_FRAME_METADATA_MANUAL_WHITE_BALANCE = 26
    RS2_FRAME_METADATA_POWER_LINE_FREQUENCY = 27
    RS2_FRAME_METADATA_LOW_LIGHT_COMPENSATION = 28
    RS2_FRAME_METADATA_FRAME_EMITTER_MODE = 29
    RS2_FRAME_METADATA_FRAME_LED_POWER = 30
    RS2_FRAME_METADATA_COUNT = 31
end

@cenum rs2_recording_mode::UInt32 begin
    RS2_RECORDING_MODE_BLANK_FRAMES = 0
    RS2_RECORDING_MODE_COMPRESSED = 1
    RS2_RECORDING_MODE_BEST_QUALITY = 2
    RS2_RECORDING_MODE_COUNT = 3
end

@cenum rs2_stream::UInt32 begin
    RS2_STREAM_ANY = 0
    RS2_STREAM_DEPTH = 1
    RS2_STREAM_COLOR = 2
    RS2_STREAM_INFRARED = 3
    RS2_STREAM_FISHEYE = 4
    RS2_STREAM_GYRO = 5
    RS2_STREAM_ACCEL = 6
    RS2_STREAM_GPIO = 7
    RS2_STREAM_POSE = 8
    RS2_STREAM_CONFIDENCE = 9
    RS2_STREAM_COUNT = 10
end

@cenum rs2_format::UInt32 begin
    RS2_FORMAT_ANY = 0
    RS2_FORMAT_Z16 = 1
    RS2_FORMAT_DISPARITY16 = 2
    RS2_FORMAT_XYZ32F = 3
    RS2_FORMAT_YUYV = 4
    RS2_FORMAT_RGB8 = 5
    RS2_FORMAT_BGR8 = 6
    RS2_FORMAT_RGBA8 = 7
    RS2_FORMAT_BGRA8 = 8
    RS2_FORMAT_Y8 = 9
    RS2_FORMAT_Y16 = 10
    RS2_FORMAT_RAW10 = 11
    RS2_FORMAT_RAW16 = 12
    RS2_FORMAT_RAW8 = 13
    RS2_FORMAT_UYVY = 14
    RS2_FORMAT_MOTION_RAW = 15
    RS2_FORMAT_MOTION_XYZ32F = 16
    RS2_FORMAT_GPIO_RAW = 17
    RS2_FORMAT_6DOF = 18
    RS2_FORMAT_DISPARITY32 = 19
    RS2_FORMAT_Y10BPACK = 20
    RS2_FORMAT_DISTANCE = 21
    RS2_FORMAT_MJPEG = 22
    RS2_FORMAT_Y8I = 23
    RS2_FORMAT_Y12I = 24
    RS2_FORMAT_INZI = 25
    RS2_FORMAT_INVI = 26
    RS2_FORMAT_W10 = 27
    RS2_FORMAT_COUNT = 28
end

@cenum rs2_distortion::UInt32 begin
    RS2_DISTORTION_NONE = 0
    RS2_DISTORTION_MODIFIED_BROWN_CONRADY = 1
    RS2_DISTORTION_INVERSE_BROWN_CONRADY = 2
    RS2_DISTORTION_FTHETA = 3
    RS2_DISTORTION_BROWN_CONRADY = 4
    RS2_DISTORTION_KANNALA_BRANDT4 = 5
    RS2_DISTORTION_COUNT = 6
end

struct rs2_intrinsics
    width::Cint
    height::Cint
    ppx::Cfloat
    ppy::Cfloat
    fx::Cfloat
    fy::Cfloat
    model::rs2_distortion
    coeffs::NTuple{5, Cfloat}
end

struct rs2_video_stream
    type::rs2_stream
    index::Cint
    uid::Cint
    width::Cint
    height::Cint
    fps::Cint
    bpp::Cint
    fmt::rs2_format
    intrinsics::rs2_intrinsics
end

struct rs2_motion_device_intrinsic
    data::NTuple{3, NTuple{4, Cfloat}}
    noise_variances::NTuple{3, Cfloat}
    bias_variances::NTuple{3, Cfloat}
end

struct rs2_motion_stream
    type::rs2_stream
    index::Cint
    uid::Cint
    fps::Cint
    fmt::rs2_format
    intrinsics::rs2_motion_device_intrinsic
end

struct rs2_pose_stream
    type::rs2_stream
    index::Cint
    uid::Cint
    fps::Cint
    fmt::rs2_format
end

const rs2_time_t = Cdouble
const rs2_stream_profile = Cvoid

struct rs2_software_video_frame
    pixels::Ptr{Cvoid}
    deleter::Ptr{Cvoid}
    stride::Cint
    bpp::Cint
    timestamp::rs2_time_t
    domain::rs2_timestamp_domain
    frame_number::Cint
    profile::Ptr{rs2_stream_profile}
end

struct rs2_software_motion_frame
    data::Ptr{Cvoid}
    deleter::Ptr{Cvoid}
    timestamp::rs2_time_t
    domain::rs2_timestamp_domain
    frame_number::Cint
    profile::Ptr{rs2_stream_profile}
end

struct rs2_software_pose_frame
    data::Ptr{Cvoid}
    deleter::Ptr{Cvoid}
    timestamp::rs2_time_t
    domain::rs2_timestamp_domain
    frame_number::Cint
    profile::Ptr{rs2_stream_profile}
end

@cenum rs2_option::UInt32 begin
    RS2_OPTION_BACKLIGHT_COMPENSATION = 0
    RS2_OPTION_BRIGHTNESS = 1
    RS2_OPTION_CONTRAST = 2
    RS2_OPTION_EXPOSURE = 3
    RS2_OPTION_GAIN = 4
    RS2_OPTION_GAMMA = 5
    RS2_OPTION_HUE = 6
    RS2_OPTION_SATURATION = 7
    RS2_OPTION_SHARPNESS = 8
    RS2_OPTION_WHITE_BALANCE = 9
    RS2_OPTION_ENABLE_AUTO_EXPOSURE = 10
    RS2_OPTION_ENABLE_AUTO_WHITE_BALANCE = 11
    RS2_OPTION_VISUAL_PRESET = 12
    RS2_OPTION_LASER_POWER = 13
    RS2_OPTION_ACCURACY = 14
    RS2_OPTION_MOTION_RANGE = 15
    RS2_OPTION_FILTER_OPTION = 16
    RS2_OPTION_CONFIDENCE_THRESHOLD = 17
    RS2_OPTION_EMITTER_ENABLED = 18
    RS2_OPTION_FRAMES_QUEUE_SIZE = 19
    RS2_OPTION_TOTAL_FRAME_DROPS = 20
    RS2_OPTION_AUTO_EXPOSURE_MODE = 21
    RS2_OPTION_POWER_LINE_FREQUENCY = 22
    RS2_OPTION_ASIC_TEMPERATURE = 23
    RS2_OPTION_ERROR_POLLING_ENABLED = 24
    RS2_OPTION_PROJECTOR_TEMPERATURE = 25
    RS2_OPTION_OUTPUT_TRIGGER_ENABLED = 26
    RS2_OPTION_MOTION_MODULE_TEMPERATURE = 27
    RS2_OPTION_DEPTH_UNITS = 28
    RS2_OPTION_ENABLE_MOTION_CORRECTION = 29
    RS2_OPTION_AUTO_EXPOSURE_PRIORITY = 30
    RS2_OPTION_COLOR_SCHEME = 31
    RS2_OPTION_HISTOGRAM_EQUALIZATION_ENABLED = 32
    RS2_OPTION_MIN_DISTANCE = 33
    RS2_OPTION_MAX_DISTANCE = 34
    RS2_OPTION_TEXTURE_SOURCE = 35
    RS2_OPTION_FILTER_MAGNITUDE = 36
    RS2_OPTION_FILTER_SMOOTH_ALPHA = 37
    RS2_OPTION_FILTER_SMOOTH_DELTA = 38
    RS2_OPTION_HOLES_FILL = 39
    RS2_OPTION_STEREO_BASELINE = 40
    RS2_OPTION_AUTO_EXPOSURE_CONVERGE_STEP = 41
    RS2_OPTION_INTER_CAM_SYNC_MODE = 42
    RS2_OPTION_STREAM_FILTER = 43
    RS2_OPTION_STREAM_FORMAT_FILTER = 44
    RS2_OPTION_STREAM_INDEX_FILTER = 45
    RS2_OPTION_EMITTER_ON_OFF = 46
    RS2_OPTION_ZERO_ORDER_POINT_X = 47
    RS2_OPTION_ZERO_ORDER_POINT_Y = 48
    RS2_OPTION_LLD_TEMPERATURE = 49
    RS2_OPTION_MC_TEMPERATURE = 50
    RS2_OPTION_MA_TEMPERATURE = 51
    RS2_OPTION_HARDWARE_PRESET = 52
    RS2_OPTION_GLOBAL_TIME_ENABLED = 53
    RS2_OPTION_APD_TEMPERATURE = 54
    RS2_OPTION_ENABLE_MAPPING = 55
    RS2_OPTION_ENABLE_RELOCALIZATION = 56
    RS2_OPTION_ENABLE_POSE_JUMPING = 57
    RS2_OPTION_ENABLE_DYNAMIC_CALIBRATION = 58
    RS2_OPTION_DEPTH_OFFSET = 59
    RS2_OPTION_LED_POWER = 60
    RS2_OPTION_ZERO_ORDER_ENABLED = 61
    RS2_OPTION_ENABLE_MAP_PRESERVATION = 62
    RS2_OPTION_COUNT = 63
end

@cenum rs2_sr300_visual_preset::UInt32 begin
    RS2_SR300_VISUAL_PRESET_SHORT_RANGE = 0
    RS2_SR300_VISUAL_PRESET_LONG_RANGE = 1
    RS2_SR300_VISUAL_PRESET_BACKGROUND_SEGMENTATION = 2
    RS2_SR300_VISUAL_PRESET_GESTURE_RECOGNITION = 3
    RS2_SR300_VISUAL_PRESET_OBJECT_SCANNING = 4
    RS2_SR300_VISUAL_PRESET_FACE_ANALYTICS = 5
    RS2_SR300_VISUAL_PRESET_FACE_LOGIN = 6
    RS2_SR300_VISUAL_PRESET_GR_CURSOR = 7
    RS2_SR300_VISUAL_PRESET_DEFAULT = 8
    RS2_SR300_VISUAL_PRESET_MID_RANGE = 9
    RS2_SR300_VISUAL_PRESET_IR_ONLY = 10
    RS2_SR300_VISUAL_PRESET_COUNT = 11
end

@cenum rs2_rs400_visual_preset::UInt32 begin
    RS2_RS400_VISUAL_PRESET_CUSTOM = 0
    RS2_RS400_VISUAL_PRESET_DEFAULT = 1
    RS2_RS400_VISUAL_PRESET_HAND = 2
    RS2_RS400_VISUAL_PRESET_HIGH_ACCURACY = 3
    RS2_RS400_VISUAL_PRESET_HIGH_DENSITY = 4
    RS2_RS400_VISUAL_PRESET_MEDIUM_DENSITY = 5
    RS2_RS400_VISUAL_PRESET_REMOVE_IR_PATTERN = 6
    RS2_RS400_VISUAL_PRESET_COUNT = 7
end

@cenum rs2_playback_status::UInt32 begin
    RS2_PLAYBACK_STATUS_UNKNOWN = 0
    RS2_PLAYBACK_STATUS_PLAYING = 1
    RS2_PLAYBACK_STATUS_PAUSED = 2
    RS2_PLAYBACK_STATUS_STOPPED = 3
    RS2_PLAYBACK_STATUS_COUNT = 4
end

const rs2_playback_status_changed_callback_ptr = Ptr{Cvoid}

@cenum rs2_camera_info::UInt32 begin
    RS2_CAMERA_INFO_NAME = 0
    RS2_CAMERA_INFO_SERIAL_NUMBER = 1
    RS2_CAMERA_INFO_FIRMWARE_VERSION = 2
    RS2_CAMERA_INFO_RECOMMENDED_FIRMWARE_VERSION = 3
    RS2_CAMERA_INFO_PHYSICAL_PORT = 4
    RS2_CAMERA_INFO_DEBUG_OP_CODE = 5
    RS2_CAMERA_INFO_ADVANCED_MODE = 6
    RS2_CAMERA_INFO_PRODUCT_ID = 7
    RS2_CAMERA_INFO_CAMERA_LOCKED = 8
    RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR = 9
    RS2_CAMERA_INFO_PRODUCT_LINE = 10
    RS2_CAMERA_INFO_ASIC_SERIAL_NUMBER = 11
    RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID = 12
    RS2_CAMERA_INFO_COUNT = 13
end

struct rs2_extrinsics
    rotation::NTuple{9, Cfloat}
    translation::NTuple{3, Cfloat}
end

@cenum rs2_notification_category::UInt32 begin
    RS2_NOTIFICATION_CATEGORY_FRAMES_TIMEOUT = 0
    RS2_NOTIFICATION_CATEGORY_FRAME_CORRUPTED = 1
    RS2_NOTIFICATION_CATEGORY_HARDWARE_ERROR = 2
    RS2_NOTIFICATION_CATEGORY_HARDWARE_EVENT = 3
    RS2_NOTIFICATION_CATEGORY_UNKNOWN_ERROR = 4
    RS2_NOTIFICATION_CATEGORY_FIRMWARE_UPDATE_RECOMMENDED = 5
    RS2_NOTIFICATION_CATEGORY_POSE_RELOCALIZATION = 6
    RS2_NOTIFICATION_CATEGORY_COUNT = 7
end

@cenum rs2_exception_type::UInt32 begin
    RS2_EXCEPTION_TYPE_UNKNOWN = 0
    RS2_EXCEPTION_TYPE_CAMERA_DISCONNECTED = 1
    RS2_EXCEPTION_TYPE_BACKEND = 2
    RS2_EXCEPTION_TYPE_INVALID_VALUE = 3
    RS2_EXCEPTION_TYPE_WRONG_API_CALL_SEQUENCE = 4
    RS2_EXCEPTION_TYPE_NOT_IMPLEMENTED = 5
    RS2_EXCEPTION_TYPE_DEVICE_IN_RECOVERY_MODE = 6
    RS2_EXCEPTION_TYPE_IO = 7
    RS2_EXCEPTION_TYPE_COUNT = 8
end

struct rs2_vertex
    xyz::NTuple{3, Cfloat}
end

struct rs2_pixel
    ij::NTuple{2, Cint}
end

struct rs2_vector
    x::Cfloat
    y::Cfloat
    z::Cfloat
end

struct rs2_quaternion
    x::Cfloat
    y::Cfloat
    z::Cfloat
    w::Cfloat
end

struct rs2_pose
    translation::rs2_vector
    velocity::rs2_vector
    acceleration::rs2_vector
    rotation::rs2_quaternion
    angular_velocity::rs2_vector
    angular_acceleration::rs2_vector
    tracker_confidence::UInt32
    mapper_confidence::UInt32
end

@cenum rs2_log_severity::UInt32 begin
    RS2_LOG_SEVERITY_DEBUG = 0
    RS2_LOG_SEVERITY_INFO = 1
    RS2_LOG_SEVERITY_WARN = 2
    RS2_LOG_SEVERITY_ERROR = 3
    RS2_LOG_SEVERITY_FATAL = 4
    RS2_LOG_SEVERITY_NONE = 5
    RS2_LOG_SEVERITY_COUNT = 6
end

@cenum rs2_extension::UInt32 begin
    RS2_EXTENSION_UNKNOWN = 0
    RS2_EXTENSION_DEBUG = 1
    RS2_EXTENSION_INFO = 2
    RS2_EXTENSION_MOTION = 3
    RS2_EXTENSION_OPTIONS = 4
    RS2_EXTENSION_VIDEO = 5
    RS2_EXTENSION_ROI = 6
    RS2_EXTENSION_DEPTH_SENSOR = 7
    RS2_EXTENSION_VIDEO_FRAME = 8
    RS2_EXTENSION_MOTION_FRAME = 9
    RS2_EXTENSION_COMPOSITE_FRAME = 10
    RS2_EXTENSION_POINTS = 11
    RS2_EXTENSION_DEPTH_FRAME = 12
    RS2_EXTENSION_ADVANCED_MODE = 13
    RS2_EXTENSION_RECORD = 14
    RS2_EXTENSION_VIDEO_PROFILE = 15
    RS2_EXTENSION_PLAYBACK = 16
    RS2_EXTENSION_DEPTH_STEREO_SENSOR = 17
    RS2_EXTENSION_DISPARITY_FRAME = 18
    RS2_EXTENSION_MOTION_PROFILE = 19
    RS2_EXTENSION_POSE_FRAME = 20
    RS2_EXTENSION_POSE_PROFILE = 21
    RS2_EXTENSION_TM2 = 22
    RS2_EXTENSION_SOFTWARE_DEVICE = 23
    RS2_EXTENSION_SOFTWARE_SENSOR = 24
    RS2_EXTENSION_DECIMATION_FILTER = 25
    RS2_EXTENSION_THRESHOLD_FILTER = 26
    RS2_EXTENSION_DISPARITY_FILTER = 27
    RS2_EXTENSION_SPATIAL_FILTER = 28
    RS2_EXTENSION_TEMPORAL_FILTER = 29
    RS2_EXTENSION_HOLE_FILLING_FILTER = 30
    RS2_EXTENSION_ZERO_ORDER_FILTER = 31
    RS2_EXTENSION_RECOMMENDED_FILTERS = 32
    RS2_EXTENSION_POSE = 33
    RS2_EXTENSION_POSE_SENSOR = 34
    RS2_EXTENSION_WHEEL_ODOMETER = 35
    RS2_EXTENSION_GLOBAL_TIMER = 36
    RS2_EXTENSION_UPDATABLE = 37
    RS2_EXTENSION_UPDATE_DEVICE = 38
    RS2_EXTENSION_L500_DEPTH_SENSOR = 39
    RS2_EXTENSION_TM2_SENSOR = 40
    RS2_EXTENSION_AUTO_CALIBRATED_DEVICE = 41
    RS2_EXTENSION_COUNT = 42
end

@cenum rs2_matchers::UInt32 begin
    RS2_MATCHER_DI = 0
    RS2_MATCHER_DI_C = 1
    RS2_MATCHER_DLR_C = 2
    RS2_MATCHER_DLR = 3
    RS2_MATCHER_DIC = 4
    RS2_MATCHER_DIC_C = 5
    RS2_MATCHER_DEFAULT = 6
    RS2_MATCHER_COUNT = 7
end

const rs2_device_info = Cvoid
const rs2_device = Cvoid
const rs2_error = Cvoid
const rs2_raw_data_buffer = Cvoid
const rs2_frame = Cvoid
const rs2_frame_queue = Cvoid
const rs2_pipeline = Cvoid
const rs2_pipeline_profile = Cvoid
const rs2_config = Cvoid
const rs2_device_list = Cvoid
const rs2_stream_profile_list = Cvoid
const rs2_processing_block_list = Cvoid
const rs2_frame_callback = Cvoid
const rs2_log_callback = Cvoid
const rs2_syncer = Cvoid
const rs2_device_serializer = Cvoid
const rs2_source = Cvoid
const rs2_processing_block = Cvoid
const rs2_frame_processor_callback = Cvoid
const rs2_playback_status_changed_callback = Cvoid
const rs2_update_progress_callback = Cvoid
const rs2_context = Cvoid
const rs2_device_hub = Cvoid
const rs2_sensor_list = Cvoid
const rs2_sensor = Cvoid
const rs2_options = Cvoid
const rs2_options_list = Cvoid
const rs2_devices_changed_callback = Cvoid
const rs2_notification = Cvoid
const rs2_notifications_callback = Cvoid
const rs2_notification_callback_ptr = Ptr{Cvoid}
const rs2_devices_changed_callback_ptr = Ptr{Cvoid}
const rs2_frame_callback_ptr = Ptr{Cvoid}
const rs2_frame_processor_callback_ptr = Ptr{Cvoid}
const rs2_update_progress_callback_ptr = Ptr{Cvoid}
const rs2_metadata_type = Clonglong


text:
module Tools

prompt(msg, yes::Bool = false) = prompt(stdin, msg, yes)

function prompt(io::IO, msg, yes::Bool = false)
    print(msg)

    if yes
        println(" Yes.")
    else
        print(" [Y/n] ")
        run(`stty raw`)
        input = read(io, Char)
        run(`stty cooked`)
        println()
        input in ['Y', 'y', '\n', '\r'] || return false
    end

    return true
end

end


text:
# Copyright (c) 2013 Jasper den Ouden, under the MIT license,
# see doc/mit.txt from the project directory.

using Treekenize

#Generates a random tree into stdout and returns the same list for later comparison.
function rnd_tree(to_stream::IOStream, p::Number,  depth::Integer,max_len::Integer, begin_end)
    list = {}
    if depth<0
        return {}
    end
    for i = 1:rand(1:max_len)
        if rand() < p #deepen
            j = rand(1:length(begin_end)) #Random 'parentheses'.
            b,e = begin_end[j]
            write(to_stream, b)
            push!(list, rnd_tree(to_stream,p, depth-1,max_len,begin_end))
            write(to_stream, e)
        else
            x = rand()
            push!(list,x)
            write(to_stream, "$x ") #Just spaced out random numbers.
            for i = 1:rand(1:10)
                write(to_stream, " ")
            end
        end
    end
    return list
end

function rnd_tree(p::Number,  depth::Integer,max_len::Integer, begin_end)
    stream = memio()
    tree = rnd_tree(stream, p,depth,max_len, begin_end)
    write(stream, ";\n");
    seek(stream,0) #Back to the beginning.
    println(readall(stream))
    println(tree)
end

function test_treekenize(p::Number,  depth::Integer,max_len::Integer,
                         begin_end, max_be_len::Integer)
    stream = memio()
    tree = rnd_tree(stream, p,depth,max_len, begin_end)

    write(stream, ";\n");
    seek(stream,0) #Back to the beginning.
    read_tree = treekenize(stream, (begin_end, none_incorrect(begin_end)),
                           ("top",";\n"),10, max_be_len)

    compare_tree(tree, compare::StrExpr) = compare_tree(tree, compare.body)
    function compare_tree(tree, compare)
        list = {}
        for el in compare
            if isa(el, String)
                for sel in split(el," ")
                    if sel!=""
                        push!(list, parsefloat(sel))
                    end
                end
            else
                push!(list, el)
            end
        end
        #ignore compare(hmm maybe that should exist..)
        assert(length(tree)==length(list), (tree,list))
        for i = 1:length(tree)
            if isa(list[i], Number)
                assert( tree[i]==list[i] )
            else
                compare_tree(tree[i], list[i])
            end
        end
    end
    compare_tree(tree, read_tree)
end

#TODO insert incorrectly placed ending/beginning parentheses and see if
# the checker finds them at the right spots.

function test(cnt::Integer)
    for n = 1:cnt #TODO may want to test a larger variation of beginnings and ends.
        test_treekenize(0.4, 4,2, {("(",")"), ("begin","end"),
                                   ("[","]")},4)
    end
end

#test(100)


text:
# This file is auto-generated by AWSMetadata.jl
using AWS
using AWS.AWSServices: rum
using AWS.Compat
using AWS.UUIDs

"""
    create_app_monitor(domain, name)
    create_app_monitor(domain, name, params::Dict{String,<:Any})

Creates a Amazon CloudWatch RUM app monitor, which collects telemetry data from your
application and sends that data to RUM. The data includes performance and reliability
information such as page load time, client-side errors, and user behavior. You use this
operation only to create a new app monitor. To update an existing app monitor, use
UpdateAppMonitor instead. After you create an app monitor, sign in to the CloudWatch RUM
console to get the JavaScript code snippet to add to your web application. For more
information, see How do I find a code snippet that I've already generated?

# Arguments
- `domain`: The top-level internet domain name for which your application has
  administrative authority.
- `name`: A name for the app monitor.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"AppMonitorConfiguration"`: A structure that contains much of the configuration data for
  the app monitor. If you are using Amazon Cognito for authorization, you must include this
  structure in your request, and it must include the ID of the Amazon Cognito identity pool
  to use for authorization. If you don't include AppMonitorConfiguration, you must set up
  your own authorization method. For more information, see Authorize your application to send
  data to Amazon Web Services. If you omit this argument, the sample rate used for RUM is set
  to 10% of the user sessions.
- `"CwLogEnabled"`: Data collected by RUM is kept by RUM for 30 days and then deleted. This
  parameter specifies whether RUM sends a copy of this telemetry data to Amazon CloudWatch
  Logs in your account. This enables you to keep the telemetry data for more than 30 days,
  but it does incur Amazon CloudWatch Logs charges. If you omit this parameter, the default
  is false.
- `"Tags"`: Assigns one or more tags (key-value pairs) to the app monitor. Tags can help
  you organize and categorize your resources. You can also use them to scope user permissions
  by granting a user permission to access or change only resources with certain tag values.
  Tags don't have any semantic meaning to Amazon Web Services and are interpreted strictly as
  strings of characters.
You can associate as many as 50 tags with an app
  monitor.

For more information, see Tagging
  Amazon Web Services resources.

"""
function create_app_monitor(Domain, Name; aws_config::AbstractAWSConfig=global_aws_config())
    return rum(
        "POST",
        "/appmonitor",
        Dict{String,Any}("Domain" => Domain, "Name" => Name);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_app_monitor(
    Domain,
    Name,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return rum(
        "POST",
        "/appmonitor",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("Domain" => Domain, "Name" => Name), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_app_monitor(name)
    delete_app_monitor(name, params::Dict{String,<:Any})

Deletes an existing app monitor. This immediately stops the collection of data.

# Arguments
- `name`: The name of the app monitor to delete.

"""
function delete_app_monitor(Name; aws_config::AbstractAWSConfig=global_aws_config())
    return rum(
        "DELETE",
        "/appmonitor/$(Name)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_app_monitor(
    Name, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return rum(
        "DELETE",
        "/appmonitor/$(Name)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_app_monitor(name)
    get_app_monitor(name, params::Dict{String,<:Any})

Retrieves the complete configuration information for one app monitor.

# Arguments
- `name`: The app monitor to retrieve information for.

"""
function get_app_monitor(Name; aws_config::AbstractAWSConfig=global_aws_config())
    return rum(
        "GET", "/appmonitor/$(Name)"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function get_app_monitor(
    Name, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return rum(
        "GET",
        "/appmonitor/$(Name)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_app_monitor_data(name, time_range)
    get_app_monitor_data(name, time_range, params::Dict{String,<:Any})

Retrieves the raw performance events that RUM has collected from your web application, so
that you can do your own processing or analysis of this data.

# Arguments
- `name`: The name of the app monitor that collected the data that you want to retrieve.
- `time_range`: A structure that defines the time range that you want to retrieve results
  from.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Filters"`: An array of structures that you can use to filter the results to those that
  match one or more sets of key-value pairs that you specify.
- `"MaxResults"`: The maximum number of results to return in one operation.
- `"NextToken"`: Use the token returned by the previous operation to request the next page
  of results.
"""
function get_app_monitor_data(
    Name, TimeRange; aws_config::AbstractAWSConfig=global_aws_config()
)
    return rum(
        "POST",
        "/appmonitor/$(Name)/data",
        Dict{String,Any}("TimeRange" => TimeRange);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_app_monitor_data(
    Name,
    TimeRange,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return rum(
        "POST",
        "/appmonitor/$(Name)/data",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("TimeRange" => TimeRange), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_app_monitors()
    list_app_monitors(params::Dict{String,<:Any})

Returns a list of the Amazon CloudWatch RUM app monitors in the account.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results to return in one operation.
- `"nextToken"`: Use the token returned by the previous operation to request the next page
  of results.
"""
function list_app_monitors(; aws_config::AbstractAWSConfig=global_aws_config())
    return rum(
        "POST", "/appmonitors"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function list_app_monitors(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return rum(
        "POST",
        "/appmonitors",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_tags_for_resource(resource_arn)
    list_tags_for_resource(resource_arn, params::Dict{String,<:Any})

Displays the tags associated with a CloudWatch RUM resource.

# Arguments
- `resource_arn`: The ARN of the resource that you want to see the tags of.

"""
function list_tags_for_resource(
    ResourceArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return rum(
        "GET",
        "/tags/$(ResourceArn)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_tags_for_resource(
    ResourceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return rum(
        "GET",
        "/tags/$(ResourceArn)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    put_rum_events(app_monitor_details, batch_id, id, rum_events, user_details)
    put_rum_events(app_monitor_details, batch_id, id, rum_events, user_details, params::Dict{String,<:Any})

Sends telemetry events about your application performance and user behavior to CloudWatch
RUM. The code snippet that RUM generates for you to add to your application includes
PutRumEvents operations to send this data to RUM. Each PutRumEvents operation can send a
batch of events from one user session.

# Arguments
- `app_monitor_details`: A structure that contains information about the app monitor that
  collected this telemetry information.
- `batch_id`: A unique identifier for this batch of RUM event data.
- `id`: The ID of the app monitor that is sending this data.
- `rum_events`: An array of structures that contain the telemetry event data.
- `user_details`: A structure that contains information about the user session that this
  batch of events was collected from.

"""
function put_rum_events(
    AppMonitorDetails,
    BatchId,
    Id,
    RumEvents,
    UserDetails;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return rum(
        "POST",
        "/appmonitors/$(Id)/",
        Dict{String,Any}(
            "AppMonitorDetails" => AppMonitorDetails,
            "BatchId" => BatchId,
            "RumEvents" => RumEvents,
            "UserDetails" => UserDetails,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function put_rum_events(
    AppMonitorDetails,
    BatchId,
    Id,
    RumEvents,
    UserDetails,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return rum(
        "POST",
        "/appmonitors/$(Id)/",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "AppMonitorDetails" => AppMonitorDetails,
                    "BatchId" => BatchId,
                    "RumEvents" => RumEvents,
                    "UserDetails" => UserDetails,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    tag_resource(resource_arn, tags)
    tag_resource(resource_arn, tags, params::Dict{String,<:Any})

Assigns one or more tags (key-value pairs) to the specified CloudWatch RUM resource.
Currently, the only resources that can be tagged app monitors. Tags can help you organize
and categorize your resources. You can also use them to scope user permissions by granting
a user permission to access or change only resources with certain tag values. Tags don't
have any semantic meaning to Amazon Web Services and are interpreted strictly as strings of
characters. You can use the TagResource action with a resource that already has tags. If
you specify a new tag key for the resource, this tag is appended to the list of tags
associated with the alarm. If you specify a tag key that is already associated with the
resource, the new tag value that you specify replaces the previous value for that tag. You
can associate as many as 50 tags with a resource. For more information, see Tagging Amazon
Web Services resources.

# Arguments
- `resource_arn`: The ARN of the CloudWatch RUM resource that you're adding tags to.
- `tags`: The list of key-value pairs to associate with the resource.

"""
function tag_resource(ResourceArn, Tags; aws_config::AbstractAWSConfig=global_aws_config())
    return rum(
        "POST",
        "/tags/$(ResourceArn)",
        Dict{String,Any}("Tags" => Tags);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function tag_resource(
    ResourceArn,
    Tags,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return rum(
        "POST",
        "/tags/$(ResourceArn)",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("Tags" => Tags), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    untag_resource(resource_arn, tag_keys)
    untag_resource(resource_arn, tag_keys, params::Dict{String,<:Any})

Removes one or more tags from the specified resource.

# Arguments
- `resource_arn`: The ARN of the CloudWatch RUM resource that you're removing tags from.
- `tag_keys`: The list of tag keys to remove from the resource.

"""
function untag_resource(
    ResourceArn, tagKeys; aws_config::AbstractAWSConfig=global_aws_config()
)
    return rum(
        "DELETE",
        "/tags/$(ResourceArn)",
        Dict{String,Any}("tagKeys" => tagKeys);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function untag_resource(
    ResourceArn,
    tagKeys,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return rum(
        "DELETE",
        "/tags/$(ResourceArn)",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("tagKeys" => tagKeys), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    update_app_monitor(name)
    update_app_monitor(name, params::Dict{String,<:Any})

Updates the configuration of an existing app monitor. When you use this operation, only the
parts of the app monitor configuration that you specify in this operation are changed. For
any parameters that you omit, the existing values are kept. You can't use this operation to
change the tags of an existing app monitor. To change the tags of an existing app monitor,
use TagResource. To create a new app monitor, use CreateAppMonitor. After you update an app
monitor, sign in to the CloudWatch RUM console to get the updated JavaScript code snippet
to add to your web application. For more information, see How do I find a code snippet that
I've already generated?

# Arguments
- `name`: The name of the app monitor to update.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"AppMonitorConfiguration"`: A structure that contains much of the configuration data for
  the app monitor. If you are using Amazon Cognito for authorization, you must include this
  structure in your request, and it must include the ID of the Amazon Cognito identity pool
  to use for authorization. If you don't include AppMonitorConfiguration, you must set up
  your own authorization method. For more information, see Authorize your application to send
  data to Amazon Web Services.
- `"CwLogEnabled"`: Data collected by RUM is kept by RUM for 30 days and then deleted. This
  parameter specifies whether RUM sends a copy of this telemetry data to Amazon CloudWatch
  Logs in your account. This enables you to keep the telemetry data for more than 30 days,
  but it does incur Amazon CloudWatch Logs charges.
- `"Domain"`: The top-level internet domain name for which your application has
  administrative authority.
"""
function update_app_monitor(Name; aws_config::AbstractAWSConfig=global_aws_config())
    return rum(
        "PATCH",
        "/appmonitor/$(Name)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_app_monitor(
    Name, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return rum(
        "PATCH",
        "/appmonitor/$(Name)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end


text:
using ExampleRajith
using Test

@testset "my_f" begin
    # 2x + 3y
    @test my_f(2, 1) == 7
    @test my_f(2, 3) == 13
end

@testset "derivative_of_my_f" begin
    @test derivative_of_my_f(2, 1) == 2
end


text:
"""
Hidden Markov Models for Julia.

[Documentation](https://maxmouchet.github.io/HMMBase.jl/stable/).
"""
module HMMBase

using ArgCheck
using Clustering
using Distributions
using LinearAlgebra

import Base: ==, copy, rand, size, OneTo
import Distributions: fit_mle, loglikelihood
import Random: AbstractRNG, GLOBAL_RNG

export
    # hmm.jl
    AbstractHMM,
    HMM,
    copy,
    rand,
    size,
    nparams,
    permute,
    statdists,
    istransmat,
    likelihoods,
    # messages_api.jl
    forward,
    backward,
    posteriors,
    loglikelihood,
    # mle_api.jl
    fit_mle,
    # viterbi_api.jl
    viterbi,
    # utilities.jl,
    gettransmat,
    randtransmat

include("hmm.jl")
include("mle.jl")
include("mle_api.jl")
include("mle_init.jl")
include("messages.jl")
include("messages_api.jl")
include("viterbi.jl")
include("viterbi_api.jl")
include("likelihoods.jl")
include("likelihoods_api.jl")
include("utilities.jl")

# To be removed in a future version
# ---------------------------------

export
    n_parameters,
    log_likelihoods,
    forward_backward,
    messages_backwards,
    messages_backwards_log,
    messages_forwards,
    messages_forwards_log,
    compute_transition_matrix,
    rand_transition_matrix

@deprecate n_parameters(hmm) nparams(hmm)
@deprecate log_likelihoods(hmm, observations) likelihoods(hmm, observations, logl = true)

@deprecate forward_backward(init_distn, trans_matrix, log_likelihoods) posteriors(init_distn, trans_matrix, log_likelihoods, logl = true)
@deprecate messages_forwards(init_distn, trans_matrix, log_likelihoods) forward(init_distn, trans_matrix, log_likelihoods, logl = true)
@deprecate messages_backwards(init_distn, trans_matrix, log_likelihoods) backward(init_distn, trans_matrix, log_likelihoods, logl = true)

@deprecate forward_backward(hmm, observations) posteriors(hmm, observations, logl = true)
@deprecate messages_forwards(hmm, observations) forward(hmm, observations, logl = true)
@deprecate messages_backwards(hmm, observations) backward(hmm, observations, logl = true)

@deprecate messages_forwards_log(init_distn, trans_matrix, log_likelihoods) log.(forward(init_distn, trans_matrix, log_likelihoods, logl = true)[1])
@deprecate messages_backwards_log(trans_matrix, log_likelihoods) log.(backward(init_distn, trans_matrix, log_likelihoods, logl = true)[1])

@deprecate compute_transition_matrix(seq) gettransmat(seq, relabel = true)
@deprecate rand_transition_matrix(K, α = 1.0) randtransmat(K, α)

end


text:
abstract type AbstractSolovevEquilibrium <: AnalyticEquilibrium end

function X(x::AbstractArray{T,1}, equ::AbstractSolovevEquilibrium) where {T <: Number}
    R(x,equ) * cos(ϕ(x,equ))
end

function Y(x::AbstractArray{T,1}, equ::AbstractSolovevEquilibrium) where {T <: Number}
    R(x,equ) * sin(ϕ(x,equ))
end

function Z(x::AbstractArray{T,1}, equ::AbstractSolovevEquilibrium) where {T <: Number}
    x[2] * equ.R₀
end

function R(x::AbstractArray{T,1}, equ::AbstractSolovevEquilibrium) where {T <: Number}
    x[1] * equ.R₀
end

function r(x::AbstractArray{T,1}, equ::AbstractSolovevEquilibrium) where {T <: Number}
    sqrt(r²(x, equ))
end

function r²(x::AbstractArray{T,1}, equ::AbstractSolovevEquilibrium) where {T <: Number}
    (R(x,equ) - equ.R₀)^2 + Z(x,equ)^2
end

function θ(x::AbstractArray{T,1}, equ::AbstractSolovevEquilibrium) where {T <: Number}
    atan2(Z(x,equ), R(x,equ) - equ.R₀)
end

function ϕ(x::AbstractArray{T,1}, equ::AbstractSolovevEquilibrium) where {T <: Number}
    x[3]
end

function J(x::AbstractArray{T,1}, equ::AbstractSolovevEquilibrium) where {T <: Number}
    R(x,equ)
end

function periodicity(x::AbstractArray{T,1}, equ::AbstractSolovevEquilibrium) where {T <: Number}
    p = zero(x)
    p[3] = 2π
    return p
end

function A₁(x::AbstractArray{T,1}, equ::AbstractSolovevEquilibrium) where {T <: Number}
    + equ.B₀ * equ.R₀ * x[2] / x[1] / 2
end

function A₂(x::AbstractArray{T,1}, equ::AbstractSolovevEquilibrium) where {T <: Number}
    - equ.B₀ * equ.R₀ * log(x[1]) / 2
end

function g₁₁(x::AbstractArray{T,1}, equ::AbstractSolovevEquilibrium) where {T <: Number}
    one(T)
end

function g₂₂(x::AbstractArray{T,1}, equ::AbstractSolovevEquilibrium) where {T <: Number}
    one(T)
end

function g₃₃(x::AbstractArray{T,1}, equ::AbstractSolovevEquilibrium) where {T <: Number}
    R(x, equ)^2
end


text:
using Documenter
using CyclicArrays

push!(LOAD_PATH,"../src/")

makedocs(
    sitename = "CyclicArrays",
    format = Documenter.HTML(),
    modules=[CyclicArrays],
    authors="udistr <strobach.ehud@gmail.com>",
    pages = [
    "Home" => "index.md",
    "Main" => "main.md",
    "API Guide" => "API.md"
            ]
)

deploydocs( repo = "github.com/udistr/CyclicArrays.jl.git" )

max_issues_repo_name: udistr/CircularArrays


text:
"""
dist(a, b)

Return the minimum unsigend distance between Intervals a and b.
returns missing if the two intervals do not have the same seqname.
"""
function dist(a::GenomicFeatures.Interval{S},b::GenomicFeatures.Interval{T}) where {S, T}

    a.seqname != b.seqname && return missing
    return minimum(abs.([a.first-b.first, a.first-b.last, a.last-b.first, a.last-b.last]))
end

"""
dist(a,b, f = minimum)

Linearly calculate all the distances between an interval a and a collection b,
return a value according to function f.

# Arguments

- `a::GenomicFeatures.interval{T}`: interval to calculate distances from.
- `b::GenomicFeatures.IntervalCollection{S}`: collection to calculate all distances to.
- `f::Function`: f Summarise all the pairwise distance for a and each interval in b
according to the supplied function f
Currently tested with `minimum`, `maximum`, `mean`, and `median`.
"""
function dist(
    a::GenomicFeatures.Interval{T},
    b::GenomicFeatures.IntervalCollection{S},
    f::Function = minimum
) where {T, S}

    d = Vector{Union{Int, Float64}}(undef,0)
    for interval in b
        tmp_d = dist(a,interval)
        if ismissing(tmp_d)
            continue
        end
        push!(d, tmp_d)
    end
    # Workaround to deal with empty collection
    isempty(d) && return(d)
    return f(d)
end

"""
dist(a, b, f, g)

Lineraly caluclates the distance between collection a and b.
Each distance between a and b is summarised according to f and then summarised
according to g.

# Agruments

- `a::GenomicFeatures.IntervalCollection{T}`: collection a.
- `b::GenomicFeatures.IntervalCollection{S}`: collectionb b.
- `f::Function = x -> x`: f summarisees the result of the distances
between each interval of a and all intervals in b.
tested with `minimum`. 'maximum`, `mean`, `median`
- `g::Function = minimum`: g summarises the distances returned by f for all
items in a. Currently tested with `minimum`. `maximum`, `mean`, and `median`.

# Note

Both g and f can be replaced by user-defined functions. f must take a
Vector{Union{Int, Float64}} and return Union{Int, Float64}.
g must take a Vector{Union{Int, Float64}} but can return any type.
Due to the fact that the result of f is stored in d before being summarised, it
is not possible to change f's return type  -
even if we use a function in g that could acept a vector of that type. Indeed
this is the reason for the need to Union{Int}
"""
function dist(
    a::GenomicFeatures.IntervalCollection{T},
    b::GenomicFeatures.IntervalCollection{S},
    g::Function = x -> x,
    f::Function = minimum
) where {S,T}

    d = Vector{Union{Int, Float64}}(undef,0)
    for interval in a
        tmp_d  =  dist(interval,b, f)
        # deal with ampty collections
        isempty(tmp_d) && continue
        push!(d,tmp_d)
    end
    return g(d)
end


text:
"""
Test script for SD dirBin0Rec0 model_mle: one parameter for total number of links and one for reciprocity
"""

# test sampling

include("...\\..\\..\\..\\..\\add_load_paths.jl")
using StaticNets
using DynNets
using PyPlot

sn = StaticNets
## define parameters
N=30
θ_0 = 1
η_0 = -1.5
T =100

## Sample SD gdp
model_mle = fooSdErgmDirBin0Rec0_mle
indTvPar = trues(2)
B0=0.95
A0 = 0.01
aResGasPar_0 = [[θ_0*(1-B0), B0, A0], [η_0*(1-B0), B0, A0] ]
vResGasPar_0 = DynNets.array_2_vec_all_par(model_mle, aResGasPar_0, indTvPar)
vResGasPar = vResGasPar_0
ftot_0= zeros(Real,2)

fig, ax = subplots(2,1)
for i=1:100
fVecT_dgp , A_T_dgp, sVecT_dgp = score_driven_filter_or_dgp( model_mle,  vResGasPar_0, indTvPar; dgpNT = (N,T))
ax[1].plot(fVecT_dgp[1,:])
ax[1].set_ylim([θ_0 - 5, θ_0 + 5])
ax[2].plot(fVecT_dgp[2,:])
ax[2].set_ylim([η_0 - 5, η_0 + 5])
end

## filter SD
fVecT_dgp , A_T_dgp, sVecT_dgp = score_driven_filter_or_dgp( model_mle,  vResGasPar_0, indTvPar; dgpNT = (N,T))
stats_T_dgp = [stats_from_mat(model_mle, A_T_dgp[:,:,t]) for t in 1:T ]
change_stats_T_dgp = change_stats(model_mle, A_T_dgp)

fVecT_filt , target_fun_val_T, sVecT_filt = score_driven_filter_or_dgp( model_mle,  vResGasPar_0, indTvPar; obsT = stats_T_dgp)
fVecT_filt_p , target_fun_val_T_p, sVecT_filt_p = score_driven_filter_or_dgp( model_mple,  vResGasPar_0, indTvPar; obsT = change_stats_T_dgp)

fig, ax = subplots(2,1)
ax[1].plot(fVecT_filt[1,:], "b")
ax[1].plot(fVecT_filt_p[1,:], "r")
ax[1].plot(fVecT_dgp[1,:], "k")
ax[1].set_ylim([θ_0 - 5, θ_0 + 5])
ax[2].plot(fVecT_filt[2,:], "b")
ax[2].plot(fVecT_filt_p[2,:], "r")
ax[2].plot(fVecT_dgp[2,:], "k")
ax[2].set_ylim([η_0 - 5, η_0 + 5])

## estimate SD
model_mple = fooSdErgmDirBin0Rec0_pmle

indTargPar = indTvPar
fVecT_dgp , A_T_dgp, sVecT_dgp = score_driven_filter_or_dgp( model_mle,  vResGasPar_0, indTvPar; dgpNT = (N,T))
stats_T_dgp = [stats_from_mat(model_mle, A_T_dgp[:,:,t]) for t in 1:T ]
change_stats_T_dgp = change_stats(model_mle, A_T_dgp)

estimate(model_mle; indTvPar=indTvPar, indTargPar=indTargPar, obsT = stats_T_dgp)

estPar_mple, conv_flag,UM_mple , ftot_0_mple = estimate(model_mple; indTvPar=indTvPar, indTargPar=indTargPar, obsT = change_stats_T_dgp)
vResEstPar_mple = DynNets.array_2_vec_all_par(model_mple, estPar_mple, indTvPar)
fVecT_filt_p , target_fun_val_T_p, sVecT_filt_p = score_driven_filter_or_dgp( model_mple,  vResEstPar_mple, indTvPar; obsT = change_stats_T_dgp)

#


text:
"""
    PostStepStrategy

Subtypes of `PostStepStrategy` can be used to perform arbitrary computation on a replica
after an FCIQMC step is finished and report the results.

# Implemented strategies:

* [`ProjectedEnergy`](@ref)
* [`Projector`](@ref)
* [`SignCoherence`](@ref)
* [`WalkerLoneliness`](@ref)
* [`Timer`](@ref)

Note: A tuple of multiple strategies can be passed to [`lomc!`](@ref). In that case, all
reported column names must be distinct.

# Interface:

A subtype of this type must implement [`post_step(::PostStepStrategy, ::ReplicaState)`](@ref).
"""
abstract type PostStepStrategy end

"""
    post_step(::PostStepStrategy, ::ReplicaState) -> kvpairs

Compute statistics after FCIQMC step. Should return a tuple of `:key => value` pairs. See
also [`PostStepStrategy`](@ref).
"""
post_step

# When startegies are a Tuple, apply all of them.
function post_step(t::Tuple{}, replica)
    return ()
end
function post_step((t,ts...)::Tuple, replica)
    head = post_step(t, replica)
    rest = post_step(ts, replica)
    return (head..., rest...)
end

"""
    Projector(name=projector) <: PostStepStrategy

After each step, compute `dot(projector, dv)` and report it in the `DataFrame` under `name`.
`projector` can be an [`AbstractDVec`](@ref), or an [`AbstractProjector`](@ref).
"""
struct Projector{P} <: PostStepStrategy
    name::Symbol
    projector::P
end
function Projector(;kwarg...)
    length(kwarg) ≠ 1 && error("exactly one keyword argument must be passed to `Projector`")
    return Projector(only(keys(kwarg)), freeze(only(values(kwarg))))
end

function post_step(p::Projector, replica)
    return (p.name => dot(p.projector, replica.v),)
end

"""
    ProjectedEnergy(hamiltonian, projector; hproj=:vproj, vproj=:vproj) <: PostStepStrategy

After every step, compute `hproj = dot(projector, hamiltonian, dv)` and `vproj =
dot(projector, dv)`, where `dv` is the instantaneous coefficient vector.  `projector` can be
an [`AbstractDVec`](@ref), or an [`AbstractProjector`](@ref).

Reports to columns `hproj` and `vproj`, which can be used to compute projective energy,
e.g. with [`Rimu.StatsTools.projected_energy`](@ref). The keyword arguments `hproj` and
`vproj` can be used to change the names of these columns. This can be used to make the names
unique when computing projected energies with different projectors in the same run.

See also [`Rimu.StatsTools.ratio_of_means`](@ref),
[`Rimu.StatsTools.mixed_estimator`](@ref).
"""
struct ProjectedEnergy{H,P,Q} <: PostStepStrategy
    vproj_name::Symbol
    hproj_name::Symbol
    ham::H
    vproj::P
    hproj::Q
end

function ProjectedEnergy(
    hamiltonian, projector;
    vproj=:vproj, hproj=:hproj
)
    hproj_vec = compute_hproj(LOStructure(hamiltonian), hamiltonian, projector)
    return ProjectedEnergy(vproj, hproj, hamiltonian, freeze(projector), hproj_vec)
end
function compute_hproj(::AdjointUnknown, hamiltonian, projector)
    @warn "$(typeof(hamiltonian)) has an unknown adjoint. This will be slow."
    return nothing
end
function compute_hproj(::LOStructure, ham, projector)
    return freeze(ham' * projector)
end

function post_step(p::ProjectedEnergy{<:Any,<:Any,Nothing}, replica)
    return (
        p.vproj_name => dot(p.vproj, replica.v),
        p.hproj_name => dot(p.vproj, p.ham, replica.v),
    )
end
function post_step(p::ProjectedEnergy, replica)
    return (
        p.vproj_name => dot(p.vproj, replica.v),
        p.hproj_name => dot(p.hproj, replica.v),
    )
end

"""
    SignCoherence(reference[; name=:coherence]) <: PostStepStrategy

After each step, compute the proportion of configurations that have the same sign as they do
in the `reference_dvec`. Reports to a column named `name`, which defaults to `coherence`.
"""
struct SignCoherence{R} <: PostStepStrategy
    name::Symbol
    reference::R
end
SignCoherence(ref; name=:coherence) = SignCoherence(name, ref)

function post_step(sc::SignCoherence, replica)
    vector = replica.v
    return (sc.name => coherence(valtype(vector), sc.reference, vector),)
end

function coherence(::Type{<:Real}, reference, vector)
    accumulator, overlap = mapreduce(+, pairs(vector); init=MultiScalar(0.0, 0)) do ((k, v))
        ref = reference[k]
        MultiScalar(Float64(sign(ref) * sign(v)), Int(!iszero(ref)))
    end
    return iszero(overlap) ? 0.0 : accumulator / overlap
end
function coherence(::Type{<:Complex}, reference, vector)
    z = MultiScalar(0.0 + 0im, 0)
    accumulator, overlap = mapreduce(+, pairs(vector); init=z) do ((k, v))
        ref = sign(reference[k])
        MultiScalar(
            ComplexF64(sign(real(v)) * sign(ref) + im * sign(imag(v)) * sign(ref)),
            Int(!iszero(ref))
        )
    end
    return iszero(overlap) ? 0.0 : accumulator / overlap
end

"""
    WalkerLoneliness(threshold=1) <: PostStepStrategy

After each step, compute the proportion of configurations that are occupied by at most
`threshold` walkers. Reports to a column named `loneliness`.
"""
struct WalkerLoneliness{T} <: PostStepStrategy
    threshold::T
end
WalkerLoneliness() = WalkerLoneliness(1)

function post_step(wl::WalkerLoneliness, replica)
    vector = replica.v
    return (:loneliness => loneliness(valtype(vector), vector, wl.threshold),)
end

function loneliness(::Type{<:Real}, vector, threshold)
    num_lonely = mapreduce(+, values(vector), init=0) do v
        abs(v) ≤ threshold
    end
    return num_lonely / length(vector)
end

function loneliness(::Type{<:Complex}, vector, threshold)
    num_lonely = mapreduce(+, values(vector), init=0 + 0im) do v
        (abs(real(v)) ≤ threshold) + im*(abs(imag(v)) ≤ threshold)
    end
    return num_lonely / length(vector)
end

"""
    Timer <: PostStepStrategy

Record current time after every step. See [`Base.time`](@ref) for information on what time
is recorded.
"""
struct Timer <: PostStepStrategy end

post_step(::Timer, _) = (:time => time(),)


text:
using Test
using LogicCircuits

# TODO add similar tests for `Trees` as `Graphs`

@test true


text:
using DataFrames: DataFrame
using Tables, FileIO

"""
    writeMDTable(fileName::String, df)

Creates or overwrites a file named as fileName writing in it, under MD table format, the content of any type that implements the [Tables.jl](https://github.com/JuliaData/Tables.jl) interface.
"""
function writeMDTable(fileName::String, df)
    rows = Tables.rows(df)
    sch = Tables.schema(rows)
    names = Tables.columnnames(rows)
    header = true
    open(fileName, "w") do io
        headers::String = ""
        for i in 1:length(names)
            if i != length(names)
                headers = headers * "| $(names[i]) "
            else
                headers = headers * "| $(names[i]) " * "|\n"
            end
        end
        write(io, headers)
    end

    open(fileName, "a") do io
        write(io, "| --- " ^ length(names) * "|\n")
        for row in rows
            line::String = ""
            Tables.eachcolumn(sch, row) do val, i, nm
                line = line * "| $val "
            end
            write(io, line * "|\n")
        end
    end
end

"""
    save(f::File{format"MD"}, df)

Creates or overwrites a file named as fileName writing in it, under MD table format, the content of any type that implements the [Tables.jl](https://github.com/JuliaData/Tables.jl) interface.
"""
function save(f::File{format"MD"}, df)
    writeMDTable(f.filename, df)
end