text:
"""
A collection of methods and submodules useful for computation of quantum sytems.
"""
module QBase

using LinearAlgebra
using Base.Iterators: flatten
using Combinatorics: permutations, combinations
using RandomMatrices: Haar

# Methods extended by QBase.jl
import Base: convert, *, kron, adjoint, show, sqrt
import LinearAlgebra: rank, eigvals

const ATOL = 1e-7

# math utilities
include("math/matrices.jl")
include("math/combinatorics.jl")

# type exports
include("types/probabilities.jl")
include("types/brakets.jl")
include("types/operators.jl")
include("types/states.jl")
include("types/unitaries.jl")
include("types/measurements.jl")

# TODO: Unitary
# TODO: KrausOperator
# TODO: AbstractChannel
# TODO: AbstractSuperOperator
# TODO: AbstractObservable

include("constructors/brakets.jl")
include("constructors/states.jl")
include("constructors/unitaries.jl")
include("constructors/measurements.jl")

# main methods
include("evolve.jl")
include("measure.jl")
include("channels.jl")
include("information.jl")

end


text:
using FileIO, Images, JLD
cd("Examples/Cactus")
# img = load("train/0a1b6731bda8f1b6a807fffc743f8d22.jpg")
# size(img)
# arr = channelview(img)
# size(arr)
#
# arr
#
# arr2 = permuteddimsview(arr, [2, 3, 1])

TRAIN_IMAGES_DIR = "train/"
TEST_IMAGES_DIR = "test/"

function images_in_dir(DIR::String)
    images = String[]
    for file in readdir(DIR)
        if endswith(file, ".jpg")
            push!(images, joinpath(DIR, file))
        end
    end
    return images
end

function load_image(path::String)
    img = load(path)
    arr = channelview(img)
    return (permuteddimsview(arr, [2, 3, 1]))
end

# arr2 = load_image("train/0a1b6731bda8f1b6a807fffc743f8d22.jpg")
# arr2
# arr3 = Array(arr2)
# arr3

train_images = images_in_dir(TRAIN_IMAGES_DIR)
test_images = images_in_dir(TEST_IMAGES_DIR)

# image_files = train_images
# train_X_orig = Array{Float32}(undef, 32, 32, 3, 0)
# train_X_orig = cat(train_X_orig, load_image(train_images[5]), dims=4)
# train_X_orig
# for image_file in image_files
#     global train_X_orig
#     train_X_orig = cat(train_X_orig, load_image(image_file), dims=4)
# end

function load_all_images(paths_vector)
    images_vector = Array{Float32}(undef, 32, 32, 3, 0)
    i = 0
    for image_file in paths_vector
        images_vector = cat(images_vector, load_image(image_file), dims=4)
        i += 1
        if i%100==0
            println(string("Processing image no. ", i))
        end
    end
    return images_vector
end

# train_X_orig = load_all_images(train_images)
# test_X_orig = load_all_images(test_images)
#
# test_X_orig
# save("test_X_orig.jld", "test_X_orig", test_X_orig)
#
# test_X = copy(test_X_orig)
#
# @benchmark load_image($test_images[8])
# @benchmark load_image($test_images[8])
# img2 = load_image(test_images[8])
# cat(test_X, img2, dims=4)
# @benchmark cat($test_X, $img2, dims=4)
# @benchmark cat($randn(100, 10, 10, 10), $randn(100, 10, 10, 10), dims=4)
# @benchmark cat(test_X, load_image(test_images[10]), dims=4)

# paths_vector = test_images
function load_images_parallel(paths_vector, num_bins)
    len = length(paths_vector) # Number of images
    bin_size = floor(UInt, len/num_bins) # Size of each bin
    all_bins = Vector{String}[] # To store image filenames in each bin
    # Create bins of images filenames
    for bin=1:num_bins-1
        paths_bin = paths_vector[(bin-1)*bin_size+1 : bin*bin_size]
        push!(all_bins, paths_bin)
    end
    # Add last bin with all extra images
    push!(all_bins, paths_vector[(num_bins-1)*bin_size+1 : len])
    bins = Vector{Array{Float32, 4}}(undef, num_bins) # To store bins of actual image arrays
    # Load each bin - multithreaded
    Threads.@threads for i = 1:num_bins
        bins[i] = load_all_images(all_bins[i])
    end
    # single array to store all images
    images_array = Array{Float32}(undef, 32, 32, 3, 0)
    # Concatenate all bins into single array
    for bin in bins
        images_array = cat(images_array, bin, dims=4)
    end
    return images_array
end
# test_X_orig_2 = load_images_parallel(test_images, 5)

# @benchmark load_images_parallel($test_images[1:100], 5)
# @benchmark load_images_parallel($test_images[1:100], 20)
# @benchmark load_all_images($test_images[1:100])

test_images = sort(test_images)
train_images = sort(train_images)
test_X_orig = load_images_parallel(test_images, 10)
train_X_orig = load_images_parallel(train_images, 100)
save("dataset.jld", "test_X_orig", test_X_orig, "train_X_orig", train_X_orig)

ext: jl


text:
mutable struct GFExtendState
    prev_trace::GFTrace
    trace::GFTrace
    args_change::Any
    constraints::Any
    score::Float64
    weight::Float64
    visitor::AddressVisitor
    params::Dict{Symbol,Any}
    retchange::Union{Some{Any},Nothing}
    callee_output_changes::HomogenousTrie{Any,Any}
end

function GFExtendState(args_change, prev_trace, constraints, params)
    visitor = AddressVisitor()
    GFExtendState(prev_trace, GFTrace(), args_change, constraints, 0., 0.,
        visitor, params, nothing, HomogenousTrie{Any,Any}())
end

get_args_change(state::GFExtendState) = state.args_change

function set_ret_change!(state::GFExtendState, value)
    if state.retchange === nothing
        state.retchange = value
    else
        lightweight_retchange_already_set_err()
    end
end

function get_addr_change(state::GFExtendState, addr)
    get_leaf_node(state.callee_output_changes, addr)
end

function extend_no_change_err(addr)
    error("Attempted to change value of random choice at $addr during extend")
end

function addr(state::GFExtendState, dist::Distribution{T}, args, addr) where {T}
    visit!(state.visitor, addr)
    has_previous = has_primitive_call(state.prev_trace, addr)
    constrained = has_leaf_node(state.constraints, addr)
    if has_previous && constrained
        extend_no_change_err(addr)
    end
    if has_internal_node(state.constraints, addr)
        lightweight_got_internal_node_err(addr)
    end
    local retval::T
    local call::CallRecord
    if has_previous
        call = get_primitive_call(state.prev_trace, addr)
        if call.args != args
            extend_no_change_err(addr)
        end
        retval = call.retval
        score = call.score
    elseif constrained
        retval = get_leaf_node(state.constraints, addr)
        score = logpdf(dist, retval, args...)
        state.weight += score
        call = CallRecord(score, retval, args)
    else
        retval = random(dist, args...)
        score = logpdf(dist, retval, args...)
        call = CallRecord(score, retval, args)
    end
    state.trace = assoc_primitive_call(state.trace, addr, call)
    state.score += score
    if constrained && has_previous
        # there was a change and this was the previous value
        retchange = (true, prev_call.retval)
    elseif has_previous
        retchange = NoChange()
    else
        # retchange is null, because the address is new
        retchange = nothing
    end
    set_leaf_node!(state.callee_output_changes, addr, retchange)
    retval
end

function addr(state::GFExtendState, gen::Generator{T}, args, addr, args_change) where {T}
    visit!(state.visitor, addr)
    if has_internal_node(state.constraints, addr)
        constraints = get_internal_node(state.constraints, addr)
    elseif has_leaf_node(state.constraints, addr)
        lightweight_got_leaf_node_err(addr)
    else
        constraints = EmptyAssignment()
    end
    if has_subtrace(state.prev_trace, addr)
        prev_trace = get_subtrace(state.prev_trace, addr)
        (trace, weight, retchange) = extend(gen, args, args_change, prev_trace, constraints)
        set_leaf_node!(state.callee_output_changes, addr, retchange)
    else
        (trace, weight) = generate(gen, args, constraints)
    end
    call::CallRecord = get_call_record(trace)
    retval::T = call.retval
    state.trace = assoc_subtrace(state.trace, addr, trace)
    state.score += call.score
    state.weight += weight
    retval
end

function splice(state::GFExtendState, gen::GenFunction, args::Tuple)
    exec(gf, state, args)
end

function extend(gf::GenFunction, args, args_change, trace::GFTrace, constraints)
    state = GFExtendState(args_change, trace, constraints, gf.params)
    retval = exec(gf, state, args)
    call = CallRecord(state.score, retval, args)
    state.trace.call = call
    (state.trace, state.weight, state.retchange)
end

max_stars_repo_name: BoltzmannBrain/Gen

max_issues_repo_name: BoltzmannBrain/Gen

max_forks_repo_name: BoltzmannBrain/Gen


text:
# import sampledata.jl
# test

function test_hexagon()
"""
hexaogon
     3 -- 4
    / ╲  /  ╲
   1 -- 2 -- 5
    ╲  / ╲  /
     7 -- 8
"""
    hexagon_vertices, hexagon_faces = hexagon()
    FEinds, EVinds = get_FEinds_and_EVinds(hexagon_faces)
    assert(size(FEinds,1) == 6)
    assert(size(FEinds,2) == 3)
    assert(size(EVinds,1) == 12)
    assert(size(EVinds,2) == 2)
end
# full(EVinds)

function test_remove_double_vertex()
    test_vertex = [ 1 2; 2 3; 4 1; 2 3; 3 3]
    test_faces = [
        1 3 4;
        4 5 1;
        1 5 4
    ]

    Vs, Is = remove_double_vertexes_alternative(test_vertex)

    for i in 1:size(test_vertex, 1)
        v1 = Vs[Is[i]]
        v2 = test_vertex[i,:]
        assert(v1 == v2)
    end
end


text:
"""
Li, Z., Wang, L., Yang, Y., Du, X. and Song, H., 2019.
Health evaluation of MVB based on SVDD and sample reduction.
IEEE Access, 7, pp.35330-35343.

Density-Based Sample Reduction for Support Vector Data Description (DBSRSVDD)
Parameter guideline from the paper:
min_pts ∈ [5, 6, 7, 8, 9, 10]
eps ∈ [0.5, 1.0]
"""
struct DBSRSVDD <: Sampler
    min_pts::Int
    eps::Real
    function DBSRSVDD(min_pts::Int=7, eps::Real=0.5)
        min_pts > 0 || throw(ArgumentError("Invalid number of min_pts $(min_pts)."))
        eps >= 0 || throw(ArgumentError("Invalid threshold $(eps)."))
        return new(min_pts, eps)
    end
end

function sample(sampler::DBSRSVDD, data::DataSet, labels::Vector{Symbol})::BitArray{1}
    d_ij = Distances.pairwise(Distances.Euclidean(), data, dims=2)
    threshold = sampler.eps * 1 / length(labels)^2 * sum(d_ij)
    c = dbscan(d_ij, threshold, sampler.min_pts)
    sample_mask = c.assignments .== 0
    return sample_mask
end


text:
const DefaultRefType = UInt32

## Pools

# Type params:
# * `T` type of categorized values
# * `R` integer type for referencing category levels
# * `V` categorical value type
mutable struct CategoricalPool{T, R <: Integer, V}
    levels::Vector{T}       # category levels ordered by their reference codes
    invindex::Dict{T, R}    # map from category levels to their reference codes
    valindex::Vector{V}     # "category value" objects 1-to-1 matching `index`
    ordered::Bool

    function CategoricalPool{T, R, V}(levels::Vector{T},
                                      ordered::Bool) where {T, R, V}
        if length(levels) > typemax(R)
            throw(LevelsException{T, R}(levels[Int(typemax(R))+1:end]))
        end
        invindex = Dict{T, R}(v => i for (i, v) in enumerate(levels))
        if length(invindex) != length(levels)
            throw(ArgumentError("Duplicate entries are not allowed in levels"))
        end
        CategoricalPool{T, R, V}(levels, invindex, ordered)
    end
    function CategoricalPool{T, R, V}(invindex::Dict{T, R},
                                      ordered::Bool) where {T, R, V}
        levels = Vector{T}(undef, length(invindex))
        # If invindex contains non consecutive values, a BoundsError will be thrown
        try
            for (k, v) in invindex
                levels[v] = k
            end
        catch BoundsError
            throw(ArgumentError("Reference codes must be in 1:length(invindex)"))
        end
        if length(invindex) > typemax(R)
            throw(LevelsException{T, R}(levels[typemax(R)+1:end]))
        end
        CategoricalPool{T, R, V}(levels, invindex, ordered)
    end
    function CategoricalPool{T, R, V}(levels::Vector{T},
                                      invindex::Dict{T, R},
                                      ordered::Bool) where {T, R, V}
        if T <: CategoricalValue && T !== Union{}
            throw(ArgumentError("Level type $T cannot be a categorical value type"))
        end
        if !(V <: CategoricalValue)
            throw(ArgumentError("Type $V is not a categorical value type"))
        end
        if V !== CategoricalValue{T, R}
            throw(ArgumentError("V must be CategoricalValue{T, R}"))
        end
        valindex = Vector{V}(undef, length(levels))
        pool = new(levels, invindex, valindex, ordered)
        pool.valindex .= CategoricalValue.(1:length(levels), Ref(pool))
        return pool
    end
end

struct LevelsException{T, R} <: Exception
    levels::Vector{T}
end

struct OrderedLevelsException{T, S} <: Exception
    newlevel::S
    levels::Vector{T}
end

## Values

