text:
module load

    using DataCreationDriver
    using StayingPutModelDriver
    using CareData
    using FosterParameters
    using GlobalDecls
    using Logging

    function do_reform_runs(
        ;
        runname   :: AbstractString,
        whichdata :: AbstractString,
        numiter   :: Integer,
        year      :: Integer,
        create_data :: Bool )

        settings = CareData.default_data_settings()
        settings.dataset = whichdata
        settings.num_iterations = numiter
        settings.name = runname
        ### FIXME REMOVE THIS
        settings.targets = ["E06000047","E0600054"]

        params = Array{Params}(undef,0)
        params1 = FosterParameters.get_default_params()
        params1.name = "Current System"
        # sys 1
        push!( params, params1 )

        params2a1 = FosterParameters.get_default_params()
        params2a1.yp_contrib_type = no_contribution
        params2a1.contrib_hb = no_contribution
        params2a1.name = "option 2(a) with Oldham style fee"
        params2a1.payment = min_payment
        params2a1.fee = [0, 78.38, 158.76, 237.23, 340.76] # oldham FIXME UPRATE
        # sys 2
        push!( params, params2a1 )

        params2a2 = FosterParameters.get_default_params()
        params2a2.yp_contrib_type = no_contribution
        params2a2.contrib_hb = no_contribution
        params2a2.name = "option 2(a) without fee"
        params2a2.payment = min_payment
        params2a2.fee = []
        # sys 3
        push!( params, params2a2 )

        params2b = FosterParameters.get_default_params()
        params2b.name = "option 2(b) with HB from all benefit recipients"
        params2b.payment = min_payment
        params2b.yp_contrib_type = no_contribution
        params2b.fee = [0, 78.38, 158.76, 237.23, 340.76] # oldham
        params2b.contrib_hb = benefits_only
        # sys 4
        push!( params, params2b )

        params3 = FosterParameters.get_default_params()
        params3.yp_contrib_type = no_contribution
        params3.contrib_hb = no_contribution
        params3.name = "option 3 - 2(a) with taper"
        params3.payment = min_payment
        params3.fee = [0, 78.38, 158.76, 237.23, 340.76] # oldham
        params3.taper = [1.0, 0.5, 0.25]
        # sys 5
        push!( params, params3 )

        params4 = FosterParameters.get_default_params()
        params4.yp_contrib_type = no_contribution
        params4.contrib_hb = all_people
        params4.name = "option 4: Oldham style fee and contributions via HB from all."
        params4.payment = min_payment
        params4.fee = [0, 78.38, 158.76, 237.23, 340.76]
        # sys 6
        push!( params, params4 )

        params5 = FosterParameters.get_default_params()
        params5.yp_contrib_type = hb_only
        params5.contrib_hb = benefits_only
        params5.name = "option 5: option 2(a) with Oldham style fee only for those with no u18 children."
        params5.payment = min_payment
        params5.fee = [0, 78.38, 158.76, 237.23, 340.76]
        params5.prop_fees_deleted = 0.84 # see email Vicki Swain 09Jan
        # sys 7
        push!( params, params5 )

        if create_data
            DataCreationDriver.create_data( settings )
        end
        nparams = length( params )[1]
        outdir = StayingPutModelDriver.do_one_run( params, settings, year )
        StayingPutModelDriver.dump_run_info( outdir, params, settings )
        StayingPutModelDriver.create_main_tables( outdir, nparams, year )
        StayingPutModelDriver.create_england_tables( outdir, params, settings, year )
        StayingPutModelDriver.create_england_tables_by_age( outdir, params, settings, year )
        StayingPutModelDriver.create_main_tables_by_region( outdir, nparams, year )
    end

    """
    FIXME this is a HORRIBLE hack
    see the FIXMEs in StayingPutModelDriver
    """
    function create_region_tables(
        ;
        runname   :: AbstractString,
        whichdata :: AbstractString,
        numiter   :: Integer,
        year      :: Integer )
        nparams = 5
        outdir = "$(RESULTSDIR)/main-results-$(whichdata)/"
        StayingPutModelDriver.create_main_tables_by_region( outdir, nparams, year )
    end

    function create_data( ds :: DataPublisher, pc :: Real, numiter :: Integer, createdata :: Bool, year :: Integer )
        settings = CareData.default_data_settings()
        settings.name = "using-$ds-$pc-pct"
        settings.dataset = "ds-$ds-$pc-pct"
        settings.annual_sp_increment = pc # 1% inrease in all SP rates per year
        settings.description = "Main run, with $pc annual increase in rates of retention data $ds; iterations $numiter"
        settings.num_iterations = numiter
        settings.reaching_18s_source = ds
        DataCreationDriver.create_data( settings )
    end

    function do_main_run( ds :: DataPublisher, pc :: Real, numiter :: Integer, createdata :: Bool, year :: Integer )
        settings = CareData.default_data_settings()
        settings.name = "using-$ds-$pc-pct"
        settings.dataset = "ds-$ds-$pc-pct"
        settings.annual_sp_increment = pc # 1% inrease in all SP rates per year
        settings.description = "Main run, with $pc annual increase in rates of retention data $ds; iterations $numiter"
        settings.num_iterations = numiter
        settings.reaching_18s_source = ds

        if createdata
            DataCreationDriver.create_data( settings )
        end
        params = Array{Params}(undef,0)
        params1 = FosterParameters.get_default_params()

        push!( params, params1 )

        params2 = FosterParameters.get_default_params()
        params2.payment = min_payment
        push!( params, params2 )

        params3 = FosterParameters.get_default_params()
        params3.yp_contrib_type = no_contribution
        push!( params, params3 )

        num_systems = size( params )[1]

        outdir = StayingPutModelDriver.do_one_run( params, settings, year )
        StayingPutModelDriver.create_main_tables( outdir, num_systems, :rcode, year )
        StayingPutModelDriver.create_main_tables( outdir, num_systems, :ccode, year )
        StayingPutModelDriver.create_england_tables( outdir, params, settings, year )
        StayingPutModelDriver.create_england_tablesbyage( outdir, params, settings, year )
    end #  function

    numiter = 200
    do_create_data = false
    year = 2020
    #do_main_run( OFSTED, 0.0, numiter, false, year )
    #do_main_run( DFE, 0.0, numiter, false, year )
    #do_main_run( OFSTED, 0.01, numiter, true, year )
    #do_main_run( DFE, 0.01, numiter, true, year )

    # create_data( DFE, 0.0, numiter, false, year )
    # create_data( OFSTED, 0.01, numiter, true, year )
    # create_data( DFE, 0.01, numiter, true, year )

    # configure logger; see: https://docs.julialang.org/en/v1/stdlib/Logging/index.html
    # and: https://github.com/oxinabox/LoggingExtras.jl
    logger = FileLogger("/home/graham_s/tmp/afc_log.txt")
    global_logger(logger)
    LogLevel( Logging.Info )

    DEFAULT_DATA = "ds-DFE-0.0-pct"

    datasets = [
        "ds-DFE-0.01-pct",
        "ds-DFE-0.0-pct",
        "ds-OFSTED-0.01-pct",
        "ds-OFSTED-0.0-pct"
    ]

    #dsname = datasets[1]
    #do_reform_runs(
    #     runname   = "test1",
    #     whichdata = DEFAULT_DATA,
#         numiter   = 1,
#         year      = 2020 )
    #
if size(ARGS)[1] > 0
    numiter = parse( Int, ARGS[1])
end

if size(ARGS)[1] > 1
    do_create_data = parse( Int, ARGS[2]) == 1
end

for dsname in datasets
    if dsname == "ds-DFE-0.0-pct"
       do_reform_runs(
            runname   = "main-results-"*dsname,
            whichdata = dsname,
            numiter   = numiter,
            year      = 2020,
            create_data = do_create_data )
    end
end

#create_region_tables(
        #    runname   = "main-results-$(DEFAULT_DATA)",
        #    whichdata = DEFAULT_DATA,
        #    numiter   = 1,
    #        year      = 2020 )

#for dsname in datasets
#        create_region_tables(
#            runname   = "main-results-"*dsname,
#            whichdata = dsname,
#            numiter   = 200 )
#end

    # pdir = "/home/graham_s/VirtualWorlds/projects/action_for_children/england/results/2020/"
    # outdir = pdir*"/test1/"
    # num_systems = 5
    # StayingPutModelDriver.create_main_tables( outdir, num_systems, :ccode )
    # StayingPutModelDriver.create_main_tables( outdir, num_systems, :rcode )
end


text:
### map

map(f::Function, r::AbstractFill) = Fill(f(getindex_value(r)), axes(r))

### Unary broadcasting

function broadcasted(::DefaultArrayStyle{N}, op, r::AbstractFill{T,N}) where {T,N}
    return Fill(op(getindex_value(r)), axes(r))
end

broadcasted(::DefaultArrayStyle, ::typeof(+), r::Zeros) = r
broadcasted(::DefaultArrayStyle, ::typeof(-), r::Zeros) = r
broadcasted(::DefaultArrayStyle, ::typeof(+), r::Ones) = r

broadcasted(::DefaultArrayStyle{N}, ::typeof(conj), r::Zeros{T,N}) where {T,N} = r
broadcasted(::DefaultArrayStyle{N}, ::typeof(conj), r::Ones{T,N}) where {T,N} = r
broadcasted(::DefaultArrayStyle{N}, ::typeof(real), r::Zeros{T,N}) where {T,N} = Zeros{real(T)}(r.axes)
broadcasted(::DefaultArrayStyle{N}, ::typeof(real), r::Ones{T,N}) where {T,N} = Ones{real(T)}(r.axes)
broadcasted(::DefaultArrayStyle{N}, ::typeof(imag), r::Zeros{T,N}) where {T,N} = Zeros{real(T)}(r.axes)
broadcasted(::DefaultArrayStyle{N}, ::typeof(imag), r::Ones{T,N}) where {T,N} = Zeros{real(T)}(r.axes)

### Binary broadcasting

function broadcasted(::DefaultArrayStyle, op, a::AbstractFill, b::AbstractFill)
    val = op(getindex_value(a), getindex_value(b))
    return Fill(val, broadcast_shape(axes(a), axes(b)))
end

_broadcasted_zeros(f, a, b) = Zeros{Base.Broadcast.combine_eltypes(f, (a, b))}(broadcast_shape(axes(a), axes(b)))
_broadcasted_ones(f, a, b) = Ones{Base.Broadcast.combine_eltypes(f, (a, b))}(broadcast_shape(axes(a), axes(b)))
_broadcasted_nan(f, a, b) = Fill(convert(Base.Broadcast.combine_eltypes(f, (a, b)), NaN), broadcast_shape(axes(a), axes(b)))

# TODO: remove at next breaking version
_broadcasted_zeros(a, b) = _broadcasted_zeros(+, a, b)
_broadcasted_ones(a, b) = _broadcasted_ones(+, a, b)

broadcasted(::DefaultArrayStyle, ::typeof(+), a::Zeros, b::Zeros) = _broadcasted_zeros(+, a, b)
broadcasted(::DefaultArrayStyle, ::typeof(+), a::Ones, b::Zeros) = _broadcasted_ones(+, a, b)
broadcasted(::DefaultArrayStyle, ::typeof(+), a::Zeros, b::Ones) = _broadcasted_ones(+, a, b)

broadcasted(::DefaultArrayStyle, ::typeof(-), a::Zeros, b::Zeros) = _broadcasted_zeros(-, a, b)
broadcasted(::DefaultArrayStyle, ::typeof(-), a::Ones, b::Zeros) = _broadcasted_ones(-, a, b)
broadcasted(::DefaultArrayStyle, ::typeof(-), a::Ones, b::Ones) = _broadcasted_zeros(-, a, b)

broadcasted(::DefaultArrayStyle{1}, ::typeof(+), a::Zeros{<:Any,1}, b::Zeros{<:Any,1}) = _broadcasted_zeros(+, a, b)
broadcasted(::DefaultArrayStyle{1}, ::typeof(+), a::Ones{<:Any,1}, b::Zeros{<:Any,1}) = _broadcasted_ones(+, a, b)
broadcasted(::DefaultArrayStyle{1}, ::typeof(+), a::Zeros{<:Any,1}, b::Ones{<:Any,1}) = _broadcasted_ones(+, a, b)

broadcasted(::DefaultArrayStyle{1}, ::typeof(-), a::Zeros{<:Any,1}, b::Zeros{<:Any,1}) = _broadcasted_zeros(-, a, b)
broadcasted(::DefaultArrayStyle{1}, ::typeof(-), a::Ones{<:Any,1}, b::Zeros{<:Any,1}) = _broadcasted_ones(-, a, b)

broadcasted(::DefaultArrayStyle, ::typeof(*), a::Zeros, b::Zeros) = _broadcasted_zeros(*, a, b)