"""
    CategoricalValue{T, R <: Integer}

A wrapper around a value of type `T` corresponding to a level
in a [`CategoricalPool`](@ref).

`CategoricalValue` objects are considered as equal to the value of type `T`
they wrap by `==` and `isequal`.
However, order comparisons like `<` and `isless` are only possible
if [`isordered`](@ref) is `true` for the value's pool, and in that case
the order of the pool's [`levels`](@ref) is used rather than the standard
ordering of values of type `T`.
"""
struct CategoricalValue{T, R <: Integer}
    level::R
    pool::CategoricalPool{T, R, CategoricalValue{T, R}}
end

## Arrays

# Type params:
# * `T` original type of elements before categorization, could be Union{T, Missing}
# * `N` array dimension
# * `R` integer type for referencing category levels
# * `V` original type of elements (excluding Missing) before categorization
# * `C` categorical value type
# * `U` type of missing value, `Union{}` if missing values are not accepted
abstract type AbstractCategoricalArray{T, N, R, V, C, U} <: AbstractArray{Union{C, U}, N} end
const AbstractCategoricalVector{T, R, V, C, U} = AbstractCategoricalArray{T, 1, R, V, C, U}
const AbstractCategoricalMatrix{T, R, V, C, U} = AbstractCategoricalArray{T, 2, R, V, C, U}

mutable struct CategoricalArray{T, N, R <: Integer, V, C, U} <: AbstractCategoricalArray{T, N, R, V, C, U}
    refs::Array{R, N}
    pool::CategoricalPool{V, R, C}

    function CategoricalArray{T, N}(refs::Array{R, N},
                                    pool::CategoricalPool{V, R, C}) where
                                                 {T, N, R <: Integer, V, C}
        T === V || T == Union{V, Missing} || throw(ArgumentError("T ($T) must be equal to $V or Union{$V, Missing}"))
        U = T >: Missing ? Missing : Union{}
        new{T, N, R, V, C, U}(refs, pool)
    end
end
const CategoricalVector{T, R, V, C, U} = CategoricalArray{T, 1, V, C, U}
const CategoricalMatrix{T, R, V, C, U} = CategoricalArray{T, 2, V, C, U}

CatArrOrSub{T, N, R} = Union{CategoricalArray{T, N, R},
                             SubArray{<:Any, N, <:CategoricalArray{T, <:Any, R}}} where
                             {T, N, R<:Integer}


text:
using AnalogDiscovery

function go()
  cDev = enumDevices()
  @show ("Available",cDev)
  myDev = Int32(0)
  if cDev > 0
    if enumDeviceIsOpened(myDev)
      error("Error opening device, already in use.")
    end
    hdwf = deviceOpen(myDev)
  else
    error("No devices available.")
  end

  pfsInput = Ref{Cuint}()
  # Similar to DigitalIO example in Python
  for i in 1:10
    # Enable output/mask on 8 LSB IO pins, from DIO 0 to 7
    digitalIOOutputEnableSet(hdwf, UInt32(0x00FF))
    # Set value on enabled IO pins
    digitalIOOutputSet(hdwf, UInt32(0x12))
    # Fetch digital IO information from the device
    digitalIOStatus(hdwf)
    # Read state of all pins, regardless of output enable
    val = digitalIOInputStatus!(pfsInput,hdwf)
    show(val)
  end

  deviceClose(hdwf)
end

go()


text:
const TRANSFORM_DURATION_DOCS = """
You may pass in a function `f` to transform the duration when computing the cost.
By default it uses `mean`, but for example you can assume everything is worst case using
`path_durations(maximum, proj)`; or you could   compute the path length in terms of number
of tasks using `path_durations(x->1, proj)`.
"""

"""
    path_durations([f=mean], proj::Project)

Compute the duration of every path of tasks with in the project.
They are returned as a vector of pairs: `path => cost`, sorted by cost (descending).
Thus the first is the critical path, and the last is the least critical path.

$TRANSFORM_DURATION_DOCS

See also [`critical_path`](@ref).
"""
path_durations(proj::Project) = path_durations(mean, proj)

function path_durations(f, proj::Project)
    children_lookup = MultiDict(proj.links)

    path_costs = Pair{Vector{Symbol}, Float64}[]
    function inner(path, cost)
        node = path[end]
        if node == :finish
            push!(path_costs, (copy(path) => cost))
            return
        end

        for child in children_lookup[node]
            push!(path, child)
            new_cost = cost + f(proj.task_durations[child])
            inner(path, new_cost)
            pop!(path)  # remove it before we compute the next
        end
    end

    inner([:start], 0.0)

    return sort(path_costs; rev=true, by=last)
end

"""
    critical_path([f=mean], proj::Project)

Computes the critical path though the project.
This is the path who's duration determines the completion time of the project.

$TRANSFORM_DURATION_DOCS

See also [`path_durations`](@ref).
"""
critical_path(args...) = first(path_durations(args...))


text:
module AnalyticalFields

using Gridap
export AnalyticalField

import Gridap: evaluate!
import Gridap: return_size
import Gridap.FieldsOperations: FieldLikeAndGradient

"""
Field generated from an analytical function
"""
struct AnalyticalField{D,T,F<:Function} <: Field{D,T}
  fun::F
end

function AnalyticalField(fun::Function,D::Int,X::Type=Float64)
  h = hasmethod(gradient,(typeof(fun),) )
  _setup(Val(h),fun,D,X)
end

function _setup(::Val{true},fun,D,X)
  gun = gradient(fun)
  v = _AnalyticalField(fun,D,X)
  g = _AnalyticalField(gun,D,X)
  FieldLikeAndGradient(v,g)
end

function _setup(::Val{false},fun,D,X)
  v = _AnalyticalField(fun,D,X)
  v
end

function _AnalyticalField(fun::Function,D::Int,X::Type)
  F = typeof(fun)
  T = Base._return_type(fun,Tuple{Point{D,X}})
  AnalyticalField{D,T,F}(fun)
end

function evaluate!(
  this::AnalyticalField{D,T},
  points::AbstractVector{<:Point{D}},
  v::AbstractVector{T}) where {D,T}
  v .= this.fun.(points)
end

return_size(::AnalyticalField, psize::NTuple{N,Int} where N) = psize

end # module


text:
#
# asian-asciiplot.jl
#
using ASCIIPlots;

S0  = 100;      # Spot price
K   = 102;      # Strike price
r   = 0.05;     # Risk free rate
q   = 0.0;      # Dividend yield
v   = 0.2;      # Volatility
tma = 0.25;     # Time to maturity
T = 100;        # Number of time steps
dt = tma/T;     # Time increment
S = zeros(Float64,T);
S[1] = S0;
dW = randn(T)*sqrt(dt)
[ S[t] = S[t-1] * (1 + (r - q - 0.5*v*v)*dt + v*dW[t] + 0.5*v*v*dW[t]*dW[t]) for t=2:T ]
x = linspace(1,T);
scatterplot(x,S,sym='*')

max_stars_repo_path: Module 3/Chapter01/asian-asciiplot.jl

max_issues_repo_path: Module 3/Chapter01/asian-asciiplot.jl

max_forks_repo_path: Module 3/Chapter01/asian-asciiplot.jl


text:
function TopocentricFrame(arg0::BodyShape, arg1::GeodeticPoint, arg2::JString)
    return TopocentricFrame((BodyShape, GeodeticPoint, JString), arg0, arg1, arg2)
end

function compute_limit_visibility_point(obj::TopocentricFrame, arg0::jdouble, arg1::jdouble, arg2::jdouble)
    return jcall(obj, "computeLimitVisibilityPoint", GeodeticPoint, (jdouble, jdouble, jdouble), arg0, arg1, arg2)
end

function get_azimuth(obj::TopocentricFrame, arg0::FieldVector3D, arg1::Frame, arg2::FieldAbsoluteDate)
    return jcall(obj, "getAzimuth", RealFieldElement, (FieldVector3D, Frame, FieldAbsoluteDate), arg0, arg1, arg2)
end

function get_azimuth(obj::TopocentricFrame, arg0::Vector3D, arg1::Frame, arg2::AbsoluteDate)
    return jcall(obj, "getAzimuth", jdouble, (Vector3D, Frame, AbsoluteDate), arg0, arg1, arg2)
end

function get_east(obj::TopocentricFrame)
    return jcall(obj, "getEast", Vector3D, ())
end

function get_elevation(obj::TopocentricFrame, arg0::FieldVector3D, arg1::Frame, arg2::FieldAbsoluteDate)
    return jcall(obj, "getElevation", RealFieldElement, (FieldVector3D, Frame, FieldAbsoluteDate), arg0, arg1, arg2)
end

function get_elevation(obj::TopocentricFrame, arg0::Vector3D, arg1::Frame, arg2::AbsoluteDate)
    return jcall(obj, "getElevation", jdouble, (Vector3D, Frame, AbsoluteDate), arg0, arg1, arg2)
end

function get_nadir(obj::TopocentricFrame)
    return jcall(obj, "getNadir", Vector3D, ())
end

function get_north(obj::TopocentricFrame)
    return jcall(obj, "getNorth", Vector3D, ())
end

function get_parent_shape(obj::TopocentricFrame)
    return jcall(obj, "getParentShape", BodyShape, ())
end

function get_point(obj::TopocentricFrame)
    return jcall(obj, "getPoint", GeodeticPoint, ())
end

function get_point(obj::TopocentricFrame, arg0::Field)
    return jcall(obj, "getPoint", FieldGeodeticPoint, (Field,), arg0)
end

function get_pv_coordinates(obj::TopocentricFrame, arg0::AbsoluteDate, arg1::Frame)
    return jcall(obj, "getPVCoordinates", TimeStampedPVCoordinates, (AbsoluteDate, Frame), arg0, arg1)
end

function get_range(obj::TopocentricFrame, arg0::FieldVector3D, arg1::Frame, arg2::FieldAbsoluteDate)
    return jcall(obj, "getRange", RealFieldElement, (FieldVector3D, Frame, FieldAbsoluteDate), arg0, arg1, arg2)
end

function get_range(obj::TopocentricFrame, arg0::Vector3D, arg1::Frame, arg2::AbsoluteDate)
    return jcall(obj, "getRange", jdouble, (Vector3D, Frame, AbsoluteDate), arg0, arg1, arg2)
end

function get_range_rate(obj::TopocentricFrame, arg0::FieldPVCoordinates, arg1::Frame, arg2::FieldAbsoluteDate)
    return jcall(obj, "getRangeRate", RealFieldElement, (FieldPVCoordinates, Frame, FieldAbsoluteDate), arg0, arg1, arg2)
end

function get_range_rate(obj::TopocentricFrame, arg0::PVCoordinates, arg1::Frame, arg2::AbsoluteDate)
    return jcall(obj, "getRangeRate", jdouble, (PVCoordinates, Frame, AbsoluteDate), arg0, arg1, arg2)
end

function get_south(obj::TopocentricFrame)
    return jcall(obj, "getSouth", Vector3D, ())
end

function get_west(obj::TopocentricFrame)
    return jcall(obj, "getWest", Vector3D, ())
end

function get_zenith(obj::TopocentricFrame)
    return jcall(obj, "getZenith", Vector3D, ())
end

function point_at_distance(obj::TopocentricFrame, arg0::jdouble, arg1::jdouble, arg2::jdouble)
    return jcall(obj, "pointAtDistance", GeodeticPoint, (jdouble, jdouble, jdouble), arg0, arg1, arg2)
end


text:
using .AdvancedHMC: AdvancedHMC

"""
    RankUpdateEuclideanMetric{T,M} <: AdvancedHMC.AbstractMetric

A Gaussian Euclidean metric whose inverse is constructed by rank-updates.

# Constructors

    RankUpdateEuclideanMetric(n::Int)
    RankUpdateEuclideanMetric(M⁻¹::Pathfinder.WoodburyPDMat)

Construct a Gaussian Euclidean metric of size `(n, n)` with inverse of `M⁻¹`.

# Example

```jldoctest
julia> using LinearAlgebra, Pathfinder, AdvancedHMC

julia> Pathfinder.RankUpdateEuclideanMetric(3)
RankUpdateEuclideanMetric(diag=[1.0, 1.0, 1.0])

julia> W = Pathfinder.WoodburyPDMat(Diagonal([0.1, 0.2]), [0.7 0.2]', Diagonal([0.3]))
2×2 Pathfinder.WoodburyPDMat{Float64, Diagonal{Float64, Vector{Float64}}, Adjoint{Float64, Matrix{Float64}}, Diagonal{Float64, Vector{Float64}}, Diagonal{Float64, Vector{Float64}}, QRCompactWYQ{Float64, Matrix{Float64}, Matrix{Float64}}, UpperTriangular{Float64, Matrix{Float64}}}:
 0.247  0.042
 0.042  0.212

julia> Pathfinder.RankUpdateEuclideanMetric(W)
RankUpdateEuclideanMetric(diag=[0.247, 0.21200000000000002])
```
"""
RankUpdateEuclideanMetric

struct RankUpdateEuclideanMetric{T,M<:WoodburyPDMat{T,<:Diagonal{T}}} <:
       AdvancedHMC.AbstractMetric
    M⁻¹::M
end

function RankUpdateEuclideanMetric(n::Int)
    M⁻¹ = WoodburyPDMat(Diagonal(ones(n)), zeros(n, 0), zeros(0, 0))
    return RankUpdateEuclideanMetric(M⁻¹)
end
function RankUpdateEuclideanMetric(::Type{T}, D::Int) where {T}
    return RankUpdateEuclideanMetric(
        WoodburyPDMat(Diagonal(ones(T, D)), Matrix{T}(undef, D, 0), Matrix{T}(undef, 0, 0))
    )
end
function RankUpdateEuclideanMetric(::Type{T}, sz::Tuple{Int}) where {T}
    return RankUpdateEuclideanMetric(T, first(sz))
end
RankUpdateEuclideanMetric(sz::Tuple{Int}) = RankUpdateEuclideanMetric(Float64, sz)

AdvancedHMC.renew(::RankUpdateEuclideanMetric, M⁻¹) = RankUpdateEuclideanMetric(M⁻¹)

Base.size(metric::RankUpdateEuclideanMetric, dim...) = size(metric.M⁻¹, dim...)

function Base.show(io::IO, metric::RankUpdateEuclideanMetric)
    print(io, "RankUpdateEuclideanMetric(diag=$(diag(metric.M⁻¹)))")
    return nothing
end

function Base.rand(rng::AbstractRNG, metric::RankUpdateEuclideanMetric{T}) where {T}
    M⁻¹ = metric.M⁻¹
    r = randn(rng, T, size(M⁻¹, 2)...)
    invunwhiten!(r, M⁻¹, r)
    return r
end

function AdvancedHMC.neg_energy(
    h::AdvancedHMC.Hamiltonian{<:RankUpdateEuclideanMetric}, r::T, θ::T
) where {T<:AbstractVecOrMat}
    return -PDMats.quad(h.metric.M⁻¹, r) / 2
end

function AdvancedHMC.∂H∂r(
    h::AdvancedHMC.Hamiltonian{<:RankUpdateEuclideanMetric}, r::AbstractVecOrMat
)
    return h.metric.M⁻¹ * r
end


text:
export completions, allcompletions, complete

const builtins = ["abstract", "baremodule", "begin", "bitstype", "break",
                  "catch", "ccall", "const", "continue", "do", "else",
                  "elseif", "end", "export", "finally", "for", "function",
                  "global", "if", "immutable", "import", "importall", "let",
                  "local", "macro", "module", "quote", "return", "try", "type",
                  "typealias", "using", "while"]

if VERSION < v"0.4-"
  macro noinline(ex)
    esc(ex)
  end
end

@noinline identifier_completions(hints = UTF8String[]; textual = true) =
  @d(:hints => hints,
     :pattern => identifier,
     :textual => textual)

function lastcall(scopes)
  for i = length(scopes):-1:1
    scopes[i].kind == :call && return scopes[i].name
  end
end

"""
Takes a block of code and a cursor and returns autocomplete data.
"""
function completions(code, cursor; mod = Main, file = nothing)
  line = precursor(lines(code)[cursor.line], cursor.column)
  scs = scopes(code, cursor)
  sc = scs[end]
  call = lastcall(scs)

  if islatexinput(line)
    @d(:hints => latex_completions,
       :pattern => r"\\[a-zA-Z0-9^_]*",
       :textual => false)
  elseif sc.kind == :using
    pkg_completions(packages())
  elseif call != nothing && (f = getthing(call, mod); haskey(fncompletions, f))
    fncompletions[f](@d(:mod => mod,
                        :file => file,
                        :input => precursor(line, cursor.column)))
  elseif sc.kind in (:string, :multiline_string, :comment, :multiline_comment)
    nothing
  elseif (q = qualifier(line)) != nothing
    thing = getthing(mod, q, nothing)
    if isa(thing, Module)
      identifier_completions((@> thing names(true) filtervalid),
                             textual = false)
    elseif thing != nothing && sc.kind == :toplevel
      identifier_completions((@> thing fieldnames filtervalid),
                             textual = false)
    end
  elseif isnum(line)
    nothing
  else
    identifier_completions(accessible(mod))
  end
end

"""
Takes a file of code and a cursor and returns autocomplete data.
"""
function allcompletions(code, cursor; mod = Main, file = nothing)
  block, _, cursor′ = getblockcursor(code, cursor)
  cs = completions(block, cursor′, mod = mod, file = file)
  cs == nothing && return nothing
  if !haskey(cs, :textual) || cs[:textual]
    ts = tokens(code, cursor)
    hints = cs[:hints]
    for t in ts
      push!(hints, t)
    end
  end
  return cs
end

# Module completions
# ––––––––––––––––––

moduleusings(mod) = ccall(:jl_module_usings, Any, (Any,), mod)

filtervalid(names) = @>> names map(string) filter(x->!ismatch(r"#", x))

accessible(mod::Module) =
  [names(mod, true, true);
   map(names, moduleusings(mod))...;
   builtins] |> unique |> filtervalid

function qualifier(s)
  m = match(Regex("((?:$(identifier.pattern)\\.)+)(?:$(identifier.pattern))?\$"), s)
  m == nothing ? m : m.captures[1]
end

isnum(s) = ismatch(r"(0x[0-9a-zA-Z]*|[0-9]+)$", s)

# Latex completions
# –––––––––––––––––

const tab_length = 8

tabpad(s, ts) = s * "\t"^max((ts - length(s)÷tab_length), 1)

const latex_completions =
  [@d(:completion => completion, :text => tabpad(text, 2) * completion)
   for (text, completion) in Base.REPLCompletions.latex_symbols]

const reverse_latex_commands =
  [first(v) => k for (k, v) in Base.REPLCompletions.latex_symbols]

islatexinput(str::AbstractString) =
  ismatch(r"\\[a-zA-Z0-9_^]*$", str)

# Custom completions
# ––––––––––––––––––

const fncompletions = Dict{Function,Function}()

complete(completions::Function, f::Function) =
  fncompletions[f] = completions

# Include completions
# TODO: cd completions

const pathpattern = r"[a-zA-Z0-9_\.\\/]*"

includepaths(path) =
  @>> dirsnearby(path, ascend = 0) jl_files map(p->p[length(path)+2:end])

includepaths(Pkg.dir("Jewel", "src"))

complete(include) do info
  file = info[:file]
  dir = file == nothing ? pwd() : dirname(file)
  @d(:hints => includepaths(dir),
     :pattern => pathpattern,
     :textual => false)
end

# Package manager completions

packages(dir = Pkg.dir()) =
  @>> dir readdir filter(x->!ismatch(r"^\.|^METADATA$|^REQUIRE$", x))

all_packages() = packages(Pkg.dir("METADATA"))

required_packages() =
  @>> Pkg.dir("REQUIRE") readall lines

unused_packages() = setdiff(all_packages(), required_packages())

@noinline pkg_completions(hints) =
  @d(:hints => hints,
     :pattern => r"[a-zA-Z0-9]*",
     :textual => false)

for f in (Pkg.add, Pkg.clone)
  complete(f) do _
    pkg_completions(unused_packages())
  end
end

for f in (Pkg.checkout, Pkg.free, Pkg.rm, Pkg.publish, Pkg.build, Pkg.test)
  complete(f) do _
    pkg_completions(packages())
  end
end


text:
struct InteractionMatrix
    m11::Float64
    m12::Float64
    m13::Float64
    m21::Float64
    m22::Float64
    m23::Float64
    m31::Float64
    m32::Float64
    m33::Float64
end

function InteractionMatrix()
    return InteractionMatrix(zeros(Float64,9)...)
end

function InteractionMatrix(M::T) where T<:AbstractMatrix
    size(M) == (3,3) || error("Interaction matrix must be of size 3x3")
    m = InteractionMatrix(M[1,1], M[1,2], M[1,3], M[2,1], M[2,2], M[2,3], M[3,1], M[3,2], M[3,3])
    return m
end


text:
using DemoProject
using Test

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


text:
#!/bin/bash
# -*- mode: julia -*-
#=
exec ${JULIA:-julia} --color=yes --startup-file=no "${BASH_SOURCE[0]}" "$@"
=#

module TestPyBase

include("install_python_dependencies.jl")
include("preamble.jl")

@testset "$file" for file in [
        "test_ufcs.jl",
        "test_misc.jl",
        "test_pytest.jl",
        ]
    include(file)
end

end  # module


text:
module CartPoleEnv
# Ported from: https://github.com/openai/gym/blob/996e5115621bf57b34b9b79941e629a36a709ea1/gym/envs/classic_control/cartpole.py
# which has header:
# 		Classic cart-pole system implemented by Rich Sutton et al.
#		Copied from https://webdocs.cs.ualberta.ca/~sutton/book/code/pole.c

using Reinforce: AbstractEnvironment
using LearnBase: DiscreteSet
using RecipesBase
using Random: seed!

import Reinforce: reset!, actions, finished, step!, state

export
  CartPole,
  reset!,
  step!,
  actions,
  finished

const gravity = 9.8
const mass_cart = 1.0
const mass_pole = 0.1
const total_mass = mass_cart + mass_pole
const pole_length = 0.5 # actually half the pole's length
const mass_pole_length = mass_pole * pole_length
const force_mag = 10.0
const τ = 0.02 # seconds between state updates

# angle at which to fail the episode
const θ_threshold = 24π / 360
const x_threshold = 2.4

mutable struct CartPole <: AbstractEnvironment
	state::Vector{Float64}
	reward::Float64
  maxsteps::Int  # max step in each episode
end
CartPole(; maxsteps = 0) = CartPole(0.1rand(4) .- 0.05, 0.0, maxsteps)

# see https://github.com/FluxML/model-zoo/pull/23#issuecomment-366030179
CartPoleV0() = CartPole(maxsteps = 200)
CartPoleV1() = CartPole(maxsteps = 500)

reset!(env::CartPole) = (env.state = 0.1rand(4) .- 0.05; env.reward = 0.0; env)
actions(env::CartPole, s) = DiscreteSet(1:2)
maxsteps(env::CartPole) = env.maxsteps

function step!(env::CartPole, s, a)
  s = state(env)
  x, xvel, θ, θvel = s

  force = (a == 1 ? -1 : 1) * force_mag
  tmp = (force + mass_pole_length * sin(θ) * (θvel^2)) / total_mass
  θacc = (gravity * sin(θ) - tmp * cos(θ)) /
          (pole_length * (4/3 - mass_pole * (cos(θ)^2) / total_mass))
  xacc = tmp - mass_pole_length * θacc * cos(θ) / total_mass

  # update state
  s[1] = x    += τ * xvel
  s[2] = xvel += τ * xacc
  s[3] = θ    += τ * θvel
  s[4] = θvel += τ * θacc

  env.reward = finished(env, s) ? 0.0 : 1.0
  env.reward, s
end

function finished(env::CartPole, s′)
  x, xvel, θ, θvel = s′
  !(-x_threshold <= x <= x_threshold &&
    -θ_threshold <= θ <= θ_threshold)
end

# ------------------------------------------------------------------------

@recipe function f(env::CartPole)
  x, xvel, θ, θvel = state(env)
  legend := false
  xlims := (-x_threshold, x_threshold)
  ylims := (-Inf, 2pole_length)
  grid := false
  ticks := nothing

  # pole
  @series begin
    linecolor := :red
    linewidth := 10
    [x, x + 2pole_length * sin(θ)], [0.0, 2pole_length * cos(θ)]
  end

  # cart
  @series begin
    seriescolor := :black
    seriestype := :shape
    hw = 0.5
    l, r = x-hw, x+hw
    t, b = 0.0, -0.1
    [l, r, r, l], [t, t, b, b]
  end
end

end


text:
module Isotonic

export isotonic_regression,
       isotonic_regression!,
       active_set_isotonic_regression,
       active_set_isotonic_regression!,
       pooled_pava_isotonic_regression,
       pooled_pava_isotonic_regression!

include("linear_pava.jl")
include("active_set.jl")
include("pooled_pava.jl")

end


text:
## Fourier transform for vectors inspired on the ESDL version of the function
## https://github.com/esa-esdl/ESDL.jl/blob/master/src/TSDecomposition.jl

using FFTW: plan_fft!
using Statistics: mean, cov, var
using Distributed: workers, remotecall, fetch, myid

max_stars_repo_name: juanrocha/ESDL

max_issues_repo_name: juanrocha/ESDL

max_forks_repo_name: juanrocha/ESDL


text:
# ------------------------------------------------------------------
# Licensed under the MIT License. See LICENSE in the project root.
# ------------------------------------------------------------------

"""
    PolyArea(outer, [inner1, inner2, ..., innerk]; fix=true)

A polygonal area with `outer` chain, and optional inner
chains `inner1`, `inner2`, ..., `innerk`.

Chains can be a vector of [`Point`](@ref) or a
vector of tuples with coordinates for convenience.

The option `fix` tries to correct issues with polygons
in the real world, including issues with:

* `orientation` - Most algorithms assume that the
  outer ring is oriented counter-clockwise (CCW) and
  that all inner rings are oriented clockwise (CW).

* `degeneracy` - Sometimes data is shared with
  degenerate rings (i.e. only 2 vertices).
"""
struct PolyArea{Dim,T,C<:Chain{Dim,T}} <: Polygon{Dim,T}
  outer::C
  inners::Vector{C}

  function PolyArea{Dim,T,C}(outer, inners, fix) where {Dim,T,C}
    @assert isclosed(outer) "invalid outer chain"
    @assert all(isclosed.(inners)) "invalid inner chains"

    if fix
      # fix orientation
      fix1(c, o) = orientation(c) == o ? c : reverse(c)
      outer  = fix1(outer, :CCW)
      inners = fix1.(inners, :CW)

      # fix degeneracy
      function fix2(c)
        if nvertices(c) == 2
          v = vertices(c)
          A, B = v[1], v[2]
          M = centroid(Segment(v[1], v[2]))
          Chain([A, M, B, A])
        else
          c
        end
      end
      outer  = fix2(outer)
      inners = fix2.(inners)
    end

    new(outer, inners)
  end
end

PolyArea(outer::C, inners=C[]; fix=true) where {Dim,T,V,C<:Chain{Dim,T,V}} =
  PolyArea{Dim,T,Chain{Dim,T,V}}(outer, inners, fix)

PolyArea(outer::AbstractVector{P}, inners=[]; fix=true) where {P<:Point} =
  PolyArea(Chain(outer), [Chain(inner) for inner in inners]; fix=fix)

PolyArea(outer::AbstractVector{TP}, inners=[]; fix=true) where {TP<:Tuple} =
  PolyArea(Point.(outer), [Point.(inner) for inner in inners]; fix=fix)

PolyArea(outer::Vararg{P}; fix=true) where {P<:Point} =
  PolyArea(collect(outer); fix=fix)