# In following, need to restrict to <: Number as otherwise we cannot infer zero from type
# TODO: generalise to things like SVector
for op in (:*, :/)
    @eval begin
        broadcasted(::DefaultArrayStyle, ::typeof($op), a::Zeros, b::Ones) = _broadcasted_zeros($op, a, b)
        broadcasted(::DefaultArrayStyle, ::typeof($op), a::Zeros, b::Fill{<:Number}) = _broadcasted_zeros($op, a, b)
        broadcasted(::DefaultArrayStyle, ::typeof($op), a::Zeros, b::Number) = _broadcasted_zeros($op, a, b)
        broadcasted(::DefaultArrayStyle, ::typeof($op), a::Zeros, b::AbstractRange) = _broadcasted_zeros($op, a, b)
        broadcasted(::DefaultArrayStyle, ::typeof($op), a::Zeros, b::AbstractArray{<:Number}) = _broadcasted_zeros($op, a, b)
        broadcasted(::DefaultArrayStyle, ::typeof($op), a::Zeros, b::Base.Broadcast.Broadcasted) = _broadcasted_zeros($op, a, b)
        broadcasted(::DefaultArrayStyle{1}, ::typeof($op), a::Zeros, b::AbstractRange) = _broadcasted_zeros($op, a, b)
    end
end

for op in (:*, :\)
    @eval begin
        broadcasted(::DefaultArrayStyle, ::typeof($op), a::Ones, b::Zeros) = _broadcasted_zeros($op, a, b)
        broadcasted(::DefaultArrayStyle, ::typeof($op), a::Fill{<:Number}, b::Zeros) = _broadcasted_zeros($op, a, b)
        broadcasted(::DefaultArrayStyle, ::typeof($op), a::Number, b::Zeros) = _broadcasted_zeros($op, a, b)
        broadcasted(::DefaultArrayStyle, ::typeof($op), a::AbstractRange, b::Zeros) = _broadcasted_zeros($op, a, b)
        broadcasted(::DefaultArrayStyle, ::typeof($op), a::AbstractArray{<:Number}, b::Zeros) = _broadcasted_zeros($op, a, b)
        broadcasted(::DefaultArrayStyle, ::typeof($op), a::Base.Broadcast.Broadcasted, b::Zeros) = _broadcasted_zeros($op, a, b)
        broadcasted(::DefaultArrayStyle{1}, ::typeof($op), a::AbstractRange, b::Zeros) = _broadcasted_zeros($op, a, b)
    end
end

for op in (:*, :/, :\)
    @eval broadcasted(::DefaultArrayStyle, ::typeof($op), a::Ones, b::Ones) = _broadcasted_ones($op, a, b)
end

for op in (:/, :\)
    @eval broadcasted(::DefaultArrayStyle, ::typeof($op), a::Zeros{<:Number}, b::Zeros{<:Number}) = _broadcasted_nan($op, a, b)
end

# special case due to missing converts for ranges
_range_convert(::Type{AbstractVector{T}}, a::AbstractRange{T}) where T = a
_range_convert(::Type{AbstractVector{T}}, a::AbstractUnitRange) where T = convert(T,first(a)):convert(T,last(a))
_range_convert(::Type{AbstractVector{T}}, a::AbstractRange) where T = convert(T,first(a)):step(a):convert(T,last(a))

# TODO: replacing with the following will support more general broadcasting.
# function broadcasted(::DefaultArrayStyle{1}, ::typeof(*), a::AbstractFill, b::AbstractRange)
#     broadcast_shape(axes(a), axes(b)) # check axes
#     r1 = b[1] * getindex_value(a)
#     T = typeof(r1)
#     if length(b) == 1 # Need a fill, but for type stability use StepRangeLen
#         StepRangeLen{T}(r1, zero(T), length(a))
#     else
#         StepRangeLen{T}(r1, convert(T, getindex_value(a) * step(b)), length(b))
#     end
# end

# function broadcasted(::DefaultArrayStyle{1}, ::typeof(*), a::AbstractRange, b::AbstractFill)
#     broadcast_shape(axes(a), axes(b)) # check axes
#     r1 = a[1] * getindex_value(b)
#     T = typeof(r1)
#     if length(a) == 1 # Need a fill, but for type stability use StepRangeLen
#         StepRangeLen{T}(r1, zero(T), length(b))
#     else
#         StepRangeLen{T}(r1, convert(T, step(a) * getindex_value(b)), length(a))
#     end
# end

function broadcasted(::DefaultArrayStyle{1}, ::typeof(*), a::Ones{T,1}, b::AbstractRange{V}) where {T,V}
    broadcast_shape(axes(a), axes(b)) == axes(b) || throw(ArgumentError("Cannot broadcast $a and $b. Convert $b to a Vector first."))
    return _range_convert(AbstractVector{promote_type(T,V)}, b)
end

function broadcasted(::DefaultArrayStyle{1}, ::typeof(*), a::AbstractRange{V}, b::Ones{T,1}) where {T,V}
    broadcast_shape(axes(a), axes(b)) == axes(a) || throw(ArgumentError("Cannot broadcast $a and $b. Convert $b to a Vector first."))
    return _range_convert(AbstractVector{promote_type(T,V)}, a)
end

for op in (:+, -)
    @eval begin
        function broadcasted(::DefaultArrayStyle{1}, ::typeof($op), a::AbstractVector{T}, b::Zeros{V,1}) where {T,V}
            broadcast_shape(axes(a), axes(b)) == axes(a) || throw(ArgumentError("Cannot broadcast $a and $b. Convert $b to a Vector first."))
            LinearAlgebra.copy_oftype(a, promote_type(T,V))
        end

        broadcasted(::DefaultArrayStyle{1}, ::typeof($op), a::AbstractFill{T,1}, b::Zeros{V,1}) where {T,V} =
            Base.invoke(broadcasted, Tuple{DefaultArrayStyle, typeof($op), AbstractFill, AbstractFill}, DefaultArrayStyle{1}(), $op, a, b)
    end
end

function broadcasted(::DefaultArrayStyle{1}, ::typeof(+), a::Zeros{T,1}, b::AbstractVector{V}) where {T,V}
    broadcast_shape(axes(a), axes(b))
    LinearAlgebra.copy_oftype(b, promote_type(T,V))
end

broadcasted(::DefaultArrayStyle{1}, ::typeof(+), a::Zeros{V,1}, b::AbstractFill{T,1}) where {T,V} =
            Base.invoke(broadcasted, Tuple{DefaultArrayStyle, typeof(+), AbstractFill, AbstractFill}, DefaultArrayStyle{1}(), +, a, b)

# Need to prevent array-valued fills from broadcasting over entry
_broadcast_getindex_value(a::AbstractFill{<:Number}) = getindex_value(a)
_broadcast_getindex_value(a::AbstractFill) = Ref(getindex_value(a))

function broadcasted(::DefaultArrayStyle{1}, ::typeof(*), a::AbstractFill, b::AbstractRange)
    broadcast_shape(axes(a), axes(b)) == axes(b) || throw(ArgumentError("Cannot broadcast $a and $b. Convert $b to a Vector first."))
    return broadcasted(*, _broadcast_getindex_value(a), b)
end

function broadcasted(::DefaultArrayStyle{1}, ::typeof(*), a::AbstractRange, b::AbstractFill)
    broadcast_shape(axes(a), axes(b)) == axes(a) || throw(ArgumentError("Cannot broadcast $a and $b. Convert $b to a Vector first."))
    return broadcasted(*, a, _broadcast_getindex_value(b))
end

broadcasted(::DefaultArrayStyle{N}, op, r::AbstractFill{T,N}, x::Number) where {T,N} = Fill(op(getindex_value(r),x), size(r))
broadcasted(::DefaultArrayStyle{N}, op, x::Number, r::AbstractFill{T,N}) where {T,N} = Fill(op(x, getindex_value(r)), size(r))
broadcasted(::DefaultArrayStyle{N}, op, r::AbstractFill{T,N}, x::Ref) where {T,N} = Fill(op(getindex_value(r),x[]), size(r))
broadcasted(::DefaultArrayStyle{N}, op, x::Ref, r::AbstractFill{T,N}) where {T,N} = Fill(op(x[], getindex_value(r)), size(r))

ext: jl


text:
@info "Loading Caesar ROS specific utilities (using RobotOS)."

export RosbagSubscriber, loop!, getROSPyMsgTimestamp, nanosecond2datetime

## Load rosbag file parser

pushfirst!(PyVector(pyimport("sys")."path"), @__DIR__ )

rosbagReaderPy = pyimport("rosbagReader")
RosbagParser = rosbagReaderPy."RosbagParser"

## Common handler approach

mutable struct RosbagSubscriber
  bagfile::String
  channels::Vector{Symbol}
  callbacks::Dict{Symbol, Function}
  readers::Dict{Symbol,PyObject}
  syncBuffer::Dict{Symbol,Tuple{DateTime, Int}} # t,ns,msgdata
  nextMsgChl::Symbol
  nextMsgTimestamp::Tuple{DateTime, Int}
  # constructors
end
RosbagSubscriber(bagfile::AbstractString;
                  channels::Vector{Symbol}=Symbol[],
                  callbacks::Dict{Symbol,Function}=Dict{Symbol,Function}(),
                  readers::Dict{Symbol,PyObject}=Dict{Symbol,PyObject}(),
                  syncBuffer::Dict{Symbol,Tuple{DateTime, Int}}=Dict{Symbol,Tuple{DateTime, Int}}() ) = RosbagSubscriber(bagfile,channels,callbacks,readers,syncBuffer, :null, (unix2datetime(0),0))
#

# loss of accuracy (Julia only Millisecond)
function nanosecond2zoneddatetime(nsT::Int64)
  nano = nsT % 1_000_000_000
  secs = nsT - (nano % 1_000_000)
  secs /= 1_000_000_000
  ZonedDateTime(unix2datetime(secs), localzone())
end
@deprecate nanosecond2datetime(x...) nanosecond2zoneddatetime(x...)

function getROSPyMsgTimestamp(msgT::PyObject)
  msgNs = msgT.to_sec()
  # jlSeconds = isa(msg, PyObject) ? msgNs : msgNs
  jlSeconds = floor(Int64, Float64(msgNs))
  jlNanosec = msgT.to_nsec()%1000000000
  # try use regular seconds if no Nanosecond information is available
  jlNanosec = floor(Int,jlNanosec) == 0 && 0 < Float64(msgNs) % 1.0 |> abs ? Float64(msgNs) % 1.0 : jlNanosec
  (unix2datetime(jlSeconds), jlNanosec)
end

function loop!(rbs::RosbagSubscriber, args...)
  # figure out which channel is behind
  t1 = rbs.syncBuffer[rbs.channels[1]][1]
  times = (x->Nanosecond(rbs.syncBuffer[x][1]-t1)+Nanosecond(rbs.syncBuffer[x][2])).(rbs.channels)
  minT = minimum(times)
  idx = findfirst(x->x==minT, times)
  rbs.nextMsgChl = rbs.channels[idx]

  # get next event from that channel
  msg = rbs.readers[rbs.nextMsgChl].get_next_message()

  # try find event time
  msgT = msg[end]
  return if isa(msgT, PyObject)
    # update the syncBuffer
    rbs.syncBuffer[rbs.nextMsgChl] = rbs.nextMsgTimestamp = getROSPyMsgTimestamp(msgT)
    # call the callback
    rbs.callbacks[rbs.nextMsgChl](msg, args...)
    true
  else
    println("false, dont know how to handle message time as typeof(msgT)=$(typeof(msgT))")
    @show msg
    false
  end
end

function (rbs::RosbagSubscriber)( chl::AbstractString,
                                  callback::Function,
                                  args...;
                                  msgType=nothing )
  #
  cn = Symbol(string(chl))
  push!(rbs.channels, cn)
  rbs.callbacks[cn] = (m)->callback(m,args...)
  rbs.syncBuffer[cn] = (unix2datetime(0), 0)
  rbs.readers[cn] = RosbagParser(rbs.bagfile, chl)
end


text:
## --- Direct access to real libc system() function

    """
    ```julia
    system(cmdstr::AbstractString)
    ```

    Direct access to the command line through C's `system` function -- without
    stripping/sanitizing special characters,  in contrast to Julia's safer
    `run()` function. This allows pipelining, etc. in shell commands. Returns
    0 on success.
    """
    function system(cmdstr::AbstractString)
        return ccall((:system,), Int, (Cstring,), cmdstr)
    end
    export system

## --- Retain deprecated functions with matlab-like syntax, to avoid breakages in user scripts that may depend on them

    if ~ @isdefined linspace
        """
        ```julia
        linspace(l::Number,u::Number,n::Number)
        ```

        Returns a linearly spaced array with `n` points between the starting
        bound `l` and ending bound `u`
        """
        function linspace(l::Number,u::Number,n::Number)
            return range(l,stop=u,length=n)
        end
        export linspace
    end

    if ~ @isdefined contains
        """
        ```julia
        contains(haystack, needle)
        ```

        Converts both `haystack` and `needle` to strings (if not already strings)
        and checks whether `string(haystack)` contains `string(needle)`.
        """
        contains(haystack::AbstractString, needle::Union{AbstractString,Regex,AbstractChar}) = occursin(needle, haystack)
        contains(haystack, needle) = occursin(string(needle), string(haystack))
        export contains
    end

    if ~ @isdefined containsi
        """
        ```julia
        containsi(haystack, needle)
        ```

        Converts both `haystack` and `needle` to strings and checks whether
        `string(haystack)` contains `string(needle)`, ignoring case.
        """
        containsi(haystack::AbstractString, needle::Union{AbstractString,AbstractChar}) = occursin(lowercase(needle), lowercase(haystack))
        containsi(haystack, needle) = occursin(lowercase(string(needle)), lowercase(string(haystack)))
        export containsi
    end

## --- End of File


text:
using JuSwarm, StaticArrays, Test
import Optim

function ackleyfunc(x::AbstractVector)
    a = 20
    b = 0.2
    c = 2*π
    d = length(x)

    sum1 = 0.0
    sum2 = 0.0
    for i in 1:d
        sum1 += x[i]^2
        sum2 += cos(c*x[i])
    end
    return -a*exp(-b*sqrt(sum1/d))  - exp(sum2/d) + a + exp(1)
end

N = 20
opts = PSOOptions(N; SwarmSize = 200,
                     LowerBounds = SVector{N}(fill(-32.768, N, 1)),
                     UpperBounds = SVector{N}(fill(32.768, N, 1)),
                     HybridOptimizer = Optim.LBFGS(),
                     Display = "none",
                     UseParallel = true)

sol = psoptimize(ackleyfunc,opts)

@test sol.fbest <= sol.fbestPSO

@test sol.fbestPSO <= 1.0e-6

@test sol.fbest <= 1.0e-10

max_stars_repo_name: GrantHecht/JuSwarm

max_forks_repo_name: GrantHecht/JuSwarm


text:
using Dates, TimeZones

function testdateparse()
    tzabbrev = Dict("EST" => "+0500", "CST" => "+0600", "MST" => "+0700",  "PST" => "+0800")
    dtstr = "March 7 2009 7:30pm EST"
    for (k, v) in tzabbrev
        dtstr = replace(dtstr, k => v)
    end
    dtformat = dateformat"U dd yyyy HH:MMp zzzzz"
    dtime = TimeZones.parse(ZonedDateTime, dtstr, dtformat)
    println(Dates.format(dtime, dtformat))
end

testdateparse()

max_stars_repo_name: ethansaxenian/RosettaDecode

max_issues_repo_name: ethansaxenian/RosettaDecode

max_forks_repo_name: ethansaxenian/RosettaDecode


text:
# sample data

c0=parse("+P(x)")
c1=parse("-P(x),+P(f(x))")
c2=parse("-P(x),+Q(x,y),+R(y)")
c3=parse("-P(x),+R(g(x))")
c4=parse("-Q(a,g(b))")
c5=parse("+R(g(x))")
c6=parse("+R(f(x))")

pr1=[makeastep(:resolution, [:x], parse("[+P(x,a)]"), 1, [:x], parse("[-P(x,x)]"),1, [:v], EmptyClause, [:a]),
 makeastep(:reduction, [:x], parse("[+P(x,a),+P(x,x)]"), 1, 2, parse("[+P(a,a)]"), [:a])
]

pr2=[
makeastep(:resolution, [:x], parse("[+P(x,a)]"), 1, [:x], parse("[-P(x,x)]"),1, [:v], EmptyClause, [:a]),
makeastep(:resolution, [:x], parse("[+P(x,a),+Q(x,a)]"), 1, [:x], parse("[-P(x,x)]"),1, [:v], parse("[+Q(a,a)]"), [:a]),
makeastep(:reduction, [:x], parse("[+P(x,a),+P(x,x)]"), 1, 2, parse("[+P(a,a)]"), [:a])
]

cls1 = [
 parse("[x,y].[+P(x),+Q(x,y)]"),
 parse("[y,x].[+P(a),-Q(x,y)]"),
 parse("[x,y].[+Q(x,x),-P(x)]"),
 parse("[].[-P(b)]"),
 parse("[x].[-P(x)]"),
 parse("[x].[-Q(x,x)]")
]

cls2 = [
 parse("[x,y].[+P(x),+Q(x,y)]"),
 parse("[y,x].[+P(a),-Q(x,y)]"),
 parse("[x,y].[+Q(x,x),-P(x)]"),
 parse("[].[-P(b),+Q(b,b)]"),
 parse("[x].[-P(x),+Q(x,x)]")
]

cls3 = [
 parse("[x,y].[+Q(x,x),+R(x),-P(x),+R(x)]"),
 parse("[y,x].[+P(a),-R(a),-Q(x,y),-R(a)]"),
 parse("[x].[-P(b),+R(b),+R(x),+Q(b,b)]"),
 parse("[x,y].[+P(x),+Q(x,y),-R(x),-R(y)]"),
 parse("[y,x].[+P(a),-Q(x,y),-R(a)]"),
 parse("[x,y].[-P(x),+Q(x,x),+R(x,f(a)),+R(x,y)]")
]

res1=[
 parse("[y].[+Q(b,y)]"),
]

# 0 means contradiction :([])

cdb1=addcdb([],vcat(cls1,res1))
db1=makedb(vcat(cls1,res1))

ipr1=[
 makeastep(:resolution,[:x],4,1,[:x,:y],1,1,[:y],7, [:b,:y]),
 makeastep(:resolution,[:x],7,1,[:y],6,1,[],     0, [:b,:y])
]

cdb2=addcdb([],cls2)
db2=makedb(cls2)
cdb3=addcdb([],cls3)
db3=makedb(cls3)

#==
# Image
==#
# input
Cls1 = [
 parse("[x].[+P(x),+Q(x)]"),
 parse("[x].[+P(a),-Q(x)]"),
 parse("[x].[+Q(x),-P(x)]"),
 parse("[].[-P(b)]"),
 parse("[x].[-P(x)]")
]

# cid : index of Cls

#==
 PG,sign,pred => (cid,lid) => literal
 CDB,cid -> [1] == vars
 CDB,cid -> [2] == literals
==#

# cid is the index of CDB1 also
CDB1=[
 ([:x],parse("[+P(x),+Q(x)]")),
 ([:x],parse("[+P(a),-Q(x)]")),
 ([:x],parse("[+Q(x),-P(x)]")),
 (Array{Symbol}([]),parse("[-P(b)]")),
 ([:x],parse("[-P(x)]"))
]

LDB1=Dict((1,1)=>(parse("+P(x)")),
        (1,2)=>(parse("+Q(x)")),
        (2,1)=>(parse("+P(a)")),
	(2,2)=>(parse("-Q(x)")),
	(3,1)=>(parse("+Q(x)")),
	(3,2)=>(parse("-P(x)")),
	(4,1)=>(parse("-P(b)")),
	(5,1)=>(parse("-P(x)"))
)

PG1 = Dict(
   :P => [[(1,1),(2,1)],[(3,2),(4,1),(5,1)]],
   :Q => [[(1,2),(3,1)],[(2,2)]]
)

max_stars_repo_name: sazare/cheapViews

max_issues_repo_name: sazare/cheapViews

max_forks_repo_name: sazare/cheapViews


text:
# using Documenter
# doctest(ActuaryUtilities)

max_stars_repo_name: alecloudenback/ActuaryUtilities

max_issues_repo_name: alecloudenback/ActuaryUtilities

max_forks_repo_name: alecloudenback/ActuaryUtilities


text:
state(prob::AbstractProblem, net, args...) = state(input_type(net), prob, net, args...)
state(T::Type{<:Number}, prob::AbstractProblem, net) = state(T, basis(prob), net)
#state(T::Type{<:Number}, prob::LRhoKLocalOpProblem, net) = state_lut(T, basis(prob), net)
state_lut(prob::AbstractProblem, net, args...) = state_lut(input_type(net), prob, net, args...)
state_lut(T::Type{<:Number}, prob::AbstractProblem, net) = state_lut(T, basis(prob), net)

function state(T::Type{<:Number}, hilb::Basis, net)
    !is_homogeneous(hilb) && error("Could not generate a state.")
    sys_state = _homogeneous_system_state(T, first(hilb.bases),
                                          length(hilb.bases), net)

    state = _network_state(sys_state, net)
    return state
end

function state_lut(T::Type{<:Number}, hilb::Basis, net)
    !is_homogeneous(hilb) && error("Could not generate a state.")
    sys_state = _homogeneous_system_state(T, first(hilb.bases),
                                          length(hilb.bases), net)

    state = _lut_state(sys_state, net)
    return state
end

function _lut_state(T::Type{<:Number}, hilb::Basis, net::MatrixNet)
    bare_state = state(T, basis(prob), net)
    state = DoubleState(ModifiedState(row(bare_state)))
    lut   = lookup(net)

    isnothing(lut) && return state
    return LUState(state, lut)
end

function _homogeneous_system_state(T::Type{<:Number}, hilb::Basis, nsites, net::Union{MatrixNet, KetNet})
    loc_size = first(hilb.shape)
    return NAryState(T, loc_size, nsites)
end

_network_state(sys_state::State, net::Union{MatrixNet, PureNet}) =
    DoubleState(sys_state)

_network_state(sys_state::State, net::KetNet) =
    return sys_state

function _lut_state(sys_state::State, net::Union{MatrixNet, PureNet})
    state = DoubleState(ModifiedState(sys_state))
    lut   = lookup(net)

    isnothing(lut) && return state
    return LUState(state, lut)
end


text:
export observmat, dependcol

function observmat(T, m, n, func, otherargs=())
    H = zeros(T, m, n)
    params = zeros(T, n)
    for i in 1:n
        params[i] = one(T)
        H[:, i] = func(params, otherargs...)::Vector{T}
        params[i] = zero(T)
    end
    H
end

function dependcol(Hs, prec=10)
    np = size(Hs, 2)

    Q1, R1 = qr(Hs)
    R1_diag = round.(diag(R1), digits=prec)

    dbi = Int[]
    ddi = Int[]
    for (i, e) in enumerate(R1_diag)
        if e != 0
            push!(dbi, i)
        else
            push!(ddi, i)
        end
    end
    dbn = length(dbi)

    P = Matrix{Int}(I, np, np)[:, [dbi; ddi]]
    Pb = P[:, 1:dbn]
    Pd = P[:, dbn+1:end]

    _ , Rbd1 = qr(Hs*P)
    Rb1 = Rbd1[1:dbn, 1:dbn]
    Rd1 = Rbd1[1:dbn, dbn+1:end]

    Kd = round.(inv(Rb1) * Rd1, digits=prec)

    Pb, Pd, Kd
end


text:
using GPUArrays, Test

@testset "JLArray" begin
    GPUArrays.test(JLArray)
end


text:
# Augment a null progress meter which disables it
import ProgressMeter.next!
struct NullProgress <: ProgressMeter.AbstractProgress
    NullProgress()=new()
end
next!(::NullProgress) = nothing

# Function which is essentially min(1, exp(p_ - p)),  but handles
# exceptional cases gracefully
@inline function _accept_prob(p, p_, FT)
    if !isfinite(p_) # p_ is not finite => force reject
        return zero(FT)
    elseif !isfinite(p) # p_ is finite but p not => force accept
        return one(FT)
    else # both finite, the standard case:
        return (p_ >= p) ? one(FT) : exp(p_ - p)
    end
end


text:
module Tests
using SparseRegressionAlgorithms
S = SparseRegressionAlgorithms
using Base.Test

macro display(ex)
    :(display($ex))
end

@testset "sweep" begin
    n, p = 1000, 5
    x = randn(n, p)
    y = x * collect(1:p) + randn(n)
    w = rand(n)
    @display S.sweepreg(x, y)
end
end

max_stars_repo_name: joshday/SparseRegressionAlgorithms

max_issues_repo_name: joshday/SparseRegressionAlgorithms

max_forks_repo_name: joshday/SparseRegressionAlgorithms


text:
# Borrowed/adapted from https://andreaskroepelin.de/blog/plutoslides/
export present_button
export Foldable
export TwoCollumn, ThreeCollumn

# My Minimal tweaks
export TwoCollumnWideLeft, TwoCollumnWideRight
export ChooseDisplayMode # combines present_button and WidthOverDocs

present_button() = html"<button onclick='present()'>present</button>"

struct Foldable{C}
    title::String
    content::C
end