PolyArea(outer::Vararg{TP}; fix=true) where {TP<:Tuple} =
  PolyArea(collect(Point.(outer)); fix=fix)

==(p1::PolyArea, p2::PolyArea) =
  p1.outer == p2.outer && p1.inners == p2.inners

function vertices(p::PolyArea{Dim,T}) where {Dim,T}
  vo = vertices(p.outer)
  vi = reduce(vcat, vertices(inner) for inner in p.inners; init=Point{Dim,T}[])
  [vo; vi]
end

nvertices(p::PolyArea) = nvertices(p.outer) + mapreduce(nvertices, +, p.inners, init=0)

centroid(p::PolyArea) = centroid(p.outer)

measure(p::PolyArea) = sum(measure, discretize(p, FIST()))

chains(p::PolyArea) = [p.outer; p.inners]

hasholes(p::PolyArea) = !isempty(p.inners)

issimple(p::PolyArea) = !hasholes(p) && issimple(p.outer)

windingnumber(point::Point, p::PolyArea) =
  windingnumber(point, p.outer)

orientation(p::PolyArea, algo=WindingOrientation()) =
  orientation.([p.outer; p.inners], Ref(algo))

function Base.unique!(p::PolyArea)
  close!(unique!(open!(p.outer)))
  hasholes(p) && foreach(c->close!(unique!(open!(c))), p.inners)
  p
end

function Base.in(point::Point, polyarea::PolyArea)
  sideof(point, polyarea.outer) == :INSIDE &&
  all(sideof(point, inner) == :OUTSIDE for inner in polyarea.inners)
end

function Base.show(io::IO, p::PolyArea)
  nverts = [[npoints(p.outer)]; npoints.(p.inners)]
  chains = join(["$n-chain" for n in nverts], ", ")
  print(io, "PolyArea($chains)")
end

function Base.show(io::IO, ::MIME"text/plain", p::PolyArea{Dim,T}) where {Dim,T}
  nverts = [[npoints(p.outer)]; npoints.(p.inners)]
  chains = ["$n-chain" for n in nverts]
  println(io, "PolyArea{$Dim,$T}")
  if length(chains) == 1
    println(io, "  outer")
    print(io, io_lines(chains[1:1], "    "))
  else
    println(io, "  outer")
    println(io, io_lines(chains[1:1], "    "))
    println(io, "  inner")
    print(io, io_lines(chains[2:end], "    "))
  end
end


text:
module TestIO

using Test, DataFrames, CategoricalArrays, Dates

# Test LaTeX export
@testset "LaTeX export" begin
    df = DataFrame(A = 1:4,
                B = ["\$10.0", "M&F", "A~B", "\\alpha"],
                C = ["A", "B", "C", "S"],
                D = [1.0, 2.0, missing, 3.0],
                E = CategoricalArray(["a", missing, "c", "d"]),
                F = Vector{String}(undef, 4)
                )
    str = """
        \\begin{tabular}{r|cccccc}
        \t& A & B & C & D & E & F\\\\
        \t\\hline
        \t& $(Int) & String & String & Float64? & Cat…? & String\\\\
        \t\\hline
        \t1 & 1 & \\\$10.0 & A & 1.0 & a & \\#undef \\\\
        \t2 & 2 & M\\&F & B & 2.0 &  & \\#undef \\\\
        \t3 & 3 & A\\textasciitilde{}B & C &  & c & \\#undef \\\\
        \t4 & 4 & \\textbackslash{}\\textbackslash{}alpha & S & 3.0 & d & \\#undef \\\\
        \\end{tabular}
        """
    @test repr(MIME("text/latex"), df) == str
    @test repr(MIME("text/latex"), eachcol(df)) == str
    @test repr(MIME("text/latex"), eachrow(df)) == str

    @test_throws ArgumentError DataFrames._show(stdout, MIME("text/latex"),
                                                DataFrame(ones(2,2)), rowid=10)
end

@testset "Huge LaTeX export" begin
    df = DataFrame(a=1:1000)
    ioc = IOContext(IOBuffer(), :displaysize => (10, 10), :limit => false)
    show(ioc, "text/latex", df)
    @test length(String(take!(ioc.io))) > 10000

    ioc = IOContext(IOBuffer(), :displaysize => (10, 10), :limit => true)
    show(ioc, "text/latex", df)
    @test length(String(take!(ioc.io))) < 10000
end

#Test HTML output for IJulia and similar
@testset "HTML output" begin
    df = DataFrame(Fish = ["Suzy", "Amir"], Mass = [1.5, missing])
    io = IOBuffer()
    show(io, "text/html", df)
    str = String(take!(io))
    @test str == "

" *
                 "	Fish	Mass
" *
                 "
	String	Float64?

" *
                 "
2 rows × 2 columns
" *
                 "
1	Suzy	1.5
" *
                 "
2	Amir	missing

"

    df = DataFrame(Fish = Vector{String}(undef, 2), Mass = [1.5, missing])
    io = IOBuffer()
    show(io, "text/html", df)
    str = String(take!(io))
    @test str == "

" *
                 "	Fish	Mass
" *
                 "
	String	Float64?

" *
                 "
2 rows × 2 columns
" *
                 "
1	#undef	1.5
" *
                 "
2	#undef	missing

"

    io = IOBuffer()
    show(io, "text/html", eachrow(df))
    str = String(take!(io))
    @test str == "
2×2 DataFrameRows
" *
                 "

" *
                 "	Fish	Mass
" *
                 "
	String	Float64?

" *
                 "
1	#undef	1.5
" *
                 "
2	#undef	missing

"

    io = IOBuffer()
    show(io, "text/html", eachcol(df))
    str = String(take!(io))
    @test str == "
2×2 DataFrameColumns
" *
                 "

" *
                 "	Fish	Mass
" *
                 "
	String	Float64?

" *
                 "
1	#undef	1.5
" *
                 "
2	#undef	missing

"

    io = IOBuffer()
    show(io, "text/html", df[1, :])
    str = String(take!(io))
    @test str == "
DataFrameRow (2 columns)

" *
                 "

	Fish	Mass

	" *
                 "String	Float64?

1	" *
                 "#undef	1.5

"

    io = IOBuffer()
    show(io, MIME"text/html"(), df, summary=false)
    str = String(take!(io))
    @test str == "

" *
                 "	Fish	Mass
" *
                 "
	String	Float64?

" *
                 "
1	#undef	1.5
" *
                 "
2	#undef	missing

"

    io = IOBuffer()
    show(io, MIME"text/html"(), eachrow(df), summary=false)
    str = String(take!(io))
    @test str == "

" *
                 "	Fish	Mass
" *
                 "
	String	Float64?

" *
                 "
1	#undef	1.5
" *
                 "
2	#undef	missing

"

    io = IOBuffer()
    show(io, MIME"text/html"(), eachcol(df), summary=false)
    str = String(take!(io))
    @test str == "

" *
                 "	Fish	Mass
" *
                 "
	String	Float64?

" *
                 "
1	#undef	1.5
" *
                 "
2	#undef	missing

"

    io = IOBuffer()
    show(io, MIME"text/html"(), df[1, :], summary=false)
    str = String(take!(io))
    @test str == "

	Fish	" *
                 "Mass

	String	Float64?

" *
                 "

1	#undef	1.5

"

    @test_throws ArgumentError DataFrames._show(stdout, MIME("text/html"),
                                                DataFrame(ones(2,2)), rowid=10)
end

# test limit attribute of IOContext is used
@testset "limit attribute" begin
    df = DataFrame(a=1:1000)
    ioc = IOContext(IOBuffer(), :displaysize => (10, 10), :limit => false)
    show(ioc, "text/html", df)
    @test length(String(take!(ioc.io))) > 10000

    ioc = IOContext(IOBuffer(), :displaysize => (10, 10), :limit => true)
    show(ioc, "text/html", df)
    @test length(String(take!(ioc.io))) < 10000
end

@testset "printtable" begin
    df = DataFrame(A = 1:3,
                B = 'a':'c',
                C = ["A", "B", "C"],
                D = CategoricalArray(string.('a':'c')),
                E = CategoricalArray(["A", "B", missing]),
                F = Vector{Union{Int, Missing}}(1:3),
                G = missings(3),
                H = fill(missing, 3))

    @test sprint(DataFrames.printtable, df) ==
        """
        "A","B","C","D","E","F","G","H"
        1,"'a'","A","a","A","1",missing,missing
        2,"'b'","B","b","B","2",missing,missing
        3,"'c'","C","c",missing,"3",missing,missing
        """
end

@testset "csv/tsv output" begin
    df = DataFrame(a = [1,2], b = [1.0, 2.0])

    for x in [df, eachcol(df), eachrow(df)]
        @test sprint(show, "text/csv", x) == """
        "a","b"
        1,1.0
        2,2.0
        """
        @test sprint(show, "text/tab-separated-values", x) == """
        "a"\t"b"
        1\t1.0
        2\t2.0
        """
    end
end

@testset "empty data frame and DataFrameRow" begin
    df = DataFrame(a = [1,2], b = [1.0, 2.0])

    @test sprint(show, "text/csv", df[:, 2:1]) == ""
    @test sprint(show, "text/tab-separated-values", df[:, 2:1]) == ""
    @test sprint(show, "text/html", df[:, 2:1]) ==
          "

" *
          "

0 rows × 0 columns

"
    @test sprint(show, "text/latex", df[:, 2:1]) ==
          "\\begin{tabular}{r|}\n\t& \\\\\n\t\\hline\n\t& \\\\\n\t\\hline\n\\end{tabular}\n"

    @test sprint(show, "text/csv", @view df[:, 2:1]) == ""
    @test sprint(show, "text/tab-separated-values", @view df[:, 2:1]) == ""
    @test sprint(show, "text/html", @view df[:, 2:1]) ==
          "

" *
          "

0 rows × 0 columns

"
    @test sprint(show, "text/latex", @view df[:, 2:1]) ==
          "\\begin{tabular}{r|}\n\t& \\\\\n\t\\hline\n\t& \\\\\n\t\\hline\n\\end{tabular}\n"

    @test sprint(show, "text/csv", df[1, 2:1]) == ""
    @test sprint(show, "text/tab-separated-values", df[1, 2:1]) == ""
    @test sprint(show, "text/html", df[1, 2:1]) ==
          "
DataFrameRow (0 columns)

" *
          "

"
    @test sprint(show, "text/latex", df[1, 2:1]) ==
          "\\begin{tabular}{r|}\n\t& \\\\\n\t\\hline\n\t& \\\\\n\t\\hline\n\\end{tabular}\n"
end

@testset "consistency" begin
    df = DataFrame(a = [1, 1, 2, 2], b = [5, 6, 7, 8], c = 1:4)
    push!(df.c, 5)
    @test_throws AssertionError sprint(show, "text/html", df)
    @test_throws AssertionError sprint(show, "text/latex", df)
    @test_throws AssertionError sprint(show, "text/csv", df)
    @test_throws AssertionError sprint(show, "text/tab-separated-values", df)

    df = DataFrame(a = [1, 1, 2, 2], b = [5, 6, 7, 8], c = 1:4)
    push!(DataFrames._columns(df), df[:, :a])
    @test_throws AssertionError sprint(show, "text/html", df)
    @test_throws AssertionError sprint(show, "text/latex", df)
    @test_throws AssertionError sprint(show, "text/csv", df)
    @test_throws AssertionError sprint(show, "text/tab-separated-values", df)
end

@testset "summary tests" begin
    df = DataFrame(ones(2,3))

    for (v, s) in [(df, "2×3 DataFrame"),
                   (view(df, :, :), "2×3 SubDataFrame"),
                   (df[1, :], "3-element DataFrameRow"),
                   (DataFrames.index(df), "data frame with 3 columns"),
                   (DataFrames.index(df[1:1, 1:1]), "data frame with 1 column"),
                   (DataFrames.index(view(df, 1:1, 1:1)), "data frame with 1 column"),
                   (eachrow(df), "2-element DataFrameRows"),
                   (eachcol(df), "3-element DataFrameColumns")]
        @test summary(v) == s
        io = IOBuffer()
        summary(io, v)
        @test String(take!(io)) == s
    end
end

@testset "eltypes tests" begin
    df = DataFrame(A = Int32.(1:3), B = ["x", "y", "z"])

    io = IOBuffer()
    show(io, MIME("text/plain"), df, eltypes=true)
    str = String(take!(io))
    @test str == """
    3×2 DataFrame
    │ Row │ A     │ B      │
    │     │ Int32 │ String │
    ├─────┼───────┼────────┤
    │ 1   │ 1     │ x      │
    │ 2   │ 2     │ y      │
    │ 3   │ 3     │ z      │"""

    io = IOBuffer()
    show(io, MIME("text/plain"), eachcol(df), eltypes=true)
    str = String(take!(io))
    @test str == """
    3×2 DataFrameColumns
    │ Row │ A     │ B      │
    │     │ Int32 │ String │
    ├─────┼───────┼────────┤
    │ 1   │ 1     │ x      │
    │ 2   │ 2     │ y      │
    │ 3   │ 3     │ z      │"""

    io = IOBuffer()
    show(io, MIME("text/plain"), eachrow(df), eltypes=true)
    str = String(take!(io))
    @test str == """
    3×2 DataFrameRows
    │ Row │ A     │ B      │
    │     │ Int32 │ String │
    ├─────┼───────┼────────┤
    │ 1   │ 1     │ x      │
    │ 2   │ 2     │ y      │
    │ 3   │ 3     │ z      │"""

    io = IOBuffer()
    show(io, MIME("text/plain"), df, eltypes=false)
    str = String(take!(io))
    @test str == """
    3×2 DataFrame
    │ Row │ A │ B │
    ├─────┼───┼───┤
    │ 1   │ 1 │ x │
    │ 2   │ 2 │ y │
    │ 3   │ 3 │ z │"""

    io = IOBuffer()
    show(io, MIME("text/plain"), eachcol(df), eltypes=false)
    str = String(take!(io))
    @test str == """
    3×2 DataFrameColumns
    │ Row │ A │ B │
    ├─────┼───┼───┤
    │ 1   │ 1 │ x │
    │ 2   │ 2 │ y │
    │ 3   │ 3 │ z │"""

    io = IOBuffer()
    show(io, MIME("text/plain"), eachrow(df), eltypes=false)
    str = String(take!(io))
    @test str == """
    3×2 DataFrameRows
    │ Row │ A │ B │
    ├─────┼───┼───┤
    │ 1   │ 1 │ x │
    │ 2   │ 2 │ y │
    │ 3   │ 3 │ z │"""

    io = IOBuffer()
    show(io, MIME("text/html"), df, eltypes=true)
    str = String(take!(io))
    @test str == "

" *
                 "	A	B
" *
                 "
	Int32	String

" *
                 "
3 rows × 2 columns
" *
                 "
1	1	x
" *
                 "
2	2	y

3	3	z

"

    io = IOBuffer()
    show(io, MIME("text/html"), eachcol(df), eltypes=true)
    str = String(take!(io))
    @test str == "
3×2 DataFrameColumns

" *
                 "	A	B
" *
                 "
	Int32	String

" *
                 "
1	1	x
" *
                 "
2	2	y

3	3	z

"

    io = IOBuffer()
    show(io, MIME("text/html"), eachrow(df), eltypes=true)
    str = String(take!(io))
    @test str == "
3×2 DataFrameRows

" *
                 "	A	B
" *
                 "
	Int32	String

" *
                 "
1	1	x
" *
                 "
2	2	y

3	3	z

"

    io = IOBuffer()
    show(io, MIME("text/html"), df, eltypes=false)
    str = String(take!(io))
    @test str == "

" *
                 "	A	B

" *
                 "
3 rows × 2 columns
" *
                 "
1	1	x
" *
                 "
2	2	y

3	3	z

"

    io = IOBuffer()
    show(io, MIME("text/html"), eachcol(df), eltypes=false)
    str = String(take!(io))
    @test str == "
3×2 DataFrameColumns

" *
                 "	A	B

" *
                 "
1	1	x
" *
                 "
2	2	y

3	3	z

"

    io = IOBuffer()
    show(io, MIME("text/html"), eachrow(df), eltypes=false)
    str = String(take!(io))
    @test str == "
3×2 DataFrameRows

" *
                 "	A	B

" *
                 "
1	1	x
" *
                 "
2	2	y

3	3	z

"

    for x in [df, eachcol(df), eachrow(df)]
        io = IOBuffer()
        show(io, MIME("text/latex"), x, eltypes=true)
        str = String(take!(io))
        @test str == """
        \\begin{tabular}{r|cc}
        \t& A & B\\\\
        \t\\hline
        \t& Int32 & String\\\\
        \t\\hline
        \t1 & 1 & x \\\\
        \t2 & 2 & y \\\\
        \t3 & 3 & z \\\\
        \\end{tabular}
        """

        io = IOBuffer()
        show(io, MIME("text/latex"), x, eltypes=false)
        str = String(take!(io))
        @test str == """
        \\begin{tabular}{r|cc}
        \t& A & B\\\\
        \t\\hline
        \t1 & 1 & x \\\\
        \t2 & 2 & y \\\\
        \t3 & 3 & z \\\\
        \\end{tabular}
        """
    end
end

end # module


text:
#julia --project=./ test/runPluto.jl

using TheNumberLine, Pluto
p=dirname(pathof(TheNumberLine))
cd(p)

println("\n Hi There \n")
println("Let's open the Number Line notebook using Pluto.jl")
println("Hit any key to start; then open `src/standard_number_line.jl`\n")
readline();

#Base.run(`open http://localhost:1234`)
Pluto.run()


text:
# LibFTD2XX.jl
#
# Library installation script based on BinaryProvider LibFoo.jl example

using Libdl
using BinaryProvider

verbose = true

prefix = joinpath(@__DIR__, "usr")

if Sys.islinux()
    libnames = ["libftd2xx", "libftd2xx.1.4.4", "libftd2xx.so.1.4.8"]
    products = Product[LibraryProduct(joinpath(prefix, "release", "build"), libnames, :libftd2xx)]
end

if Sys.iswindows()
    if Sys.WORD_SIZE == 64
        libnames = ["ftd2xx64"]
        products = Product[LibraryProduct(joinpath(prefix, "amd64"), libnames, :libftd2xx)]
    else
        libnames = ["ftd2xx"]
        products = Product[LibraryProduct(joinpath(prefix, "i386"), libnames, :libftd2xx)]
    end
end

if Sys.isapple()
    libnames = ["libftd2xx.1.4.4"]
    products = Product[LibraryProduct(joinpath(prefix, "lib"), libnames, :libftd2xx)]
end

bin_prefix = "https://www.ftdichip.com/Drivers"
download_info = Dict(
    Linux(:aarch64, :glibc) => ("$bin_prefix/D2XX/Linux/libftd2xx-arm-v8-1.4.8.gz", "e353cfa94069dee6d5bba1c4d8a19b0fd2bf3db1e8bbe0c3b9534fdfaf7a55ed"),
    Linux(:armv7l, :glibc)  => ("$bin_prefix/D2XX/Linux/libftd2xx-arm-v7-hf-1.4.8.gz", "81c8556184e9532a3a19ee6915c3a43110dc208116967a4d3e159f00db5d16e1"),
    Linux(:i686, :glibc)    => ("$bin_prefix/D2XX/Linux/libftd2xx-i386-1.4.8.gz", "84c9aaf7288a154faf0e2814ba590ec965141c698b2a00bffc94d8e0c7ebeb4c"),
    Linux(:x86_64, :glibc)  => ("$bin_prefix/D2XX/Linux/libftd2xx-x86_64-1.4.8.gz", "815d880c5ec40904f062373e52de07b2acaa428e54fece98b31e6573f5d261a0"),
    MacOS(:x86_64)          => ("$bin_prefix/D2XX/MacOSX/D2XX1.4.4.dmg", "3327e646e71819a48fdbf72c8ced24ba99ad1eec1a609f0e9cbc6dbadd2285b6"),
    Windows(:i686)          => ("$bin_prefix/CDM/CDM%20v2.12.28%20WHQL%20Certified.zip", "82db36f089d391f194c8ad6494b0bf44c508b176f9d3302777c041dad1ef7fe6"),
    Windows(:x86_64)        => ("$bin_prefix/CDM/CDM%20v2.12.28%20WHQL%20Certified.zip", "82db36f089d391f194c8ad6494b0bf44c508b176f9d3302777c041dad1ef7fe6")
)

# First, check to see if we're all satisfied
if any(!satisfied(p; verbose=verbose) for p in products)
    try
        # Download and install binaries
        url, tarball_hash = choose_download(download_info)
        if Sys.islinux()
            install(url, tarball_hash, prefix=Prefix(prefix), force=true, verbose=verbose)
        elseif Sys.iswindows() || Sys.isapple()
            # Explicitly download
            tarball_path = joinpath(Prefix(prefix), "downloads", basename(url))
            download_verify(url, tarball_hash, tarball_path, force=true, verbose=verbose)
            if Sys.iswindows()
                # On windows, manuall unzip as .zip not handled well by BinaryProvider
                exe7z = joinpath(Sys.BINDIR, "7z.exe")
                isfile(exe7z) || error("7z.exe not in $(Sys.BINDIR)")
                run(`$exe7z x $tarball_path -o$prefix`)
            end
            if Sys.isapple()
                # On Mac, extract from disk image
                run(`./build_osx.sh`)
            end
        else
            throw(ArgumentError("Unsupported platform"))
        end
    catch e
        if typeof(e) <: ArgumentError
            error("Your platform $(Sys.MACHINE) is not supported by this package!")
        else
            rethrow(e)
        end
    end

end

# Finally, write out a deps.jl file
write_deps_file(joinpath(@__DIR__, "deps.jl"), products, verbose=verbose)


text:
abstract type Smoothers end
struct RTTSmoother <: Smoothers end
RauchTungStriebel() = RTTSmoother()
struct MBFmoother <: Smoothers end
ModifiedBrysonFrazier() = MBFmoother()

## Rauch Tung Striebel
struct RTSSmoother
	xk::Vector
	P::AbstractMatrix
end