function Base.show(io, mime::MIME"text/html", fld::Foldable)
    write(io,"$(fld.title)
")
    show(io, mime, fld.content)
    write(io,"
")
end

struct TwoColumn{L, R}
    left::L
    right::R
end

function Base.show(io, mime::MIME"text/html", tc::TwoColumn)
    write(io, """

""")
    show(io, mime, tc.left)
    write(io, """

""")
    show(io, mime, tc.right)
    write(io, """

""")
end

struct TwoColumnWideLeft{L, R}
    left::L
    right::R
end

function Base.show(io, mime::MIME"text/html", tc::TwoColumnWideLeft)
    write(io, """

""")
    show(io, mime, tc.left)
    write(io, """

""")
    show(io, mime, tc.right)
    write(io, """

""")
end

struct TwoColumnWideRight{L, R}
    left::L
    right::R
end

function Base.show(io, mime::MIME"text/html", tc::TwoColumnWideRight)
    write(io, """

""")
    show(io, mime, tc.left)
    write(io, """

""")
    show(io, mime, tc.right)
    write(io, """

""")
end

struct ThreeColumn{L, C, R}
    left::L
    center::C
    right::R
end

function Base.show(io, mime::MIME"text/html", tc::ThreeColumn)
    write(io, """

""")
    show(io, mime, tc.left)
    write(io, """

""")
    show(io, mime, tc.center)
    write(io, """

""")
    show(io, mime, tc.right)
    write(io, """

""")
end

""" Provides checkbox to toggle full width and present mode. """
function ChooseDisplayMode(;wide::Bool=false, present::Bool = false)  # Adapted from PlutoThemes.jl
        checked = wide ? "checked" : ""
        checked_present_mode = present ? "checked" : ""
        init = wide ? "toggle_width(document.getElementById('width-over-livedocs'))" : ""
        return HTML("""

<input
        type="checkbox"
        id="width-over-livedocs"
        name="width-over-livedocs"
    onclick="window.plutoOptIns.toggle_width(this)"
        $(checked)>

        Full Width Mode

<input
        type="checkbox"
        id="present-mode"
        name="present-mode"
        onclick="present()"
        $(checked_present_mode)>

        Present Mode

""")
end


text:
"""
    Womble

The `Womble` abstract type is a catch-all for specific wombling outputs.
"""
abstract type Womble end

"""
    TriangulationWomble{T <: Number} <: Womble

A set of data (and co-ordinates) that are irregularly arranged in space are of
type `TriangulationWomble` after having been passed through `wombling` - the
fields in this type are

- `m`, a *vector* of rate of change at each (x,y) co-ordinate
- `θ`, a *vector* of direction of change at each (x,y) co-ordinate
- `x` and `y`, the coordinates of the barycenter of each triangle in the plan

Note that the type of `x` and `y` should be the same as the element type of ` m`
and `θ`, because these values are all used when calculating the rate of change
and that `x` and `y` correspond to latitude and longitude respectively.
"""
mutable struct TriangulationWomble{T<:Number} <: Womble
    m::Vector{T}
    θ::Vector{T}
    x::Vector{T}
    y::Vector{T}
end

"""
    LatticeWomble{T <: Number} <: Womble

A set of data (and co-ordinates) that are regularly arranged in space are of
type `LatticeWomble` after having been passed through `wombling` - the fields in
this type are

- `m`, a *matrix* of rate of change at each (x,y) co-ordinate
- `θ`, a *matrix* of direction of change at each (x,y) co-ordinate
- `x` and `y`, the coordinates of the center of each cell

Note that the type of `x` and `y` should be the same as the element type of ` m`
and `θ`, because these values are all used when calculating the rate of change
and that `x` and `y` correspond to latitude and longitude respectively.
"""
mutable struct LatticeWomble{T<:Number} <: Womble
    m::Matrix{T}
    θ::Matrix{T}
    x::Vector{T}
    y::Vector{T}
end


text:
module TestUsesProcesses
using Folds
using Folds.Testing: test_uses_processes
test_uses_processes(DistributedEx())
end  # module


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

"""
Support for sparse arrays. Provides `AbstractSparseArray` and subtypes.
"""
module SparseArrays

using Base: ReshapedArray, promote_op, setindex_shape_check, to_shape, tail
using Base.Sort: Forward
using Base.LinAlg: AbstractTriangular, PosDefException

import Base: +, -, *, \, /, &, |, xor, ==
import Base: A_mul_B!, Ac_mul_B, Ac_mul_B!, At_mul_B, At_mul_B!
import Base: A_mul_Bc, A_mul_Bt, Ac_mul_Bc, At_mul_Bt
import Base: At_ldiv_B, Ac_ldiv_B, A_ldiv_B!
import Base.LinAlg: At_ldiv_B!, Ac_ldiv_B!, A_rdiv_B!, A_rdiv_Bc!

import Base: @get!, acos, acosd, acot, acotd, acsch, asech, asin, asind, asinh,
    atan, atand, atanh, broadcast!, chol, conj!, cos, cosc, cosd, cosh, cospi, cot,
    cotd, coth, count, csc, cscd, csch, adjoint!, diag, diff, done, dot, eig,
    exp10, exp2, eye, findn, floor, hash, indmin, inv, issymmetric, istril, istriu,
    log10, log2, lu, next, sec, secd, sech, show, sin,
    sinc, sind, sinh, sinpi, squeeze, start, sum, summary, tan,
    tand, tanh, trace, transpose!, tril!, triu!, trunc, vecnorm, abs, abs2,
    broadcast, ceil, complex, cond, conj, convert, copy, copy!, adjoint, diagm,
    exp, expm1, factorize, find, findmax, findmin, findnz, float, getindex,
    vcat, hcat, hvcat, cat, imag, indmax, ishermitian, kron, length, log, log1p, max, min,
    maximum, minimum, norm, one, promote_eltype, real, reshape, rot180,
    rotl90, rotr90, round, scale!, setindex!, similar, size, transpose, tril,
    triu, vec, permute!, map, map!

export AbstractSparseArray, AbstractSparseMatrix, AbstractSparseVector,
    SparseMatrixCSC, SparseVector, blkdiag, droptol!, dropzeros!, dropzeros,
    issparse, nonzeros, nzrange, rowvals, sparse, sparsevec, spdiagm, speye, spones,
    sprand, sprandn, spzeros, nnz, permute

include("abstractsparse.jl")
include("sparsematrix.jl")
include("sparsevector.jl")
include("higherorderfns.jl")

include("linalg.jl")
if Base.USE_GPL_LIBS
    include("umfpack.jl")
    include("cholmod.jl")
    include("spqr.jl")
end

end

max_stars_repo_name: xorJane/julia

max_issues_repo_name: xorJane/julia

max_forks_repo_name: xorJane/julia


text:
"Sequential Monte Carlo module - MCMC and PF algorithm compositionally used"
module BaytesSMC

############################################################################################
#Import modules
import BaytesCore:
    BaytesCore,
    update!,
    infer,
    results,
    init,
    init!,
    propose,
    propose!,
    propagate,
    propagate!,
    result!,
    get_result,
    get_sym,

    generate_showvalues,
    ResamplingMethod,
    shuffle!,
    resample!,
    weight!,
    jitter!

using BaytesCore:
    BaytesCore,
    AbstractAlgorithm,
    AbstractTune,
    AbstractConfiguration,
    AbstractDiagnostics,
    AbstractKernel,
    AbstractConstructor,
    Updater,
    Iterator,
    issmaller,
    computeESS,
    grab,
    to_NamedTuple,
    UpdateBool,
    UpdateTrue,
    UpdateFalse,
    update,
    split,
    ChainsTune,
    ParameterWeights,
    ResampleTune,
    ModelParameterBuffer,
    SampleDefault

using ModelWrappers:
    ModelWrappers,
    ModelWrapper,
    Tagged,
    Objective,
    DiffObjective,
    ℓObjectiveResult,
    ℓDensityResult,
    ℓGradientResult
import ModelWrappers: predict, generate, dynamics

import BaytesFilters: ParticleKernel
using BaytesMCMC, BaytesFilters, BaytesPMCMC

using DocStringExtensions:
    DocStringExtensions, TYPEDEF, TYPEDFIELDS, FIELDS, SIGNATURES, FUNCTIONNAME
using ArgCheck: ArgCheck, @argcheck
using UnPack: UnPack, @unpack, @pack!

using Random: Random, AbstractRNG, GLOBAL_RNG
using Statistics: Statistics, mean, std, sqrt, quantile, var, cor
#using Polyester: Polyester, @batch

############################################################################################
# Import sub-folder
include("Core/Core.jl")
include("Kernels/Kernels.jl")

############################################################################################
export
    # BaytesCore
    UpdateBool,
    UpdateTrue,
    UpdateFalse
    propose,
    propose!,
    propagate,
    propagate!,
    ResamplingMethod,
    infer,
    SampleDefault,

    # SMC
    update!,
    init,
    init!,
    resample!,

    #ModelWrappers
    predict,
    generate,
    dynamics

end


text:
function cstrt_fodor_ngon(n)
if mod(log2(n),1)==0 && n>=8
    # initialization
    v(u) = (pi/2-(n/4+1)*u)/(n/4-1);
    d(u) = (cos(v(u))-sin(u)+sin(u+v(u)))/(cos(u)+sin(v(u)));
    F(u) = 1+d(u)^2-2*d(u)*cos(u) - (2-2*cos(v(u)));
    u0 = find_zero(F,(pi/n, 2*pi/(n+4)));
    v0 = (pi/2-(n/4+1)*u0)/(n/4-1);
    d0 = (cos(v0)-sin(u0)+sin(u0+v0))/(cos(u0)+sin(v0));
    r = ones(Int(n/4+1));
    for i = 1:Int(n/8)
        r[2*i] = d0;
    end
    x = zeros(Int(n/4+1));
    x[1] = u0;
    x[2:end-1] .= u0+v0;
    x[end] = u0;
    p = zeros(Int(n/4)); q = zeros(Int(n/4));
    p[1] = r[1]*sin(x[1]); q[1] = r[1]*cos(x[1]);
    for i = 2:Int(n/4)
        p[i] = p[i-1] - (-1)^i*r[i]*sin(sum(x[1:i]));
        q[i] = q[i-1] - (-1)^i*r[i]*cos(sum(x[1:i]));
    end
    # construction
    a = zeros(n-1); b = zeros(n-1);
    a[Int(n/2-1)] = p[1]; a[Int(n/2+1)] = -a[Int(n/2-1)];
    b[Int(n/2-1)] = q[1]; b[Int(n/2+1)] = b[Int(n/2-1)];
    if n>=16
        for i = 2:Int(n/4-1)
            a[Int(mod(i*(n/2-1),n))] = p[i];
            a[Int(n-mod(i*(n/2-1),n))] = -a[Int(mod(i*(n/2-1),n))];
            b[Int(mod(i*(n/2-1),n))] = q[i];
            b[Int(n-mod(i*(n/2-1),n))] = b[Int(mod(i*(n/2-1),n))];
            a[Int(mod((i-1)*(n/2-1)+n/2,n))] = a[Int(mod((i-1)*(n/2-1),n))] - (-1)^i*sin(sum(x[1:i-1])+v0);
            a[Int(n-mod((i-1)*(n/2-1)+n/2,n))] = -a[Int(mod((i-1)*(n/2-1)+n/2,n))];
            b[Int(mod((i-1)*(n/2-1)+n/2,n))] = b[Int(mod((i-1)*(n/2-1),n))] - (-1)^i*cos(sum(x[1:i-1])+v0);
            b[Int(n-mod((i-1)*(n/2-1)+n/2,n))] = b[Int(mod((i-1)*(n/2-1)+n/2,n))];
        end
    end
    a[Int(3*n/4)] = p[Int(n/4)]; a[Int(n/4)] = -a[Int(3*n/4)];
    b[Int(3*n/4)] = q[Int(n/4)]; b[Int(n/4)] = b[Int(3*n/4)];
    a[Int(3*n/4+1)] = a[Int(n/4+1)]-sin(sum(x[1:Int(n/4-1)])+v0); a[Int(n/4-1)] = -a[Int(3*n/4+1)];
    b[Int(3*n/4+1)] = b[Int(n/4+1)]-cos(sum(x[1:Int(n/4-1)])+v0); b[Int(n/4-1)] = b[Int(3*n/4+1)];
    a[Int(n/2)] = 0; b[Int(n/2)] = d0;
    return(a,b)
end
end

max_stars_repo_name: cbingane/optigon

max_issues_repo_name: cbingane/optigon

max_forks_repo_name: cbingane/optigon


text:
#!/usr/bin/env julia

module GeoSender

    using ZMQ
    using JSON

    function send_to_py(data)
        context = Context()
        data_sender = Socket(context, PUSH)
        ZMQ.connect(data_sender, "tcp://127.0.0.1:5556")

        to_send = JSON.json(data)
        ZMQ.send(data_sender, to_send)
        ZMQ.close(data_sender)
        ZMQ.close(context)
    end
end

max_stars_repo_name: giannamars/AutomatedMBAM

max_issues_repo_name: giannamars/AutomatedMBAM

max_forks_repo_name: giannamars/AutomatedMBAM


text:
module TestCat

using Test, Random, DataFrames
const ≅ = isequal

#
# hcat
#
@testset "hcat" begin
    nvint = [1, 2, missing, 4]
    nvstr = ["one", "two", missing, "four"]

    df2 = DataFrame([nvint, nvstr])
    df3 = DataFrame([nvint])
    df4 = convert(DataFrame, [1:4 1:4])
    df5 = DataFrame([Union{Int, Missing}[1,2,3,4], nvstr])

    ref_df = copy(df3)
    dfh = hcat(df3, df4, makeunique=true)
    @test ref_df ≅ df3 # make sure that df3 is not mutated by hcat
    @test size(dfh, 2) == 3
    @test names(dfh) ≅ [:x1, :x1_1, :x2]
    @test dfh[!, :x1] ≅ df3[!, :x1]
    @test dfh ≅ DataFrames.hcat!(DataFrame(), df3, df4, makeunique=true)

    dfa = DataFrame(a=[1,2])
    dfb = DataFrame(b=[3,missing])
    @test hcat(dfa, dfb) ≅ [dfa dfb]

    dfh3 = hcat(df3, df4, df5, makeunique=true)
    @test names(dfh3) == [:x1, :x1_1, :x2, :x1_2, :x2_1]
    @test dfh3 ≅ hcat(dfh, df5, makeunique=true)
    @test dfh3 ≅ DataFrames.hcat!(DataFrame(), df3, df4, df5, makeunique=true)

    @test df2 ≅ DataFrames.hcat!(df2, makeunique=true)
end

@testset "hcat: copying" begin
    df = DataFrame(x=1:3)
    @test hcat(df)[!, 1] == df[!, 1]
    @test hcat(df)[!, 1] !== df[!, 1]
    hdf = hcat(df, df, makeunique=true)
    @test hdf[!, 1] == df[!, 1]
    @test hdf[!, 1] !== df[!, 1]
    @test hdf[!, 2] == df[!, 1]
    @test hdf[!, 2] !== df[!, 1]
    @test hdf[!, 1] == hdf[!, 2]
    @test hdf[!, 1] !== hdf[!, 2]
    hdf = hcat(df, df, df, makeunique=true)
    @test hdf[!, 1] == df[!, 1]
    @test hdf[!, 1] !== df[!, 1]
    @test hdf[!, 2] == df[!, 1]
    @test hdf[!, 2] !== df[!, 1]
    @test hdf[!, 3] == df[!, 1]
    @test hdf[!, 3] !== df[!, 1]
    @test hdf[!, 1] == hdf[!, 2]
    @test hdf[!, 1] !== hdf[!, 2]
    @test hdf[!, 1] == hdf[!, 3]
    @test hdf[!, 1] !== hdf[!, 3]
    @test hdf[!, 2] == hdf[!, 3]
    @test hdf[!, 2] !== hdf[!, 3]
    x = [4, 5, 6]
    hdf = hcat(df, x)
    @test hdf[!, 1] == df[!, 1]
    @test hdf[!, 1] !== df[!, 1]
    @test hdf[!, 2] !== x
    hdf = hcat(x, df)
    @test hdf[!, 2] == df[!, 1]
    @test hdf[!, 2] !== df[!, 1]
    @test hdf[!, 1] !== x
end

@testset "hcat ::AbstractDataFrame" begin
    df = DataFrame(A = repeat('A':'C', inner=4), B = 1:12)
    gd = groupby(df, :A)
    answer = DataFrame(A = fill('A', 4), B = 1:4, A_1 = 'B', B_1 = 5:8, A_2 = 'C', B_2 = 9:12)
    @test hcat(gd..., makeunique=true) == answer
    answer = answer[:, 1:4]
    @test hcat(gd[1], gd[2], makeunique=true) == answer
end

@testset "hcat ::AbstractDataFrame" begin
    df = DataFrame(A = repeat('A':'C', inner=4), B = 1:12)
    gd = groupby(df, :A)
    answer = DataFrame(A = fill('A', 4), B = 1:4, A_1 = 'B', B_1 = 5:8, A_2 = 'C', B_2 = 9:12)
    @test hcat(gd..., makeunique=true) == answer
    answer = answer[:, 1:4]
    @test hcat(gd[1], gd[2], makeunique=true) == answer
end

@testset "hcat ::AbstractVectors" begin
    df = DataFrame()
    DataFrames.hcat!(df, CategoricalVector{Union{Int,Missing}}(1:10), makeunique=true)
    @test df[!, 1] == CategoricalVector(1:10)
    DataFrames.hcat!(df, 1:10, makeunique=true)
    @test df[!, 2] == collect(1:10)
    DataFrames.hcat!(df, collect(1:10), makeunique=true)
    @test df[!, 3] == collect(1:10)

    df = DataFrame()
    df2 = hcat(CategoricalVector{Union{Int,Missing}}(1:10), df, makeunique=true)
    @test isempty(df)
    @test df2[!, 1] == collect(1:10)
    @test names(df2) == [:x1]
    ref_df = copy(df2)
    df3 = hcat(11:20, df2, makeunique=true)
    @test df2 == ref_df
    @test df3[!, 1] == collect(11:20)
    @test names(df3) == [:x1, :x1_1]

    @test_throws ArgumentError hcat("a", df, makeunique=true)
    @test_throws ArgumentError hcat(df, "a", makeunique=true)
end

@testset "hcat: copycols" begin
    df1 = DataFrame(a=1:3)
    df2 = DataFrame(b=1:3)
    dfv = view(df2, :, :)
    x = [1,2,3]

    df3 = hcat(df1)
    @test df3 == df1
    @test df3.a !== df1.a
    df3 = hcat(df1, copycols=true)
    @test df3 == df1
    @test df3.a !== df1.a
    df3 = hcat(df1, copycols=false)
    @test df3 == df1
    @test df3.a === df1.a

    df3 = hcat(df1, df2)
    @test names(df3) == [:a, :b]
    @test df3.a == df1.a
    @test df3.b == df2.b
    @test df3.a !== df1.a
    @test df3.b !== df2.b
    df3 = hcat(df1, df2, copycols=true)
    @test names(df3) == [:a, :b]
    @test df3.a == df1.a
    @test df3.b == df2.b
    @test df3.a !== df1.a
    @test df3.b !== df2.b
    df3 = hcat(df1, df2, copycols=false)
    @test names(df3) == [:a, :b]
    @test df3.a === df1.a
    @test df3.b === df2.b

    df3 = hcat(df1, dfv)
    @test names(df3) == [:a, :b]
    @test df3.a == df1.a
    @test df3.b == df2.b
    @test df3.a !== df1.a
    @test df3.b !== df2.b
    df3 = hcat(df1, dfv, copycols=true)
    @test names(df3) == [:a, :b]
    @test df3.a == df1.a
    @test df3.b == df2.b
    @test df3.a !== df1.a
    @test df3.b !== df2.b
    df3 = hcat(df1, dfv, copycols=false)
    @test names(df3) == [:a, :b]
    @test df3.a === df1.a
    @test df3.b === dfv.b

    df3 = hcat(df1, x)
    @test names(df3) == [:a, :x1]
    @test df3.a == df1.a
    @test df3.x1 == x
    @test df3.a !== df1.a
    @test df3.x1 !== x
    df3 = hcat(df1, x, copycols=true)
    @test names(df3) == [:a, :x1]
    @test df3.a == df1.a
    @test df3.x1 == x
    @test df3.a !== df1.a
    @test df3.x1 !== x
    df3 = hcat(df1, x, copycols=false)
    @test names(df3) == [:a, :x1]
    @test df3.a === df1.a
    @test df3.x1 === x

    df3 = hcat(x, df1)
    @test names(df3) == [:x1, :a]
    @test df3.a == df1.a
    @test df3.x1 == x
    @test df3.a !== df1.a
    @test df3.x1 !== x
    df3 = hcat(x, df1, copycols=true)
    @test names(df3) == [:x1, :a]
    @test df3.a == df1.a
    @test df3.x1 == x
    @test df3.a !== df1.a
    @test df3.x1 !== x
    df3 = hcat(x, df1, copycols=false)
    @test names(df3) == [:x1, :a]
    @test df3.a === df1.a
    @test df3.x1 === x

    df3 = hcat(dfv, x, df1)
    @test names(df3) == [:b, :x1, :a]
    @test df3.a == df1.a
    @test df3.b == dfv.b
    @test df3.x1 == x
    @test df3.a !== df1.a
    @test df3.b !== dfv.b
    @test df3.x1 !== x
    df3 = hcat(dfv, x, df1, copycols=true)
    @test names(df3) == [:b, :x1, :a]
    @test df3.a == df1.a
    @test df3.b == dfv.b
    @test df3.x1 == x
    @test df3.a !== df1.a
    @test df3.b !== dfv.b
    @test df3.x1 !== x
    df3 = hcat(dfv, x, df1, copycols=false)
    @test names(df3) == [:b, :x1, :a]
    @test df3.a === df1.a
    @test df3.b === dfv.b
    @test df3.x1 === x
end
#
# vcat
#

@testset "vcat" begin
    missing_df = DataFrame()
    df = DataFrame([3.0  2.0  2.0
                    2.0  2.0  2.0
                    3.0  1.0  2.0
                    3.0  3.0  3.0])
    df[!, 3] = Int.(df[!, 3])

    @test vcat(missing_df) == DataFrame()
    @test vcat(missing_df, missing_df) == DataFrame()
    @test vcat(missing_df) == DataFrame()
    @test vcat(missing_df, missing_df) == DataFrame()
    @test vcat(missing_df, df) == df
    @test vcat(df, missing_df) == df
    @test eltypes(vcat(df, df)) == Type[Float64, Float64, Int]
    @test size(vcat(df, df)) == (size(df, 1) * 2, size(df, 2))
    res = vcat(df, df)
    @test res[1:size(df, 1), :] == df
    @test res[(1+size(df, 1)):end, :] == df
    res = vcat(df, df, df)
    @test eltypes(res) == Type[Float64, Float64, Int]
    @test size(res) == (size(df, 1) * 3, size(df, 2))

    s = size(df, 1)
    for i in 1:3
        @test res[1+(i-1)*s:i*s, :] == df
    end

    alt_df = deepcopy(df)
    @test vcat(df, alt_df) == DataFrame([[3.0,2.0,3.0,3.0,3.0,2.0,3.0,3.0],
                                         [2.0,2.0,1.0,3.0,2.0,2.0,1.0,3.0],
                                         [2,2,2,3,2,2,2,3]])

    # Don't fail on non-matching types
    df[!, 1] = zeros(Int, nrow(df))
    @test vcat(df, alt_df) == DataFrame([[0.0,0.0,0.0,0.0,3.0,2.0,3.0,3.0],
                                         [2.0,2.0,1.0,3.0,2.0,2.0,1.0,3.0],
                                         [2,2,2,3,2,2,2,3]])

    df1 = DataFrame(A=Int[], B=Float64[])
    df2 = DataFrame(B=1.0, A=1)
    @test vcat(df2, df1, df2, df1) == vcat(df2, df2)

    df = DataFrame(A=1:5, B=11:15, C=21:25)
    @test vcat(view(df, 1:2, :), view(df, 3:5, [3,2,1])) == df
    @test vcat(view(df, 1:2, [1,2,3,1,2,3]), view(df, 3:5, [3,2,1,1,2,3])) == df
    @test all(==(df[1, :]), eachrow(vcat(view(df, [1,1,1], [1,2,3,1,2,3]),
                                         view(df, [1,1,1], [3,2,1,1,2,3]))))
end

@testset "vcat copy" begin
    df = DataFrame(x=1:3)
    @test vcat(df)[!, 1] == df[!, 1]
    @test vcat(df)[!, 1] !== df[!, 1]
end

@testset "vcat >2 args" begin
    empty_dfs = [DataFrame(), DataFrame(), DataFrame()]
    @test vcat(empty_dfs...) == reduce(vcat, empty_dfs) == DataFrame()
    @test reduce(vcat, Tuple(empty_dfs)) == DataFrame()

    df = DataFrame(x = trues(1), y = falses(1))
    dfs = [df, df, df]
    @test vcat(dfs...) == reduce(vcat, dfs) == DataFrame(x = trues(3), y = falses(3))
    @test reduce(vcat, Tuple(dfs)) == DataFrame(x = trues(3), y = falses(3))
end

@testset "vcat mixed coltypes" begin
    df = vcat(DataFrame([[1]], [:x]), DataFrame([[1.0]], [:x]))
    @test df == DataFrame([[1.0, 1.0]], [:x])
    @test typeof.(eachcol(df)) == [Vector{Float64}]
    df = vcat(DataFrame([[1]], [:x]), DataFrame([["1"]], [:x]))
    @test df == DataFrame([[1, "1"]], [:x])
    @test typeof.(eachcol(df)) == [Vector{Any}]
    df = vcat(DataFrame([Union{Missing, Int}[1]], [:x]), DataFrame([[1]], [:x]))
    @test df == DataFrame([[1, 1]], [:x])
    @test typeof.(eachcol(df)) == [Vector{Union{Missing, Int}}]
    df = vcat(DataFrame([CategoricalArray([1])], [:x]), DataFrame([[1]], [:x]))
    @test df == DataFrame([[1, 1]], [:x])
    @test df[!, :x] isa Vector{Int}
    df = vcat(DataFrame([CategoricalArray([1])], [:x]),
              DataFrame([Union{Missing, Int}[1]], [:x]))
    @test df == DataFrame([[1, 1]], [:x])
    @test df[!, :x] isa Vector{Union{Int, Missing}}
    df = vcat(DataFrame([CategoricalArray([1])], [:x]),
              DataFrame([CategoricalArray{Union{Int, Missing}}([1])], [:x]))
    @test df == DataFrame([[1, 1]], [:x])
    @test df[!, :x] isa CategoricalVector{Union{Int, Missing}}
    df = vcat(DataFrame([Union{Int, Missing}[1]], [:x]),
              DataFrame([["1"]], [:x]))
    @test df == DataFrame([[1, "1"]], [:x])
    @test typeof.(eachcol(df)) == [Vector{Any}]
    df = vcat(DataFrame([CategoricalArray([1])], [:x]),
              DataFrame([CategoricalArray(["1"])], [:x]))
    @test df == DataFrame([[1, "1"]], [:x])
    @test df[!, :x] isa CategoricalVector{Any}
    df = vcat(DataFrame([trues(1)], [:x]), DataFrame([[false]], [:x]))
    @test df == DataFrame([[true, false]], [:x])
    @test typeof.(eachcol(df)) == [Vector{Bool}]
end

@testset "vcat out of order" begin
    df1 = DataFrame(A = 1:3, B = 4:6, C = 7:9)
    df2 = DataFrame([2x for x in eachcol(df1)], reverse(names(df1)))
    @test vcat(df1, df2) == DataFrame(A = [1, 2, 3, 14, 16, 18],
                                      B = [4, 5, 6, 8, 10, 12],
                                      C = [7, 8, 9, 2, 4, 6])
    # test with cols keyword argument
    @test vcat(df1, df2, cols = :equal) == DataFrame(A = [1, 2, 3, 14, 16, 18],
                                                     B = [4, 5, 6, 8, 10, 12],
                                                     C = [7, 8, 9, 2, 4, 6])
    @test vcat(df1, df1, df2) == DataFrame(A = [1, 2, 3, 1, 2, 3, 14, 16, 18],
                                           B = [4, 5, 6, 4, 5, 6, 8, 10, 12],
                                           C = [7, 8, 9, 7, 8, 9, 2, 4, 6])
    @test vcat(df1, df2, df2) == DataFrame(A = [1, 2, 3, 14, 16, 18, 14, 16, 18],
                                           B = [4, 5, 6, 8, 10, 12, 8, 10, 12],
                                           C = [7, 8, 9, 2, 4, 6, 2, 4, 6])
    @test vcat(df2, df1, df2) == DataFrame(C = [2, 4, 6, 7, 8, 9, 2, 4, 6],
                                           B = [8, 10, 12, 4, 5, 6, 8, 10, 12],
                                           A = [14, 16, 18, 1, 2, 3, 14, 16, 18])
    @test size(vcat(df1, df1, df1, df2, df2, df2)) == (18, 3)
    df3 = df1[:, [1, 3, 2]]
    res = vcat(df1, df1, df1, df2, df2, df2, df3, df3, df3, df3)
    @test res == reduce(vcat, [df1, df1, df1, df2, df2, df2, df3, df3, df3, df3])
    @test res == reduce(vcat, (df1, df1, df1, df2, df2, df2, df3, df3, df3, df3))
    @test size(res) == (30, 3)
    @test res[1:3,:] == df1
    @test res[4:6,:] == df1
    @test res[7:9,:] == df1
    @test res[10:12,:] == df2[:, names(res)]
    @test res[13:15,:] == df2[:, names(res)]
    @test res[16:18,:] == df2[:, names(res)]
    @test res[19:21,:] == df3[:, names(res)]
    @test res[22:24,:] == df3[:, names(res)]
    @test res[25:27,:] == df3[:, names(res)]
    df1 = DataFrame(A = 1, B = 2)
    df2 = DataFrame(B = 12, A = 11)
    df3 = DataFrame(A = [1, 11], B = [2, 12])
    @test [df1; df2] == df3 == reduce(vcat, [df1, df2])
    @test df3 == reduce(vcat, (df1, df2))
end

@testset "vcat with cols=:union" begin
    df1 = DataFrame(A = 1:3, B = 4:6)
    df2 = DataFrame(A = 7:9)
    df3 = DataFrame(B = 4:6, A = 1:3)

    @test vcat(df1, df2; cols = :union) ≅
        DataFrame(A = [1, 2, 3, 7, 8, 9],
                  B = [4, 5, 6, missing, missing, missing])
    @test vcat(df1, df2; cols = :union) ≅ reduce(vcat, [df1, df2]; cols = :union)
    @test vcat(df1, df2; cols = :union) ≅ reduce(vcat, (df1, df2); cols = :union)
    @test vcat(df1, df2, df3; cols = :union) ≅
        DataFrame(A = [1, 2, 3, 7, 8, 9, 1, 2, 3],
                  B = [4, 5, 6, missing, missing, missing, 4, 5, 6])
    @test vcat(df1, df2, df3; cols = :union) ≅ reduce(vcat, [df1, df2, df3]; cols = :union)
    @test vcat(df1, df2, df3; cols = :union) ≅ reduce(vcat, (df1, df2, df3); cols = :union)
end

@testset "vcat with cols=:intersect" begin
    df1 = DataFrame(A = 1:3, B = 4:6)
    df2 = DataFrame(A = 7:9)
    df3 = DataFrame(A = 10:12, C = 13:15)

    @test vcat(df1, df2; cols = :intersect) ≅ DataFrame(A = [1, 2, 3, 7, 8, 9])
    @test vcat(df1, df2; cols = :intersect) ≅ reduce(vcat, [df1, df2]; cols = :intersect)
    @test vcat(df1, df2; cols = :intersect) ≅ reduce(vcat, (df1, df2); cols = :intersect)
    @test vcat(df1, df2, df3; cols = :intersect) ≅ DataFrame(A = [1, 2, 3, 7, 8, 9,
                                                                     10, 11, 12])
    @test vcat(df1, df2, df3; cols = :intersect) ≅ reduce(vcat, [df1, df2, df3]; cols = :intersect)
    @test vcat(df1, df2, df3; cols = :intersect) ≅ reduce(vcat, (df1, df2, df3); cols = :intersect)
end

@testset "vcat with cols::Vector" begin
    df1 = DataFrame(A = 1:3, B = 4:6)
    df2 = DataFrame(A = 7:9)
    df3 = DataFrame(A = 10:12, C = 13:15)

    @test vcat(df1, df2; cols = [:A, :B, :C]) ≅
        DataFrame(A = [1, 2, 3, 7, 8, 9],
                  B = [4, 5, 6, missing, missing, missing],
                  C = [missing, missing, missing, missing, missing, missing])
    @test vcat(df1, df2; cols = [:A, :B, :C]) ≅ reduce(vcat, [df1, df2]; cols = [:A, :B, :C])
    @test vcat(df1, df2; cols = [:A, :B, :C]) ≅ reduce(vcat, (df1, df2); cols = [:A, :B, :C])

    @test vcat(df1, df2, df3; cols = [:A, :B, :C]) ≅
        DataFrame(A = [1, 2, 3, 7, 8, 9, 10, 11, 12],
                  B = [4, 5, 6, missing, missing, missing, missing, missing, missing],
                  C = [missing, missing, missing, missing, missing, missing, 13, 14, 15])
    @test vcat(df1, df2, df3; cols = [:A, :B, :C]) ≅ reduce(vcat, [df1, df2, df3]; cols = [:A, :B, :C])
    @test vcat(df1, df2, df3; cols = [:A, :B, :C]) ≅ reduce(vcat, (df1, df2, df3); cols = [:A, :B, :C])

    df1 = DataFrame(A=Int[], B=Float64[])
    df2 = DataFrame(B=1.0, A=1)
    @test vcat(df1, df2, df1, cols=[:A, :C, :B]) ≅ DataFrame(A=1, C=missing, B=1.0)
    @test vcat(df1, df2, df1, cols=[:A, :C, :B]) ≅ reduce(vcat, [df1, df2, df1], cols=[:A, :C, :B])
    @test vcat(df1, df2, df1, cols=[:A, :C, :B]) ≅ reduce(vcat, (df1, df2, df1), cols=[:A, :C, :B])
    @test vcat(df1, df2, df2, cols=[:C]) ≅ DataFrame(C=[missing, missing])
    @test vcat(df1, df2, df2, cols=[:C]) ≅ reduce(vcat, [df1, df2, df2], cols=[:C])
    @test vcat(df1, df2, df2, cols=[:C]) ≅ reduce(vcat, (df1, df2, df2), cols=[:C])
    @test_throws ArgumentError vcat(df1, df2, df2, cols=[:C, :C])
    @test_throws ArgumentError reduce(vcat, [df1, df2, df2], cols=[:C, :C])
    @test_throws ArgumentError reduce(vcat, (df1, df2, df2), cols=[:C, :C])
end

@testset "vcat errors" begin
    df1 = DataFrame(A = 1:3, B = 1:3)
    df2 = DataFrame(A = 1:3)
    # right missing 1 column
    err = @test_throws ArgumentError vcat(df1, df2)
    @test err.value.msg == "column(s) B are missing from argument(s) 2"
    # left missing 1 column
    err = @test_throws ArgumentError vcat(df2, df1)
    @test err.value.msg == "column(s) B are missing from argument(s) 1"
    # multiple missing 1 column
    err1 = @test_throws ArgumentError vcat(df1, df2, df2, df2, df2, df2)
    err2 = @test_throws ArgumentError reduce(vcat, [df1, df2, df2, df2, df2, df2])
    @test_throws ArgumentError reduce(vcat, (df1, df2, df2, df2, df2, df2))
    @test err1.value.msg == err2.value.msg == "column(s) B are missing from argument(s) 2, 3, 4, 5 and 6"
    # argument missing >1 columns
    df1 = DataFrame(A = 1:3, B = 1:3, C = 1:3, D = 1:3, E = 1:3)
    err = @test_throws ArgumentError vcat(df1, df2)
    @test err.value.msg == "column(s) B, C, D and E are missing from argument(s) 2"
    # >1 arguments missing >1 columns
    err = @test_throws ArgumentError vcat(df1, df2, df2, df2, df2)
    @test err.value.msg == "column(s) B, C, D and E are missing from argument(s) 2, 3, 4 and 5"
    # missing columns throws error
    df1 = DataFrame(A = 1, B = 1)
    df2 = DataFrame(A = 1)
    df3 = DataFrame(B = 1, A = 1)
    err = @test_throws ArgumentError vcat(df1, df2, df3)
    @test err.value.msg == "column(s) B are missing from argument(s) 2"
    # unique columns for both sides
    df1 = DataFrame(A = 1, B = 1, C = 1, D = 1)
    df2 = DataFrame(A = 1, C = 1, D = 1, E = 1, F = 1)
    err = @test_throws ArgumentError vcat(df1, df2)
    @test err.value.msg == "column(s) E and F are missing from argument(s) 1, and column(s) B are missing from argument(s) 2"
    err = @test_throws ArgumentError vcat(df1, df1, df2, df2)
    @test err.value.msg == "column(s) E and F are missing from argument(s) 1 and 2, and column(s) B are missing from argument(s) 3 and 4"
    df3 = DataFrame(A = 1, B = 1, C = 1, D = 1, E = 1)
    err = @test_throws ArgumentError vcat(df1, df2, df3)
    @test err.value.msg == "column(s) E and F are missing from argument(s) 1, column(s) B are missing from argument(s) 2, and column(s) F are missing from argument(s) 3"
    err = @test_throws ArgumentError vcat(df1, df1, df2, df2, df3, df3)
    @test err.value.msg == "column(s) E and F are missing from argument(s) 1 and 2, column(s) B are missing from argument(s) 3 and 4, and column(s) F are missing from argument(s) 5 and 6"
    err = @test_throws ArgumentError vcat(df1, df1, df1, df2, df2, df2, df3, df3, df3)
    @test err.value.msg == "column(s) E and F are missing from argument(s) 1, 2 and 3, column(s) B are missing from argument(s) 4, 5 and 6, and column(s) F are missing from argument(s) 7, 8 and 9"
    # df4 is a superset of names found in all other DataFrames and won't be shown in error
    df4 = DataFrame(A = 1, B = 1, C = 1, D = 1, E = 1, F = 1)
    err = @test_throws ArgumentError vcat(df1, df2, df3, df4)
    @test err.value.msg == "column(s) E and F are missing from argument(s) 1, column(s) B are missing from argument(s) 2, and column(s) F are missing from argument(s) 3"
    err = @test_throws ArgumentError vcat(df1, df1, df2, df2, df3, df3, df4, df4)
    @test err.value.msg == "column(s) E and F are missing from argument(s) 1 and 2, column(s) B are missing from argument(s) 3 and 4, and column(s) F are missing from argument(s) 5 and 6"
    err = @test_throws ArgumentError vcat(df1, df1, df1, df2, df2, df2, df3, df3, df3, df4, df4, df4)
    @test err.value.msg == "column(s) E and F are missing from argument(s) 1, 2 and 3, column(s) B are missing from argument(s) 4, 5 and 6, and column(s) F are missing from argument(s) 7, 8 and 9"
    err = @test_throws ArgumentError vcat(df1, df2, df3, df4, df1, df2, df3, df4, df1, df2, df3, df4)
    @test err.value.msg == "column(s) E and F are missing from argument(s) 1, 5 and 9, column(s) B are missing from argument(s) 2, 6 and 10, and column(s) F are missing from argument(s) 3, 7 and 11"
end

@testset "vcat with view" begin
    x = view(DataFrame(A = Vector{Union{Missing, Int}}(1:3)), 2:2, :)
    y = DataFrame(A = 4:5)
    @test vcat(x, y) == DataFrame(A = [2, 4, 5]) == reduce(vcat, [x, y]) == reduce(vcat, (x, y))
end

end # module


text:
#-------------------------------------------------------------------
#* EMSO Model Library (EML) Copyright (C) 2004 - 2007 ALSOC.
#*
#* This LIBRARY is free software; you can distribute it and/or modify
#* it under the therms of the ALSOC FREE LICENSE as available at
#* http://www.enq.ufrgs.br/alsoc.
#*
#* EMSO Copyright (C) 2004 - 2007 ALSOC, original code
#* from http://www.rps.eng.br Copyright (C) 2002-2004.
#* All rights reserved.
#*
#* EMSO is distributed under the therms of the ALSOC LICENSE as
#* available at http://www.enq.ufrgs.br/alsoc.
#*
#*----------------------------------------------------------------------
#* Author: Maur좩cio Carvalho Maciel, Paula B. Staudt, Rafael P. Soares
#* $Id$
#*--------------------------------------------------------------------
type splitter_column
	splitter_column()=begin
		new(
			stream(Dict{Symbol,Any}(
				:Brief=>"Inlet stream",
				:PosX=>0.5,
				:PosY=>0,
				:Symbol=>"_{in}"
			)),
			stream(Dict{Symbol,Any}(
				:Brief=>"Reflux stream",
				:PosX=>0.25,
				:PosY=>1,
				:Symbol=>"_{reflux}"
			)),
			stream(Dict{Symbol,Any}(
				:Brief=>"Distillate stream",
				:PosX=>0.75,
				:PosY=>1,
				:Symbol=>"_{distillate}"
			)),
			fraction(Dict{Symbol,Any}(
				:Brief=>"split of the outlet Reflux stream",
				:Default=>0.33
			)),
			fraction(Dict{Symbol,Any}(
				:Brief=>"split of the outlet Distillate stream",
				:Default=>0.33
			)),
			positive(Dict{Symbol,Any}(
				:Brief=>"Reflux Ratio",
				:Default=>10,
				:Lower=>0.05
			)),
			[
				:(SplitFlow_RefluxStream*(1 + RefluxRatio) = RefluxRatio),
				:(SplitFlow_RefluxStream + SplitFlow_DistillateStream = 1),
				:(Reflux.F = Inlet.F * SplitFlow_RefluxStream),
				:(Inlet.F = Reflux.F + Distillate.F),
				:(Reflux.z = Inlet.z),
				:(Distillate.z = Inlet.z),
				:(Reflux.P = Inlet.P),
				:(Distillate.P = Inlet.P),
				:(Reflux.h = Inlet.h),
				:(Distillate.h = Inlet.h),
				:(Reflux.T = Inlet.T),
				:(Distillate.T = Inlet.T),
				:(Reflux.v = Inlet.v),
				:(Distillate.v = Inlet.v),
			],
			[
				"Reflux Ratio","Normalize Flow Ratios","Flow","","Composition","","Pressure","","Enthalpy","","Temperature","","Vapourisation Fraction","",
			],
			[:Inlet,:Reflux,:Distillate,:SplitFlow_RefluxStream,:SplitFlow_DistillateStream,:RefluxRatio,]
		)
	end
	Inlet::stream
	Reflux::stream
	Distillate::stream
	SplitFlow_RefluxStream::fraction
	SplitFlow_DistillateStream::fraction
	RefluxRatio::positive
	equations::Array{Expr,1}
	equationNames::Array{String,1}
	variables::Array{Symbol,1}
	attributes::Dict{Symbol,Any}
end
export splitter_column
function setEquationFlow(in::splitter_column)
	#Reflux.F*RefluxRatio = SplitFlow_RefluxStream*(Reflux.F*RefluxRatio + Reflux.F);
	addEquation(1)
	addEquation(2)
	addEquation(3)
	addEquation(4)
	addEquation(5)
	addEquation(6)
	addEquation(7)
	addEquation(8)
	addEquation(9)
	addEquation(10)
	addEquation(11)
	addEquation(12)
	addEquation(13)
	addEquation(14)
end
function atributes(in::splitter_column,_::Dict{Symbol,Any})
	fields::Dict{Symbol,Any}=Dict{Symbol,Any}()
	fields[:Pallete]=true
	fields[:Icon]="icon/splitter_column"
	fields[:Brief]="Splitter with 2 outlet streams to be used with column section model"
	fields[:Info]="== Assumptions ==
*Thermodynamics equilibrium
*Adiabatic

== Specify ==
* The inlet stream
* One Split Flow of the outlet stream:
**SplitFlow_RefluxStream: split of the outlet Reflux stream
**SplitFlow_DistillateStream: split of the outlet Distillate stream

OR

* The inlet stream and the RefluxRatio
"
	drive!(fields,_)
	return fields
end
splitter_column(_::Dict{Symbol,Any})=begin
	newModel=splitter_column()
	newModel.attributes=atributes(newModel,_)
	newModel
end


text:
struct AWAP <: RasterDataSource end

layers(::Type{AWAP}) = (:solar, :rainfall, :vprpress09, :vprpress15, :tmin, :tmax)

date_step(::Type{<:AWAP}) = Day(1)

# AWAP files dont all have matching extents.
has_matching_layer_size(::Type{<:AWAP}) = false

@doc """
AWAP <: RasterDataSource

Daily weather data from the Australian Water Availability Project, developed by CSIRO.

See: [www.csiro.au/awap](http://www.csiro.au/awap/)

The available layers are: `$(layers(AWAP))`.
""" AWAP

const AWAP_PATHSEGMENTS = (
    solar = ("solar", "solarave", "daily"),
    rainfall = ("rainfall", "totals", "daily"),
    vprpress09 = ("vprp", "vprph09", "daily"),
    vprpress15 = ("vprp", "vprph15", "daily"),
    tmin = ("temperature", "minave", "daily"),
    tmax = ("temperature", "maxave", "daily"),
)
# Add ndvi monthly?  ndvi, ndviave, month

"""
    getraster(source::Type{AWAP}, [layer]; date)

Download data from the [`AWAP`](@ref) weather dataset, from
[www.csiro.au/awap](http://www.csiro.au/awap/).

The AWAP dataset contains ASCII `.grid` files.

# Arguments

- `layer` `Symbol` or `Tuple` of `Symbol` for `layer`s in `$(layers(AWAP))`. Without a
    `layer` argument, all layers will be downloaded, and a `NamedTuple` of paths returned.

# Keywords

- `date`: a `DateTime`, `AbstractVector` of `DateTime` or a `Tuple` of start and end dates.
    For multiple dates, A `Vector` of multiple filenames will be returned.
    AWAP is available with a daily timestep.

# Example

Download rainfall for the first month of 2001:

```julia
julia> getraster(AWAP, :rainfall; date=Date(2001, 1, 1):Day(1):Date(2001, 1, 31))

31-element Vector{String}:
 "/your/path/AWAP/rainfall/totals/20010101.grid"
 "/your/path/AWAP/rainfall/totals/20010102.grid"
 ...
 "/your/path/AWAP/rainfall/totals/20010131.grid"
```

Returns the filepath/s of the downloaded or pre-existing files.
"""
getraster(T::Type{AWAP}, layer::Union{Tuple,Symbol}; date) = _getraster(T, layer, date)

function _getraster(T::Type{AWAP}, layer::Union{Tuple,Symbol}, dates::Tuple{<:Any,<:Any})
    _getraster(T, layer, date_sequence(T, dates))
end
function _getraster(T::Type{AWAP}, layers::Union{Tuple,Symbol}, dates::AbstractArray)
    _getraster.(T, Ref(layers), dates)
end
function _getraster(T::Type{<:AWAP}, layers::Tuple, date::Dates.TimeType)
    _map_layers(T, layers, date)
end
function _getraster(T::Type{AWAP}, layer::Symbol, date::Dates.TimeType)
    _check_layer(T, layer)
    mkpath(_rasterpath(T, layer))
    raster_path = rasterpath(T, layer; date=date)
    if !isfile(raster_path)
        zip_path = zippath(T, layer; date=date)
        _maybe_download(zipurl(T, layer; date=date), zip_path)
        run(`uncompress $zip_path -f`)
    end
    return raster_path
end

rasterpath(T::Type{AWAP}) = joinpath(rasterpath(), "AWAP")
rasterpath(T::Type{AWAP}, layer; date::Dates.AbstractTime) =
    joinpath(_rasterpath(T, layer), rastername(T, layer; date))
_rasterpath(T::Type{AWAP}, layer) = joinpath(rasterpath(T), AWAP_PATHSEGMENTS[layer][1:2]...)
rastername(T::Type{AWAP}, layer; date::Dates.AbstractTime) =
    joinpath(_date2string(T, date) * ".grid")

function zipurl(T::Type{AWAP}, layer; date)
    s = AWAP_PATHSEGMENTS[layer]
    d = _date2string(T, date)
    # The actual zip name has the date twice, which is weird.
    # So we getraster in to a different name as there no output
    # name flages for `uncompress`. It's ancient.
    uri = URI(scheme="http", host="www.bom.gov.au", path="/web03/ncc/www/awap")
    joinpath(uri, s..., "grid/0.05/history/nat/$d$d.grid.Z")
end
zipname(T::Type{AWAP}, layer; date) = _date2string(T, date) * ".grid.Z"
zippath(T::Type{AWAP}, layer; date) =
    joinpath(_rasterpath(T, layer), zipname(T, layer; date))

_dateformat(::Type{AWAP}) = DateFormat("yyyymmdd")

max_forks_repo_name: cesaraustralia/RasterDataSources


text:
abstract Light <: Compose3DNode

using Colors

export pointlight, spotlight, ambientlight
#Ambient Light is applied globally to all objects.
immutable AmbientLight <: Light
    color::Color
end

ambientlight(color::AbstractString) = ambientlight(parse(Colorant, color))
ambientlight(color::Color=colorant"white") = AmbientLight(color)

resolve(box::Absolute3DBox, light::AmbientLight) = light

#Like a light bulb. Light shines in all directions.
immutable PointLight <: Light
    position::Vec3
    color::Color
    intensity::Float64
    distance::Length
end

PointLight(x::Length, y::Length, z::Length, color::Color, intensity::Float64,
           distance::Length) =
    PointLight((x, y, z), color, intensity, distance)

pointlight(x::Length, y::Length, z::Length, color::Color=colorant"white";
    intensity::Float64=1.0, distance=0mm) =
    PointLight(x, y, z, color, intensity, distance)

pointlight(x::Length, y::Length, z::Length, color::AbstractString;
    intensity::Float64=1.0, distance=0mm) =
    PointLight(x, y, z, parse(Colorant, color),intensity,distance)

function resolve(box::Absolute3DBox, light::PointLight)
    absposition = resolve(box, light.position)
    absdistance = resolve(box, light.distance)
    PointLight(absposition, light.color, light.intensity, absdistance)
end

#PointLight casting shadow in one direction.
immutable SpotLight <: Light
    position::Vec3
    color::Color
    intensity::Float64
    distance::Length
    angle::Float64 #Degrees
    exponent::Float64
    shadow::Bool
end

SpotLight(x::Length, y::Length, z::Length, color::Color, intensity::Float64,
          distance::Length, angle::Float64, exponent::Float64, shadow::Bool) =
    SpotLight((x, y, z), color, intensity, distance, angle, exponent, shadow)

spotlight(x::Length,y::Length,z::Length,color::Color=colorant"white";
          intensity::Float64=1.0, distance=0mm, angle::Float64=60.0,
          exponent::Float64=8.0, shadow::Bool=false) =
    SpotLight(x, y, z, color, intensity, distance, angle, exponent, shadow)

spotlight(x::Length, y::Length, z::Length, color::AbstractString;
    intensity::Float64=1.0, distance=0mm, angle::Float64=60.0,
    exponent::Float64=8.0, shadow::Bool=false) =
    SpotLight(x,y,z,parse(Colorant, color),intensity,distance,angle,exponent,shadow)

function resolve(box::Absolute3DBox, light::SpotLight)
    absposition = resolve(box, light.position)
    absdistance = resolve(box, light.distance)
    SpotLight(
        absposition,
        light.color,
        light.intensity,
        absdistance,
        light.angle,
        light.exponent,
        light.shadow
    )
end


text:
# This file is a part of AstroLib.jl. License is MIT "Expat".
# Copyright (C) 2016 Mosè Giordano.

using AstroLib
using Base.Test

include("utils-tests.jl")
include("misc-tests.jl")

# Dummy calls to "show" for new data types, just to increase code coverage.
show(DevNull, AstroLib.planets["mercury"])
show(DevNull, AstroLib.observatories["ca"])


text:
using ProximalOperators: ProximableFunction
using RecursiveArrayTools: ArrayPartition
import ProximalOperators: gradient!, gradient

struct ComposeAffine <: ProximableFunction
    f
    A
    b
end

function compose_affine_gradient!(y, g::ComposeAffine, x)
    res = g.A * x .+ g.b
    gradres, v = gradient(g.f, res)
    mul!(y, adjoint(g.A), gradres)
    return v
end

gradient!(y, g::ComposeAffine, x) = compose_affine_gradient!(y, g, x)
gradient!(y::ArrayPartition, g::ComposeAffine, x::ArrayPartition) = compose_affine_gradient!(y, g, x)

function ProximalOperators.gradient(h::ComposeAffine, x::ArrayPartition)
    grad_fx = similar(x)
    fx = gradient!(grad_fx, h, x)
    return grad_fx, fx
end


text:
struct TabularItem{T} <: Item
    data::T
    columns
end


text:
"""
Class for Gaussian Processes models

```julia
GP(X::AbstractArray{T}, y::AbstractArray, kernel::Kernel;
    noise::Real=1e-5, opt_noise::Bool=true, verbose::Int=0,
    optimizer::Bool=Adam(α=0.01),atfrequency::Int=1,
    mean::Union{<:Real,AbstractVector{<:Real},PriorMean}=ZeroMean(),
    IndependentPriors::Bool=true,ArrayType::UnionAll=Vector)
```

Argument list :

**Mandatory arguments**

 - `X` : input features, should be a matrix N×D where N is the number of observation and D the number of dimension
 - `y` : input labels, can be either a vector of labels for multiclass and single output or a matrix for multi-outputs (note that only one likelihood can be applied)
 - `kernel` : covariance function, can be either a single kernel or a collection of kernels for multiclass and multi-outputs models

**Keyword arguments**
 - `noise` : Initial noise of the model
 - `opt_noise` : Flag for optimizing the noise σ=Σ(y-f)^2/N
 - `mean` : Option for putting a prior mean
 - `verbose` : How much does the model print (0:nothing, 1:very basic, 2:medium, 3:everything)
 - `optimizer` : Optimizer for kernel hyperparameters (to be selected from [GradDescent.jl](https://github.com/jacobcvt12/GradDescent.jl)) or set it to `false` to keep hyperparameters fixed
 - `IndependentPriors` : Flag for setting independent or shared parameters among latent GPs
 - `atfrequency` : Choose how many variational parameters iterations are between hyperparameters optimization
 - `mean` : PriorMean object, check the documentation on it [`MeanPrior`](@ref meanprior)
 - `ArrayType` : Option for using different type of array for storage (allow for GPU usage)
"""
mutable struct GP{T<:Real,TLikelihood<:Likelihood{T},TInference<:Inference{T},TGP<:Abstract_GP{T},N} <: AbstractGP{T,TLikelihood,TInference,TGP,N}
    X::Matrix{T} #Feature vectors
    y::Vector #Output (-1,1 for classification, real for regression, matrix for multiclass)
    nSamples::Int64 # Number of data points
    nDim::Int64 # Number of covariates per data point
    nFeatures::Int64 # Number of features of the GP (equal to number of points)
    nLatent::Int64 # Number pf latent GPs
    f::NTuple{N,TGP} # Vector of latent GPs
    likelihood::TLikelihood
    inference::TInference
    verbose::Int64 #Level of printing information
    atfrequency::Int64
    Trained::Bool
end

function GP(X::AbstractArray{T}, y::AbstractArray,kernel::Kernel;
                noise::Real=1e-5, opt_noise::Bool=true, verbose::Int=0,
                optimizer::Union{Optimizer,Nothing,Bool}=Adam(α=0.01),atfrequency::Int=1,
                mean::Union{<:Real,AbstractVector{<:Real},PriorMean}=ZeroMean(), variance::Real = 1.0,
                ArrayType::UnionAll=Vector) where {T<:Real}
            likelihood = GaussianLikelihood(noise,opt_noise=opt_noise)
            inference = Analytic()
            X,y,nLatent,likelihood = check_data!(X,y,likelihood)

            nFeatures = nSamples = size(X,1); nDim = size(X,2);
            if isa(optimizer,Bool)
                optimizer = optimizer ? Adam(α=0.01) : nothing
            end

            latentf = ntuple(_->_GP{T}(nFeatures,kernel,mean,variance,optimizer),nLatent)

            likelihood = init_likelihood(likelihood,inference,nLatent,nSamples,nFeatures)
            inference = init_inference(inference,nLatent,nSamples,nSamples,nSamples)
            inference.xview = view(X,:,:)
            inference.yview = view_y(likelihood,y,1:nSamples)
            model = GP{T,GaussianLikelihood{T},typeof(inference),_GP{T},1}(X,y,nFeatures,
            nDim, nFeatures, nLatent,latentf,likelihood,inference,
            verbose,atfrequency,false)
            computeMatrices!(model)
            model.Trained = true
            return model
end

function Base.show(io::IO,model::GP{T,<:Likelihood,<:Inference}) where {T}
    print(io,"Gaussian Process with a $(model.likelihood) infered by $(model.inference) ")
end

get_y(model::GP) = model.inference.yview
get_Z(model::GP) = [model.inference.xview]


text:
include(joinpath(pathof(GroupsCore), "..", "..", "test", "conformance_test.jl"))

@testset "GroupsCore interface conformance" begin
    G = PermGroup(perm"(1,2,3,4,5)", perm"(1,2)")
    test_Group_interface(G)
    test_GroupElement_interface(rand(G, 2)...)

    @test gens(SymmetricGroup(1)) == Perm{Int}[]
    @test gens(SymmetricGroup(2)) == [perm"(1,2)"]
    @test gens(SymmetricGroup(3)) == [perm"(1,2,3)", perm"(1,2)(3)"]
end


text:
using LambdaTAME: TAME_param_search_profiled,  TAME_param_search, TAME, TAME_profiled
using LambdaTAME: setup_tame_data
@testset "TAME" begin

    β = 1.0
    α = 0.5
    tol = 1e-6
    max_iter = 15
    @testset "Type Stability" begin

        @suppress_out begin

            for (A_ten,B_ten) in [(A_TOST,B_TOST),(A_UST,A_UST),(A_UST_Cycle,B_UST_Cycle)]
                @inferred TAME_param_search_profiled(A_TOST,B_TOST)
                @inferred TAME_param_search(A_TOST,B_TOST)

                @inferred TAME(A_TOST, B_TOST, β, max_iter,tol,α)
                @inferred TAME_profiled(A_TOST, B_TOST, β, max_iter,tol,α)
            end
        end

    end

    @testset "TOST === UST when k = 3" begin
        #ensure the code gives the same results

        A_Ti,B_Ti = setup_tame_data(A_TOST,B_TOST)
        A_Mi,B_Mi = setup_tame_data(A_UST,B_UST)

        @testset "setup code" begin
            @test all([Set([Tuple(x) for x in A_Mi[i]]) == Set(A_Ti[i]) for i in 1:A_UST.n])
            @test all([Set([Tuple(x) for x in B_Mi[i]]) == Set(B_Ti[i]) for i in 1:B_UST.n])
        end

        @testset "power method" begin

            x_TOST, tri_match, match_TOST  = TAME(A_TOST, B_TOST, β, max_iter,tol,α)
            x_UST, motif_match, match_UST = TAME(A_UST, B_UST, β, max_iter,tol,α)

            @test norm(x_TOST - x_UST)/norm(x_UST) < round_off_bound(x_TOST)
            @test match_UST == match_TOST && tri_match == motif_match

            x_TOST, tri_match, match_TOST,_   = TAME_profiled(A_TOST, B_TOST, β, max_iter,tol,α)
            x_UST, motif_match, match_UST,_ = TAME_profiled(A_UST, B_UST, β, max_iter,tol,α)

            @test norm(x_TOST - x_UST)/norm(x_UST) < round_off_bound(x_TOST)
            @test match_UST == match_TOST && tri_match == motif_match

        end

    end

end

max_stars_repo_name: chuckcol/LambdaTAME

max_issues_repo_name: chuckcol/LambdaTAME

max_forks_repo_name: chuckcol/LambdaTAME


text:
include("FiltSparseMatrix.jl")
include("unified_dir_pt_sample.jl")
include("unified_real_ctrl_fvecs_bettis_PIs_new.jl")
include("utils-de-error.jl")


text:
using ..ChemistryFeaturization.Utils.ElementFeatureUtils
using DataFrames
using ..ChemistryFeaturization: elements
using ..ChemistryFeaturization.AbstractType: AbstractCodec, AbstractAtoms
using ..ChemistryFeaturization.Codec: OneHotOneCold

include("abstractfeatures.jl")

"""
    ElementFeatureDescriptor

Describe features associated with individual atoms that depend only upon their elemental identity

## Fields
- `name::String`: Name of the feature
- `encoder_decoder::AbstractCodec`: Codec defined which handles the feature's encoding and decoding logic
- `categorical::Bool`: flag for whether the feature is categorical or continuous-valued
- `lookup_table::DataFrame`: table containing values of feature for every encodable element
"""
struct ElementFeatureDescriptor{C<:AbstractCodec} <: AbstractAtomFeatureDescriptor
    name::String
    encoder_decoder::C
    categorical::Bool
    lookup_table::DataFrame
    function ElementFeatureDescriptor(
        feature_name::String,
        encoder_decoder::AbstractCodec,
        categorical::Bool,
        lookup_table = atom_data_df,
    )
        colnames = names(lookup_table)
        @assert feature_name in colnames && "Symbol" in colnames "Your lookup table must have a column called :Symbol and one with the same name as your feature to be usable!"

        lookup_table = lookup_table[:, ["Symbol", feature_name]]
        dropmissing!(lookup_table)

        new{typeof(encoder_decoder)}(
            feature_name,
            encoder_decoder,
            categorical,
            lookup_table,
        )
    end
end

"""
    ElementFeatureDescriptor(feature_name, lookup_table, nbins, logspaced, categorical)

Construct a feature object that encodes features associated with individual atoms that depend only upon their elemental identity.
If a Codec isn't explicity specified, [OneHotOneCold](@ref) with [default_efd_encode](@ref) and [default_efd_decode](@ref)
as the encoding and decoding functions respectively is the default choice.

## Required Arguments
- `name::String`: the name of the feature
- `lookup_table::DataFrame`: table containing values of feature for every encodable element (defaults to standard included data table, but must be included for custom features)

## Keyword Arguments
All will populate with default choices if not included.
- `nbins::Integer`: Number of bins to use for one-cold decoding of continuous-valued features
- `logspaced::Bool`: whether onehot-style bins should be logarithmically spaced or not
- `categorical::Bool`: flag for whether the feature is categorical or continuous-valued
"""
function ElementFeatureDescriptor(
    feature_name::String,
    lookup_table::DataFrame = atom_data_df;
    nbins::Integer = default_nbins,
    logspaced::Bool = default_log(feature_name, lookup_table),
    categorical::Bool = default_categorical(feature_name, lookup_table),
)
    lookup_table = lookup_table[:, ["Symbol", feature_name]]
    dropmissing!(lookup_table)

    bins = get_bins(
        feature_name,
        lookup_table;
        nbins = nbins,
        logspaced = logspaced,
        categorical = categorical,
    )

    ElementFeatureDescriptor(
        feature_name,
        OneHotOneCold(categorical, bins),
        categorical,
        lookup_table,
    )
end

# pretty printing, long version
function Base.show(io::IO, ::MIME"text/plain", efd::ElementFeatureDescriptor)
    st = "ElementFeature $(efd.name):\n   categorical: $(efd.categorical)\n   encoded length: $(output_shape(efd))"
    print(io, st)
end

encodable_elements(efd::ElementFeatureDescriptor) = efd.lookup_table[:, :Symbol]

function get_value(efd::ElementFeatureDescriptor, a::AbstractAtoms)
    @assert all([el in encodable_elements(efd) for el in elements(a)]) "Feature $(efd.name) cannot encode some element(s) in this structure!"

    feature_vals = efd.lookup_table[:, [:Symbol, Symbol(efd.name)]]
    map(
        el ->
            getproperty(feature_vals[feature_vals.Symbol.==el, :][1, :], Symbol(efd.name)),
        elements(a),
    )
end