function kalman_smooth(
	s::RTTSmoother,
	x₀::Vector,
	xk::Vector,
	xkp1::Vector,
	Pk::AbstractMatrix,
	Pkp1::AbstractMatrix,
	F::AbstractMatrix,
	)
	A = similar(F)
	mul!(A, Pk, F')
	F = qr(Pkp1)
	A = _return_type(Pk, F.R\(F.q' * A))
	P = Pkp1 .- Pk
    P = Pk .+ _return_type(Pk, A*P*A')
	x̂ = x₀ .- xkp1
	x̂ .= muladd(A, x̂, xk)
    return RTSSmoother(vec(x̂), P)
end

## Modified Bryson–Frazier smoother
struct MBFSmoother
	xk::Vector
	P::AbstractMatrix
	L::AbstractMatrix
	l::Vector
end

function kalman_smooth(
	s::MBFmoother,
	xk::Vector,
	Pk::AbstractMatrix,
	K::AbstractMatrix,
	F::AbstractMatrix,
	H::AbstractMatrix,
	Λ::AbstractMatrix,
	λ::Vector,
	S::AbstractMatrix,
	y::Vector,
	)
	A = _return_type(Pk, muladd(-K, H, eye(length(xk))))
	Aᵀ, Fᵀ = A', F'
	Sqr = qr(S)
	SH = Sqr.R \ (Sqr.Q' * H')
	λ̂ = mul!(similar(λ), Fᵀ, λ)
	Λ̂ = Fᵀ*Λ*F
	x̂ = muladd(Pk, -λ̂, xk)
	P = _return_type(Pk, Pk .- Pk*Λ̂*Pk)
	Λ̂ = muladd(SH, H, Aᵀ*Λ̂*A)
	λ̂ = muladd(Aᵀ, λ̂, -SH*y)
	return MBFSmoother(vec(x̂), P, Λ̂, vec(λ̂))
end


text:
module RoomWindow

using Gtk, Gtk.ShortNames, Gtk.GConstants
using ..Ahorn, Maple

roomWindow = nothing
templateRoom = Maple.Room(name="1")

currentRoom = nothing
minimumRecommended = (320, 184)

# Each line represents a line in window with 4 columns
roomFieldOrder = String[
    "name", "color",
    "x", "y",
    "width", "height",
    "cameraOffsetX", "cameraOffsetY",
    "windPattern", "underwater", "space",
    "disableDownTransition", "checkpoint", "dark", "whisper",
    "musicLayer1", "musicLayer2", "musicLayer3", "musicLayer4",
    "ambienceProgress", "musicProgress",
    "music",
]

dropdownOptions = Dict{String, Any}(
    "music" => sort(collect(keys(Maple.Songs.songs))),
    "altMusic" => sort(collect(keys(Maple.Songs.songs))),
    "windPattern" => sort(Maple.wind_patterns),
    "color" => collect(0:length(Ahorn.colors.background_room_color_coded_fill) - 1)
)

# Symbols reads and sets values on the room, other values are stored in data dict
fields = Dict{String, Any}(
    "checkpoint" => (room, simple) -> findfirst(e -> e.name == "checkpoint", room.entities) != nothing,

    "width" => (room, simple) -> round(Int, room.size[1] / (simple ? 8 : 1)),
    "height" => (room, simple) -> round(Int, room.size[2] / (simple ? 8 : 1)),

    "x" => (room, simple) -> round(Int, room.position[1] / (simple ? 8 : 1)),
    "y" => (room, simple) -> round(Int, room.position[2] / (simple ? 8 : 1)),

    "name" => :name,

    "musicLayer1" => :musicLayer1,
    "musicLayer2" => :musicLayer2,
    "musicLayer3" => :musicLayer3,
    "musicLayer4" => :musicLayer4,

    "dark" => :dark,
    "space" => :space,
    "underwater" => :underwater,
    "whisper" => :whisper,

    "disableDownTransition" => :disableDownTransition,

    "color" => :color,

    "music" => :music,

    "musicProgress" => :musicProgress,
    "ambienceProgress" => :ambienceProgress,

    "windPattern" => :windPattern,

    "cameraOffsetX" => :cameraOffsetX,
    "cameraOffsetY" => :cameraOffsetY
)

function getValue(room::Maple.Room, value::Any, simple::Bool)
    if isa(value, Symbol)
        return getfield(room, value)

    elseif isa(value, Function)
        return value(room, simple)

    else
        return value
    end
end

function getOptions(room::Maple.Room, dropdownOptions::Dict{String, Any}, langdata::Ahorn.LangData, simple::Bool=get(Ahorn.config, "use_simple_room_values", true))
    res = Ahorn.Form.Option[]

    names = get(langdata, :names)
    tooltips = get(langdata, :tooltips)

    for (dataName, symbol) in fields
        symbolDataName = Symbol(dataName)
        keyOptions = get(dropdownOptions, dataName, nothing)
        displayName = haskey(names, symbolDataName) ? names[symbolDataName] : Ahorn.humanizeVariableName(dataName)
        tooltip = Ahorn.expandTooltipText(get(tooltips, symbolDataName, ""))
        value = getValue(room, symbol, simple)

        push!(res, Ahorn.Form.suggestOption(displayName, value, tooltip=tooltip, dataName=dataName, choices=keyOptions, editable=true))
    end

    return res
end

function createCheckpoint(room::Maple.Room)
    x, y = Int.(room.size ./ 2)

    for entity in room.entities
        if entity.name == "player"
            x, y = Int(get(entity.data, "x", 0)), Int(get(entity.data, "y", 0))

            break
        end
    end

    checkpoint = Maple.ChapterCheckpoint(x, y, allowOrigin=true)
    checkpoint.id = Ahorn.EntityIds.nextId()

    return checkpoint
end

function handleCheckpoint!(room::Maple.Room, add::Bool=false)
    checkpoints = filter(e -> e.name == "checkpoint", room.entities)

    filter!(e -> e.name != "checkpoint", room.entities)

    if add
        if isempty(checkpoints)
            push!(room.entities, createCheckpoint(room))

        else
            push!(room.entities, checkpoints[1])
        end
    end
end

function handleSimpleValues!(data::Dict{String, Any}, simple::Bool=get(Ahorn.config, "use_simple_room_values", true))
    if simple
        data["x"] *= 8
        data["y"] *= 8

        data["width"] *= 8
        data["height"] *= 8
    end
end

function handleFakeKeys!(data::Dict{String, Any})
    data["position"] = (data["x"], data["y"])
    data["size"] = (data["width"], data["height"])

    signs = sign.(data["size"]) .== -1
    data["size"] = abs.(data["size"])
    data["position"] = data["position"] .- data["size"] .* signs
end

function handleMusicTrack(data::Dict{String, Any}, parent::Gtk.GtkWindow=Ahorn.window)
    if data["music"] != "" && !(data["music"] in dropdownOptions["music"]) && !startswith(data["music"], "event:/")
        Ahorn.topMostInfoDialog("You have entered an invalid song name.\nIf you're using a custom song, make sure to copy the event path from FMOD Studio, which starts with 'event:/'", parent)

        return true
    end

    return false
end

function handleRoomSize(data::Dict{String, Any}, simple::Bool=get(Ahorn.config, "use_simple_room_values", true), parent::Gtk.GtkWindow=Ahorn.window)
    minimumRecommendedDisplay = (floor(Int, 320 / (simple ? 8 : 1)), floor(Int, 184 / (simple ? 8 : 1)))
    if any(data["size"] .< minimumRecommended)
        if !Ahorn.topMostAskDialog("The size you have chosen is smaller than the recommended minimum size $minimumRecommended.\nAre you sure you want this size?", parent)
            return true
        end
    end

    return false
end

function handleRoomName(data::Dict{String, Any}, currentRoom::Maple.Room, map::Maple.Map, creating::Bool=true, parent::Gtk.GtkWindow=Ahorn.window)
    exists = isa(Maple.getRoomByName(map, data["name"]), Maple.Room)

    if exists
        if !creating && currentRoom.name == data["name"]
            return false
        end

        Ahorn.topMostInfoDialog("The selected room name is already in use.", parent)

        return true
    end

    return false
end

function handleRoomValues!(room::Maple.Room, data::Dict{String, Any})
    structFields = fieldnames(typeof(room))

    for symbol in structFields
        name = string(symbol)

        if haskey(data, name)
            setfield!(room, symbol, data[name])
        end
    end
end

function markForRedraw(room::Maple.Room, map::Maple.Map)
    dr = Ahorn.getDrawableRoom(map, room)

    for layer in dr.layers
        layer.redraw = true
    end
end

function updateTemplateRoom(creating::Bool=true)
    # Copy all fields from the selected room if we are creating new one
    if creating && Ahorn.loadedState.room !== nothing
        global templateRoom = deepcopy(Ahorn.loadedState.room)
    end

    global currentRoom = creating ? templateRoom : Ahorn.loadedState.room
end

function createRoomWindow(creating::Bool=true, simple::Bool=get(Ahorn.config, "use_simple_room_values", true))
    if Ahorn.loadedState.map === nothing
        Ahorn.topMostInfoDialog("No map is currently loaded.", Ahorn.window)

    elseif !creating && Ahorn.loadedState.room === nothing
        Ahorn.topMostInfoDialog("Cannot edit non existing room.", Ahorn.window)

    else
        updateTemplateRoom(creating)
        title = creating ? "$(Ahorn.baseTitle) - Create Room" : "$(Ahorn.baseTitle) - $(currentRoom.name)"

        langdata = get(Ahorn.langdata, :room_window)
        options = getOptions(currentRoom, dropdownOptions, langdata)
        section = Ahorn.Form.Section("Room", options, fieldOrder=roomFieldOrder)
        buttonText = creating ? "Add Room" : "Update Room"

        function callback(data::Dict{String, Any})
            updateTemplateRoom(creating)
            currentMap = Ahorn.loadedState.map

            handleSimpleValues!(data, simple)
            handleFakeKeys!(data)

            exitEarly = handleRoomSize(data, simple, roomWindow) ||
                handleMusicTrack(data, roomWindow) ||
                handleRoomName(data, currentRoom, currentMap, creating, roomWindow)

            if exitEarly
                return false
            end

            snapshotDesc = (creating ? "Created room" : "Updated room ") * data["name"]
            Ahorn.History.addSnapshot!(Ahorn.History.MapSnapshot(snapshotDesc, currentMap))

            handleCheckpoint!(currentRoom, data["checkpoint"])
            handleRoomValues!(currentRoom, data)

            if creating
                # Remove values so we don't create a carbon copy of the room
                empty!(currentRoom.fgDecals)
                empty!(currentRoom.bgDecals)

                empty!(currentRoom.triggers)
                empty!(currentRoom.entities)

                currentRoom.fgTiles.data .= '0'
                currentRoom.bgTiles.data .= '0'
                currentRoom.objTiles.data .= -1

                push!(currentMap.rooms, currentRoom)
            end

            Maple.updateTileSize!(currentRoom, Maple.tile_fg_names["Air"], Maple.tile_fg_names["Air"])
            Ahorn.handleRoomChanged(currentMap, currentRoom, Ahorn.loadedState.room)
            Ahorn.updateTreeView!(Ahorn.roomList, Ahorn.getTreeData(currentMap), row -> row[1] == currentRoom.name)

            markForRedraw(currentRoom, currentMap)
            draw(Ahorn.canvas)

            return true
        end

        if roomWindow !== nothing
            Gtk.destroy(roomWindow)
        end

        return global roomWindow = Ahorn.Form.createFormWindow(title, section, callback=callback, buttonText=buttonText)
    end
end

createRoom(widget::Union{Ahorn.MenuItemsTypes, Nothing}=nothing) = showall(createRoomWindow(true))
configureRoom(widget::Union{Ahorn.MenuItemsTypes, Nothing}=nothing) = showall(createRoomWindow(false))

function roomNameValidator(s::String)
    if Ahorn.loadedState.map === nothing || currentRoom === nothing
        return false
    end

    room = Maple.getRoomByName(Ahorn.loadedState.map, s)

    return s != "" && (s == currentRoom.name || !isa(room, Maple.Room))
end

end


text:
import .TensorBoardLogger: TensorBoardLogger

function TensorBoardLogger.preprocess(name, val::Measurement, data)
    TensorBoardLogger.preprocess(name*"/mean", val.mean, data)
    TensorBoardLogger.preprocess(name*"/err", val.error, data)

    return data
end


text:
module HexBinPlots
# Copyright (c) 2017: Ralph Smith
# portions derived from Gadfly.jl, StatPlots.jl, StatsBase.jl
# Copyright (c) 2012-2017: the Gadfly.jl developers
# Copyright (c) 2012-2017: the StatPlots.jl developers
# Copyright (c) 2012-2017: the StatsBase.jl developers

# SPDX-License-Identifier: MIT-Expat
# License-Filename: LICENSE.md

export hexbins

using Compat
using Reexport
@reexport using Plots
using Hexagons
using StatsBase
import StatsBase.fit

# superficially similar to StatsBase.Histogram API
struct HexHistogram{T <: Real,S <: Real}
    xc::Vector{T}
    yc::Vector{T}
    weights::Vector{S}
    xsize::T
    ysize::T
    isdensity::Bool
end

function fit(::Type{HexHistogram},x::AbstractVector,y::AbstractVector,
             bins::Union{NTuple{1,Int},NTuple{2,Int},Int};
             xyweights=nothing,
             density::Bool=false)
    if length(bins) == 2
        xbins, ybins = bins
    else
        xbins, ybins = (bins...,bins...)
    end
    xmin, xmax = extrema(x)
    ymin, ymax = extrema(y)
    xspan, yspan = xmax - xmin, ymax - ymin
    xsize, ysize = xspan / xbins, yspan / ybins
    fit(HexHistogram,x,y,xsize,ysize,boundingbox=[xmin,xmax,ymin,ymax],
        density=density,xyweights=xyweights)
end

function xy2counts_(x::AbstractArray,y::AbstractArray,
                    xsize::Real,ysize::Real,x0,y0)
    counts = Dict{(Tuple{Int, Int}), Int}()
    @inbounds for i in eachindex(x)
        h = convert(HexagonOffsetOddR,
                    cube_round(x[i] - x0,y[i] - y0,xsize, ysize))
        idx = (h.q, h.r)
        counts[idx] = 1 + get(counts,idx,0)
    end
    counts
end
function xy2counts_(x::AbstractArray,y::AbstractArray,wv::AbstractVector{T},
                    xsize::Real,ysize::Real,x0,y0) where{T}
    counts = Dict{(Tuple{Int, Int}), T}()
    zc = zero(T)
    @inbounds for i in eachindex(x)
        h = convert(HexagonOffsetOddR,
                    cube_round(x[i] - x0,y[i] - y0,xsize, ysize))
        idx = (h.q, h.r)
        counts[idx] = wv[i] + get(counts,idx,zc)
    end
    counts
end
function counts2xy_(counts::Dict{S,T},xsize, ysize, x0, y0) where {S,T}
    nhex = length(counts)
    xh = zeros(nhex)
    yh = zeros(nhex)
    vh = zeros(T,nhex)
    k = 0
    for (idx, cnt) in counts
        k += 1
        xx,yy = Hexagons.center(HexagonOffsetOddR(idx[1], idx[2]),
                                xsize, ysize, x0, y0)
        xh[k] = xx
        yh[k] = yy
        vh[k] = cnt
    end
    xh,yh,vh
end
function fit(::Type{HexHistogram},x::AbstractVector,y::AbstractVector,
             xsize, ysize; boundingbox=[], density::Bool=false,
             xyweights::Union{Nothing,AbstractWeights}=nothing)
    (length(x) == length(y)) || throw(
        ArgumentError("data vectors must be commensurate"))
    (xyweights == nothing ) || (length(xyweights) == length(x)) || throw(
        ArgumentError("data and weight vectors must be commensurate"))

    if isempty(boundingbox)
        xmin, xmax = extrema(x)
        ymin, ymax = extrema(y)
    else
        xmin, xmax, ymin, ymax = (boundingbox...,)
    end
    xspan, yspan = xmax - xmin, ymax - ymin
    x0, y0 = xmin - xspan / 2,ymin - yspan / 2
    if xyweights == nothing
        counts = xy2counts_(x,y,xsize,ysize,x0,y0)
    else
        counts = xy2counts_(x,y,xyweights.values,xsize,ysize,x0,y0)
    end
    xh,yh,vh = counts2xy_(counts,xsize, ysize, x0, y0)
    if density
        binarea = sqrt(27)*xsize*ysize/2
        vh = 1/(sum(vh)*binarea) * vh
    end
    HexHistogram(xh,yh,vh,xsize,ysize,density)
end

function make_shapes(h::HexHistogram)
    nhex = length(h.xc)
    hexes = Vector{Shape}(undef, nhex)
    for k in eachindex(h.xc)
        hp = hexpoints(h.xc[k],h.yc[k],h.xsize,h.ysize)
        hexes[k] = Shape([p[1] for p in hp],[p[2] for p in hp])
    end
    hexes,h.weights
end

"""
    hexbins(x,y; density=false, weights=ones(), bins=20,...) --> plot object

Construct and plot a hexbin histogram of two vectors `x`,`y` of equal length.

# Important keyword options

* `bins`: an integer or 2-tuple of integers determining grid resolution.

* `density`: boolean indicating whether result should be normalized as a density.

* `weights`: `AbstractWeights` denoting contribution of each sample pair to its bin.

* Plot attributes, notably `colorbar`, `color_palette`.

"""
function hexbins end

@shorthands hexbins
@recipe function f(::Type{Val{:hexbins}}, plt::AbstractPlot; density = false,
                   weights=nothing)
    x, y = plotattributes[:x], plotattributes[:y]
    bns = get(plotattributes, :bins, 20)
    hx = fit(HexHistogram,x,y,bns,density=density,xyweights=weights)
    legend := false
    h,vh = make_shapes(hx)
    vmax = maximum(vh)
    xsh = Vector{Float64}()
    ysh = Vector{Float64}()
    for k in eachindex(h)
        append!(xsh,h[k].x)
        push!(xsh,h[k].x[1])
        push!(xsh,NaN)
        append!(ysh,h[k].y)
        push!(ysh,h[k].y[1])
        push!(ysh,NaN)
    end
    if haskey(plotattributes,:color_palette)
        fc = Plots.cgrad(plotattributes[:color_palette])
    else
        fc = Plots.cgrad()
    end

    cb = get(plotattributes,:colorbar,false)
    wantcb = (cb != :none) & (cb != false)
    if wantcb && (cb != true) && (cb != :right) && (cb != :best)
        warn("overriding unimplemented colorbar specification")
    end
    if wantcb
        xr = 1:3
        yr = linspace(0,vmax,256)
        ramp = ones(3)' .* yr

        layout --> @layout [ ctrplot{0.95w,1h} cbar ]
    end
    @series begin
        seriestype := :shape
        subplot := 1
        background_color_inside := fc[0.0]
        cols = map(x->fc[clamp(x/vmax,0,1)],vh)
        fillcolor := cols
        x := xsh
        y := ysh
    end

    if wantcb
        @series begin
            seriestype := :heatmap
            # left_margin --> 1mm
            colorbar := false
            subplot := 2
            xticks := false
            ylims := extrema(yr)
            ymirror := true
            if haskey(plotattributes,:color_palette)
                fillcolor := Plots.cgrad(plotattributes[:color_palette])
            end
            x := xr
            y := yr
            z := Surface(ramp)
        end
    end

end

end


text:
A = diagm([1, -0.5, 1])

ws = DgeesWs(3)

dgees!(ws, A)
println(ws.eigen_values)

dgees!(ws, A, >=, 1.0)
println(ws.eigen_values)


text:
using Weave, Test
using Mustache

# Test parsing

doc = """

! println("Something")

Some markdown with inline stuff and `j code`

 ! Not julia code but `j show("is")`

"""

pat = Weave.input_formats["markdown"].inline
ms = collect(eachmatch(pat, doc))
@test ms[1][2] == "println(\"Something\")"
@test ms[2][1] == "code"
@test ms[3][1] == "show(\"is\")"

chunk = Weave.parse_doc(doc, Weave.input_formats["markdown"])[1]
@test length(chunk.content) == 7
@test chunk.content[2].content == ms[1][2]
@test chunk.content[4].content == ms[2][1]
@test chunk.content[6].content == ms[3][1]

chunknw = Weave.parse_doc(doc, Weave.input_formats["noweb"])[1]
@test all([chunknw.content[i].content == chunk.content[i].content for i in 1:7])

# Test with document

tpl = mt"""
{{{ :body }}}
"""

out = weave(joinpath(@__DIR__, "documents", "markdown_beamer.jmd"), doctype="md2html", template=tpl)
@test read(out, String) == read(out*".ref", String)
rm(out)

out = weave(joinpath(@__DIR__, "documents", "markdown_beamer.jmd"), doctype="md2tex", template=tpl)
@test read(out, String) == read(out*".ref", String)
rm(out)


text:
#posit_ops.jl
#posit operations.

macro __unaryshim(fn)
  :($fn{N,ES}(x::Posit{N,ES}) = Posit{N,ES}($fn(__p2f(x))))
end

macro __binaryshim(fn)
  :($fn{N,ES}(lhs::Posit{N,ES}, rhs::Posit{N,ES}) = Posit{N,ES}($fn(__p2f(lhs), __p2f(rhs))))
end

#some unary operations
Base.:+{N,ES}(x::Posit{N,ES}) = x
Base.:-{N,ES}(x::Posit{N,ES}) = reinterpret(__PT(Posit{N,ES}), -__s(x))

#partial required operations
function Base.:+{N,ES}(lhs::Posit{N,ES}, rhs::Posit{N,ES})
  if (isinf(lhs) | isinf(rhs))
    (isinf(lhs) & isinf(rhs)) && (throw(NaNError()))
    return Posit{N,ES}(Inf)
  end

  Posit{N,ES}(__p2f(lhs) + __p2f(rhs))
end

@__binaryshim Base.:-
@__binaryshim Base.:*

function Base.cmp{N,ES}(lhs::Posit{N,ES}, rhs::Posit{N,ES})
  if isinf(lhs) && isinf(rhs)
    throw(DomainError())
  else
    cmp(__s(lhs), __s(rhs))
  end
end

function Base.:<{N,ES}(lhs::Posit{N,ES}, rhs::Posit{N,ES})
  if isinf(lhs) || isinf(rhs)
    true
  else
    __s(lhs) < __s(rhs)
  end
end

function Base.:<={N,ES}(lhs::Posit{N,ES}, rhs::Posit{N,ES})
  if isinf(lhs) || isinf(rhs)
    true
  else
    __s(lhs) <= __s(rhs)
  end
end

#do not waste time downconverting.
Base.:(==){N,ES}(lhs::Posit{N,ES}, rhs::Posit{N,ES}) = __u(lhs) == __u(rhs)

#full posit required operations
@__binaryshim Base.:/
@__unaryshim Base.inv
@__unaryshim Base.log2
@__unaryshim Base.exp2

#full posit extended operations
@__unaryshim Base.sqrt
@__unaryshim Base.log10
@__unaryshim Base.log
@__unaryshim Base.exp
@__binaryshim Base.:^
@__binaryshim Base.log
@__unaryshim Base.sin
@__unaryshim Base.cos
@__unaryshim Base.atan
@__binaryshim Base.atan2

#required fused operations - overload julia definition
function Base.fma{N,ES}(a::Posit{N,ES}, b::Posit{N,ES}, c::Posit{N,ES})
  Posit{N,ES}(fma(__p2f(a), __p2f(b), __p2f(c)))
end
function fms{N, ES}(a::Posit{N,ES}, b::Posit{N,ES}, c::Posit{N,ES})
  Posit{N,ES}(fma(__p2f(a), __p2f(b), -__p2f(c)))
end
function nfma{N, ES}(a::Posit{N,ES}, b::Posit{N,ES}, c::Posit{N,ES})
  Posit{N,ES}(-fma(__p2f(a), __p2f(b), __p2f(c)))
end
function nfms{N, ES}(a::Posit{N,ES}, b::Posit{N,ES}, c::Posit{N,ES})
  Posit{N,ES}(-fma(__p2f(a), __p2f(b), -__p2f(c)))
end

export fms, nfma, nfms

#the following operations:
#FAS - fused-add-scale
#FCP - fused cross product
#FDP - fused dot product
# are found in "fusedpositoperations.jl"


text:
#=====================================#
# MIP solvers (commercial, but fast)  #
#=====================================#

function get_gurobi()
    return JuMP.optimizer_with_attributes(Gurobi.Optimizer,
                                          MOI.Silent() => false,
                                          # "MIPFocus" => 3, # Focus on optimality over feasibility
                                          "Presolve" => 1)
end

function get_cplex()
     return JuMP.optimizer_with_attributes(CPLEX.Optimizer,
                                           MOI.Silent() => false,
                                           # "CPX_PARAM_EPGAP" => 1E-4,
                                           # "CPX_PARAM_MIPEMPHASIS" => 2 # Focus on optimality over feasibility
                                           "CPX_PARAM_PREIND" => 1)
end

#======================================#
# MIP solvers (open-source, but slow)  #
#======================================#

function get_cbc()
    return JuMP.optimizer_with_attributes(Cbc.Optimizer,
                                          MOI.Silent() => false)
end

function get_glpk()
    return JuMP.optimizer_with_attributes(GLPK.Optimizer,
                                          MOI.Silent() => false)
end

#========================================================#
# Continuous nonlinear programming solver (open-source)  #
#========================================================#

function get_ipopt()
     return JuMP.optimizer_with_attributes(Ipopt.Optimizer,
                                       MOI.Silent() => true,
                                       "sb" => "yes",
                                       "max_iter" => Int(1E4))
end

#=================================================================#
# Local mixed-integer nonlinear programming solver (open-source)  #
#=================================================================#
function get_juniper()
     return JuMP.optimizer_with_attributes(Juniper.Optimizer,
                                         MOI.Silent() => false,
                                         "mip_solver" => get_gurobi(),
                                         "nl_solver" => get_ipopt())
end

#=================================================================#
# Global mixed-integer nonlinear programming solver (open-source) #
#=================================================================#
function get_alpine()
        return JuMP.optimizer_with_attributes(Alpine.Optimizer,
                                            "nlp_solver" => get_ipopt(),
                                            "minlp_solver" => get_juniper(),
                                            "mip_solver" => get_gurobi(),
                                            "optimizer_presolve_bt" => false,
                                            "optimizer_presolve_max_iter" => 10,
                                            "optimizer_presolve_bp" => false,
                                            "disc_ratio" => 10)
end


text:
using Test
using QuantumLattices.Prerequisites.Factories

@testset "escape" begin
    @test escape(true, RawExpr()) == true
    @test escape(true, Escaped()) == true
    @test escape(true, UnEscaped()) == true
    @test escape(:Int, Escaped(:Int)) == :($(Expr(:escape, :Int)))
    @test escape(:Int, Escaped()) == :Int
    @test escape(:(Vector{Int}), Escaped(:Vector)) == :(($(Expr(:escape, :Vector))){Int})
    @test escape(:Int, UnEscaped(:Int)) == :Int
    @test escape(:Int, UnEscaped()) == :($(Expr(:escape, :Int)))
    @test escape(:(Vector{Int}), UnEscaped(:Vector)) == :(Vector{$(Expr(:escape, :Int))})
end

@testset "names" begin
    @test names(:a) == [:a]
    @test names(:(Vector{Int})) == [:Vector, :Int]
end

@testset "Inference" begin
    @test Inference(name=:T) == Inference(nothing, :T, nothing)
    @test isequal(Inference(name=:T), Inference(nothing, :T, nothing))
    @test (@inference Vector{Tuple{Int, String}})(UnEscaped(:Vector, :Tuple, :Int, :String)) == :(Vector{Tuple{Int, String}})
    @test (@inference Type{<:Real})(UnEscaped(:Type, :Real)) == :(Type{<:Real})
    @test string(Inference(:(SVector{N, <:Real}))) == "Inference(\n  head:   curly\n  name:   SVector\n  params: Inference[N, <:Real]\n)"
    @test replace(@inference(Vector{<:Real}), name=:AbstractVector) == @inference(AbstractVector{<:Real})
end

@testset "Argument" begin
    argument = Argument(name=:name, default=nothing)
    @test string(argument) == "Argument(\n  name:    name\n  type:    Any\n  slurp:   false\n  default: nothing\n)"

    argument = Argument(:(phone::Vector{Int} = [9, 1, 1]))
    @test argument.name == :phone
    @test argument.type == Inference(:(Vector{Int}))
    @test argument.slurp == false
    @test argument.default == :([9, 1, 1])
    @test argument(MixEscaped(UnEscaped(:Vector), Escaped(:Int))) == Expr(:kw, :(phone::Vector{$(Expr(:escape, :Int))}), :[9, 1, 1])

    argument = Argument(:(properties::Int...))
    @test argument.name == :properties
    @test argument.type == Inference(:Int)
    @test argument.slurp == true
    @test argument.default === nothing
    @test argument(MixEscaped(UnEscaped(:Int))) == :(properties::Int...)

    argument1 = @argument address::String
    argument2 = Argument(:(address::String))
    @test argument1 == argument2
end

@testset "Parameter" begin
    parameter = Parameter(head=:(<:), name=:name, type=Inference(:T))
    @test string(parameter) == "Parameter(\n  head: <:\n  name: name\n  type: T\n)"

    parameter = Parameter(:T)
    @test parameter.head === nothing
    @test parameter.name == :T
    @test parameter.type === nothing
    @test parameter(UnEscaped(:T)) == :T

    parameter = Parameter(:(T<:Real))
    @test parameter.head == :(<:)
    @test parameter.name == :T
    @test parameter.type == Inference(:Real)
    @test parameter(UnEscaped(:Real)) == :(T<:Real)

    parameter = Parameter(:(<:Real))
    @test parameter.head == :(<:)
    @test parameter.name === nothing
    @test parameter.type == Inference(:Real)
    @test parameter(UnEscaped(:Real)) == :(<:Real)

    parameter = @parameter ::Int
    @test parameter.head == :(::)
    @test parameter.name === nothing
    @test parameter.type == Inference(:Int)
    @test parameter(UnEscaped(:Int)) == :(Int)
end

@testset "Field" begin
    field = Field(name=:name)
    @test string(field) == "Field(\n  name: name\n  type: Any\n)"

    field = Field(:xs)
    @test field.name == :xs
    @test field.type == Inference(:Any)
    @test field(UnEscaped(:Any)) == :(xs::Any)

    field = Field(:(xs::Vector{Int}))
    @test field.name == :xs
    @test field.type == Inference(:(Vector{Int}))
    @test field(UnEscaped(:Vector, :Int)) == :(xs::Vector{Int})

    field1 = @field xs::Vector{Int}
    field2 = Field(:(xs::Vector{Int}))
    @test field1 == field2
end

@testset "Block" begin
    block = Block(:(x = 1; y = 2))
    push!(block)
    rmlines!(block)
    @test block.body == Any[:(x = 1), :(y = 2)]
    @test block == @rmlines Block(:(x = 1; y = 2))
    @test block(MixEscaped()) == Expr(:block, :(x = 1), :(y = 2))
    @test block(Escaped()) == Expr(:block, :(x = 1), :(y = 2))

    block = @block a = 1
    @push! block b = 2 c = 3 d = 4
    @test block.body == [:(a = 1), :(b = 2), :(c = 3), :(d = 4)]
end

@testset "FunctionFactory" begin
    ff = FunctionFactory(name=:fx)
    addargs!(ff)
    addkwargs!(ff)
    extendbody!(ff)
    addwhereparams!(ff)
    addparams!(ff)
    @test ff == FunctionFactory(name=:fx)

    ff = FunctionFactory(:(fx(x::Int, y::Int; choice::Function=sum) = choice(x, y)))
    @test ff.name == :fx
    @test ff.args == Argument.([:(x::Int), :(y::Int)])
    @test ff.kwargs == Argument.([:(choice::Function=sum)])
    @test ff.rtype == Inference(:Any)
    @test ff.whereparams == Parameter[]
    @test rmlines(ff.body) == Block(:(begin choice(x, y) end))

    ff = FunctionFactory(:(
        function fx(x::T, y::T; choice::Function=sum) where T
            choice(x, y)
        end
    ))
    @test ff.name == :fx
    @test ff.args == Argument.([:(x::T), :(y::T)])
    @test ff.kwargs == Argument.([:(choice::Function=sum)])
    @test ff.rtype == Inference(:Any)
    @test ff.whereparams == Parameter.([:T])
    @test rmlines(ff.body) == Block(:(begin choice(x, y) end))

    ff = @functionfactory (fx()::T) = nothing
    @addargs! ff x::T y::T z::T
    @addkwargs! ff sign::Int=1 choice::Function=sum
    @addparams! ff T
    @addwhereparams! ff T<:Number
    @extendbody! ff result = choice(x, y, z) result *= sign
    @test ff.name == :fx
    @test ff.args == Argument.([:(x::T), :(y::T), :(z::T)])
    @test ff.kwargs == Argument.([:(sign::Int=1), :(choice::Function=sum)])
    @test ff.rtype == Inference(:T)
    @test ff.params == [Inference(:T)]
    @test ff.whereparams == Parameter.([:(T<:Number)])
    @test rmlines(ff.body) == Block(:nothing, :(result = choice(x, y, z)), :(result *= sign))
end

@testset "TypeFactory" begin
    tf = TypeFactory(name=:Child)
    addfields!(tf)
    addconstructors!(tf)
    addparams!(tf)
    @test tf == TypeFactory(name=:Child)

    tf = TypeFactory(:(
        struct Child{T<:Real} <: Parent{T}
            address::String
            phone::Vector{Int}
            properties::Vector{T}
        end
    ))
    @test tf.name == :Child
    @test tf.mutable == false
    @test tf.params == Parameter.([:(T<:Real)])
    @test tf.supertype == Inference(:(Parent{T}))
    @test tf.fields == Field.([:(address::String), :(phone::Vector{Int}), :(properties::Vector{T})])
    @test tf.constructors == FunctionFactory[]

    tf = @typefactory struct Child <: Parent{T} end
    @addparams! tf T<:Real
    @addfields! tf address::String phone::Vector{Int} properties::Vector{T}
    @addconstructors! tf Child(address::String, phone::Vector{Int}, properties::Vector{T}) where T = new(address, phone, properties)
    @test tf.name == :Child
    @test tf.mutable == false
    @test tf.params == Parameter.([:(T<:Real)])
    @test tf.supertype == Inference(:(Parent{T}))
    @test tf.fields == Field.([:(address::String), :(phone::Vector{Int}), :(properties::Vector{T})])
end

eval((
    @typefactory struct Child
        name::String
        seniority::Int
        Child(name::String, seniority::Int=1) = new(name, seniority)
    end
)(MixEscaped(UnEscaped(:String, :Int, :Any))))

@testset "call" begin
    c = Child("Tuanzi")
    @test c.name == "Tuanzi"
    @test c.seniority == 1
end


text:
struct AfromB{O,I} <: PushInstructionA1tB1{I,O} end
opname(::Type{<:AfromB}) = "from"
function name(t::Type{AfromB{O,I}}) where {I,O}
    lowercase(string(O)) * "_" * opname(t) * "_" * lowercase(string(I))
end

function oldname(::Type{AfromB{O,I}}) where {I,O}
    uppercase(string(O)) * ".FROM" * uppercase(string(I))
end

@inline function execute!(i::AfromB{O,I}, interp::AbstractPushInterpreter) where {I,O}
    stackhas(interp, I, 1) || return(nothing)
    a = pop!(interp, I)
    res = convert(O, a)
    push!(interp, res)
end

@inline function execute!(i::AfromB{O,I}, interp::AbstractPushInterpreter) where {I,O<:String}
    stackhas(interp, I, 1) || return(nothing)
    a = pop!(interp, I)
    res = string(a)
    push!(interp, res)
end


text:
using ImageFiltering: imfilter, reflect, FIR, FFT
using OffsetArrays: OffsetArray

function analyze(A::TransformSystem{NS}, x::AbstractArray{TX,D}) where {TF,TX,D,NS<:AbstractNsolt{TF,D}}
    pvx = mdarray2polyphase(x, decimations(A.operator))
    y = analyze(A.operator, pvx; A.options...)
    reshape_polyvec(A.shape, A.operator, y)
end

analyze(fb::PolyphaseFB{TF,D}, pvx::PolyphaseVector{TX,D}; kwargs...) where {TF,TX,D} = PolyphaseVector(analyze(fb, pvx.data, pvx.nBlocks; kwargs...), pvx.nBlocks)

function analyze(nsolt::AbstractNsolt, px::AbstractMatrix, nBlocks::NTuple; kwargs...)
    ty = initialStep(nsolt, px; kwargs...)

    nShifts = fld.(size(px, 2), nBlocks)
    rotatedimsfcns = ([ t->rotatedimspv(t, blk) for blk in nBlocks ]...,)
    exty = extendAtoms(nsolt, ty, nShifts, rotatedimsfcns; kwargs...)
    return shiftFilterSymmetry(nsolt, exty)
end

function initialStep(nsolt::RnsoltTypeI, px::AbstractMatrix; kwargs...)
    M = prod(nsolt.decimationFactor)
    fM, cM = fld(M, 2), cld(M, 2)
    CJup = @view nsolt.CJ[1:cM, :]
    CJlw = @view nsolt.CJ[(1:fM) .+ cM, :]

    return [
        nsolt.W0 * Matrix(I, nsolt.nChannels[1], cM) * CJup * px;
        nsolt.U0 * Matrix(I, nsolt.nChannels[2], fM) * CJlw * px
    ]
end

function initialStep(nsolt::RnsoltTypeII, px::AbstractMatrix; kwargs...)
    M = prod(nsolt.decimationFactor)
    fM, cM = fld(M, 2), cld(M, 2)
    CJup = @view nsolt.CJ[1:cM, :]
    CJlw = @view nsolt.CJ[(1:fM) .+ cM, :]

    return [
        nsolt.W0 * Matrix(I, nsolt.nChannels[1], cM) * CJup * px;
        nsolt.U0 * Matrix(I, nsolt.nChannels[2], fM) * CJlw * px
    ]
end

function extendAtoms(nsolt::RnsoltTypeI, px::AbstractMatrix, nShifts::NTuple, rotatedimsfcns::Tuple; border=:circular)
    for d in nsolt.perm
        px = rotatedimsfcns[d](px)
        xu = @view px[1:nsolt.nChannels[1], :]
        xl = @view px[(1:nsolt.nChannels[2]) .+ nsolt.nChannels[1], :]

        foreach(1:nsolt.nStages[d], nsolt.Udks[d]) do k, U
            unnormalized_butterfly!(xu, xl)
            shiftcoefs!(Val(border), k, xu, xl, nShifts[d])
            half_butterfly!(xu, xl)

            xl .= U * xl
        end
    end
    return px
end

# TODO:
function extendAtoms(nsolt::RnsoltTypeII, px::AbstractMatrix, nShifts::NTuple, rotatedimsfcns; border=:circular)
    mnP, mxP = minmax(nsolt.nChannels...)
    for d in nsolt.perm
        px = rotatedimsfcns[d](px)

        xu = @view px[1:mnP, :]
        xl = @view px[end-mnP+1:end, :]

        xum = @view px[1:mxP, :]
        xml = @view px[end-mxP+1:end, :]

        foreach(1:nsolt.nStages[d], nsolt.Wdks[d], nsolt.Udks[d]) do k, W, U
            unnormalized_butterfly!(xu, xl)
            shiftcoefs!(Val(border), 2k-1, xu, xml, nShifts[d])
            half_butterfly!(xu, xl)
            if nsolt.nChannels[1] < nsolt.nChannels[2]
                xu .= W * xu
            else
                xl .= U * xl
            end

            unnormalized_butterfly!(xu, xl)
            shiftcoefs!(Val(border), 2k, xum, xl, nShifts[d])
            half_butterfly!(xu, xl)
            if nsolt.nChannels[1] < nsolt.nChannels[2]
                xml .= U * xml
            else
                xum .= W * xum
            end
        end
    end
    return px
end

shiftFilterSymmetry(::Rnsolt, y::AbstractMatrix) = y

function initialStep(nsolt::CnsoltTypeI, px::AbstractMatrix; kwargs...)
    Ipm = Matrix(I, nsolt.nChannels, prod(nsolt.decimationFactor))
    return nsolt.V0 * Ipm * nsolt.FJ * px
end

function initialStep(nsolt::CnsoltTypeII, px::AbstractMatrix; kwargs...)
    Ipm = Matrix(I, nsolt.nChannels, prod(nsolt.decimationFactor))
    return nsolt.V0 * Ipm * nsolt.FJ * px
end

function extendAtoms(nsolt::CnsoltTypeI, px::AbstractMatrix, nShifts::NTuple, rotatedimsfcns::NTuple; border=:circular)
    hP = fld(nsolt.nChannels, 2)
    for d in nsolt.perm
        px = rotatedimsfcns[d](px)
        xu = @view px[1:hP, :]
        xl = @view px[(1:hP) .+ hP, :]

        foreach(1:nsolt.nStages[d], nsolt.Wdks[d], nsolt.Udks[d], nsolt.θdks[d]) do k, W, U, θ
            B = getMatrixB(nsolt.nChannels, θ)
            px .= B' * px
            shiftcoefs!(Val(border), k, xu, xl, nShifts[d])
            px .= B * px

            xl .= U * xl
            xu .= W * xu
        end
    end
    return px
end

function extendAtoms(nsolt::CnsoltTypeII, px::AbstractMatrix, nShifts::NTuple, rotatedimsfcns; border=:circular)
    fP, cP = fld(nsolt.nChannels, 2), cld(nsolt.nChannels, 2)
    for d in nsolt.perm
        px = rotatedimsfcns[d](px)

        xW = @view px[1:fP, :]
        xU = @view px[(1:fP) .+ fP, :]
        xb = @view px[(fP+1):end, :]
        xŴ = @view px[1:cP, :]
        xÛ = @view px[(1:cP) .+ fP, :]
        xe  = @view px[1:end-1, :]

        foreach(1:nsolt.nStages[d], nsolt.Wdks[d], nsolt.Udks[d], nsolt.θ1dks[d], nsolt.Ŵdks[d], nsolt.Ûdks[d], nsolt.θ2dks[d]) do k, W, U, θ1, Ŵ, Û, θ2
            B1 = getMatrixB(nsolt.nChannels, θ1)
            xe .= B1' * xe
            shiftcoefs!(Val(border), 2k-1, xW, xU, nShifts[d])
            xe .= B1 * xe
            xU .= U * xU
            xW .= W * xW

            B2 = getMatrixB(nsolt.nChannels, θ2)
            xe .= B2' * xe
            shiftcoefs!(Val(border), 2k, xW, xb, nShifts[d])
            xe .= B2 * xe
            xÛ .= Û * xÛ
            xŴ .= Ŵ * xŴ
        end
    end
    return px
end

shiftFilterSymmetry(nsolt::Cnsolt, y::AbstractMatrix) = nsolt.Φ * y

function analyze(jts::JoinedTransformSystems{MS}, x::AbstractArray{TX,D}) where {MS<:Multiscale,TX,D}
    subanalyze(jts.shape, x, jts.transforms...)
end

# analyze(msop::MultiscaleOperator{TF,D}, x::AbstractArray{TX,D}) where {TF,TX,D} = subanalyze(msop.shape, x, msop.operators...)

# shape == Shapes.Separated
function subanalyze(shape::Shapes.Separated, sx::AbstractArray, abop::AbstractOperator, args...)
    sy = analyze(abop, sx)
    [sy[2:end], subanalyze(shape, sy[1], args...)...]
end

subanalyze(::Shapes.Separated, sx::AbstractArray, abop::AbstractOperator) = [ analyze(abop, sx) ]

# shape == Shapes.Combined
function subanalyze(shape::Shapes.Combined, sx::AbstractArray{T,D}, abop::AbstractOperator, args...) where {T,D}
    sy = analyze(abop, sx)
    clns = fill(:,D)
    [ sy[clns...,2:end], subanalyze(shape, sy[clns...,1], args...)... ]
end

subanalyze(::Shapes.Combined, sx::AbstractArray, abop::AbstractOperator) = [ analyze(abop, sx) ]

# shape == Shapes.Vec
function subanalyze(shape::Shapes.Vec, sx::AbstractArray, abop::AbstractOperator, args...)
    sy = analyze(abop, sx)
    lndc = fld(length(sy), nchannels(abop))
    dcdata = reshape(sy[1:lndc], args[1].shape.insize...)
    vcat(sy[lndc+1:end], subanalyze(shape, dcdata, args...))
end

subanalyze(::Shapes.Vec, sx::AbstractArray, abop::AbstractOperator) = analyze(abop, sx)

function analyze(pfs::ParallelFilters{TF,D}, x::AbstractArray{TX,D}; resource=CPU1(FIR())) where {TF,TX,D}
    df = pfs.decimationFactor
    ord = pfs.polyphaseOrder

    nShift = df .* fld.(ord, 2) .+ 1
    region = UnitRange.(1 .- nShift, df .* (ord .+ 1) .- nShift)
    offset = df .- 1

    map(pfs.kernelspair[1]) do f
        ker = reflect(OffsetArray(f, region...))
        fltimg = imfilter(resource, x, ker, "circular")
        downsample(fltimg, df, offset)
    end
end

function analyze(ca::TransformSystem{PF}, x::AbstractArray{TX,D}) where {TF,TX,D,PF<:ParallelFilters{TF,D}}
    y = analyze(ca.operator, x; ca.options...)
    reshape_polyvec(ca.shape, ca.operator, y)
end

max_stars_repo_name: nixir/MDCDL

max_issues_repo_name: nixir/MDCDL

max_forks_repo_name: nixir/MDCDL


text:
################################
################################
### auxiliary functions
################################
################################

# Function to quickly multiply vectors of matrices
function fastmultiply(out, L, R)
    for i = 1:length(L)
        @inbounds mul!(out[i], L[i], R[i])
    end
    out = hcat(out...)
    return out
end

# dictionary extraction
function extract(d)
    expr = quote end
    for (k, v) in d
        push!(expr.args, :($(Symbol(k)) = $v))
    end
    eval(expr)
    return
end

max_stars_repo_name: rafserqui/class-repo

max_issues_repo_name: rafserqui/class-repo

max_forks_repo_name: rafserqui/class-repo