text:
import SimpleValueGraphs: tuple_of_types, default_edgeval_types

function testset_toplogical_equivalent(g::SimpleGraph, gv::EdgeValGraph)
    @testset "Topological equivalent" begin
        @test all(lr -> lr[1] == lr[2], zip(g.fadjlist, gv.fadjlist))
    end
end

function testset_toplogical_equivalent(g::SimpleDiGraph, gv::EdgeValOutDiGraph)
    @testset "Topological equivalent" begin
        @test all(lr -> lr[1] == lr[2], zip(g.fadjlist, gv.fadjlist))
    end
end

function testset_toplogical_equivalent(g::SimpleDiGraph, gv::EdgeValDiGraph)
    @testset "Topological equivalent" begin
        @test all(lr -> lr[1] == lr[2], zip(g.fadjlist, gv.fadjlist))
        @test all(lr -> lr[1] == lr[2], zip(g.badjlist, gv.badjlist))
    end
end

# EdgeValGraph{Int, Tuple{Float64}}(10)
@testset "Constructor $G{\$V, \$E_VALS}(\$n)" for
    G in (EdgeValGraph, EdgeValOutDiGraph, EdgeValDiGraph)

    @testset "Params: V = $V, E_VALS = $E_VALS" for
         V in TEST_VERTEX_TYPES_SMALL,
    E_VALS in TEST_EDGEVAL_TYPES_SMALL,
         n in (V in (UInt8, Int8) ? V[0, 5, typemax(V)] : V[0, 5])

        g = G{V, E_VALS}(n)

        @test g isa G{V, E_VALS}
        @test ne(g) == 0
        @test nv(g) == n
        gs = is_directed(G) ? SimpleDiGraph(n) : SimpleGraph(n)
        testset_topological_equivalent(gs, g)
        testset_isvalidgraph(g)

    end
end

# EdgeValGraph(10, (Float64, ))
@testset "Constructor $G(\$n::\$V, \$edgeval_types)" for
    G in (EdgeValGraph, EdgeValOutDiGraph, EdgeValDiGraph)

    @testset "Params n = $n, V = $V, edgeval_types = $edgeval_types" for
                V in TEST_VERTEX_TYPES_SMALL,
    edgeval_types in tuple_of_types.(TEST_EDGEVAL_TYPES_SMALL),
                n in (V in (UInt8, Int8) ? V[0, 5, typemax(V)] : V[0, 5])

        g = G(n, edgeval_types)

        E_VALS_should_be = (edgeval_types isa Tuple) ?
            Tuple{edgeval_types...} :
            NamedTuple{keys(edgeval_types), Tuple{edgeval_types...}}

        @test g isa G{V, E_VALS_should_be}
        @test ne(g) == 0
        @test nv(g) == n
        gs = is_directed(G) ? SimpleDiGraph(n) : SimpleGraph(n)
        testset_topological_equivalent(gs, g)
        testset_isvalidgraph(g)
    end

end

# EdgeValGraph(10)
@testset "Constructor $G(\$n::\$V)" for
    G in (EdgeValGraph, EdgeValOutDiGraph, EdgeValDiGraph)

    @testset "Params n = $n, V = $V" for
        V in TEST_VERTEX_TYPES_SMALL,
        n in (V in (UInt8, Int8) ? V[0, 5, typemax(V)] : V[0, 5])

        g = G(n)

        @testset "correct type" begin
            E_VALS_should_be = (default_edgeval_types isa Tuple) ?
                Tuple{default_edgeval_types...} :
                NamedTuple{keys(default_edgeval_types),
                           Tuple{default_edgeval_types...}}

            @test g isa G{V, E_VALS_should_be}
        end

        @testset "0 edges" begin @test ne(g) == 0 end
        @testset "$n vertices" begin @test ne(g) == 0 end
        gs = is_directed(G) ? SimpleDiGraph(n) : SimpleGraph(n)
        testset_topological_equivalent(gs, g)
        testset_isvalidgraph(g)
    end
end

# EdgeValGraph(undef, gs, (Float64,))
@testset "Constructor $G(undef, \$gs, \$edgeval_types)" for
    G in (EdgeValGraph, EdgeValOutDiGraph, EdgeValDiGraph)

    GS = is_directed(G) ? SimpleDiGraph : SimpleGraph

    @testset "Params: edgeval_types = $edgeval_types, gs = $info" for
                V in TEST_VERTEX_TYPES_SMALL,
    edgeval_types in tuple_of_types.(TEST_EDGEVAL_TYPES_SMALL),
       (gs, info) in make_testgraphs(GS{V})

        g = G(undef, gs, edgeval_types)

        @testset "correct type" begin
            E_VALS_should_be = (edgeval_types isa Tuple) ?
                Tuple{edgeval_types...} :
                NamedTuple{keys(edgeval_types),
                           Tuple{edgeval_types...}}

            @test g isa G{V, E_VALS_should_be}
        end
        testset_topological_equivalent(gs, g)
        testset_isvalidgraph(g, undef_edgevalues=true)
    end
end

# EdgeValGraph(undef, gs)
@testset "Constructor $G(undef, \$gs)" for
    G in (EdgeValGraph, EdgeValOutDiGraph, EdgeValDiGraph)

    GS = is_directed(G) ? SimpleDiGraph : SimpleGraph

    @testset "Params: gs = $info" for
                V in TEST_VERTEX_TYPES_SMALL,
       (gs, info) in make_testgraphs(GS{V})

        g = G(undef, gs)

        @testset "correct type" begin
            E_VALS_should_be = (default_edgeval_types isa Tuple) ?
                Tuple{default_edgeval_types...} :
                NamedTuple{keys(default_edgeval_types),
                           Tuple{default_edgeval_types...}}

            @test g isa G{V, E_VALS_should_be}
        end
        testset_topological_equivalent(gs, g)
        testset_isvalidgraph(g, undef_edgevalues=true)
    end
end

# EdgeValGraph((s, d) -> (f(s, d),), gs, (Float64,))
@testset "Constructor $G(f, \$gs, \$edgeval_types)" for
    G in (EdgeValGraph, EdgeValOutDiGraph, EdgeValDiGraph)

    GS = is_directed(G) ? SimpleDiGraph : SimpleGraph

    @testset "Params: edgeval_types = $(tuple_of_types(E_VALS)), gs = $info" for
                V in TEST_VERTEX_TYPES_SMALL,
           E_VALS in TEST_EDGEVAL_TYPES_SMALL,
       (gs, info) in make_testgraphs(GS{V})

        n = nv(gs)
        A = rand_sample(E_VALS, n, n)
        edgeval_types = tuple_of_types(E_VALS)

        g = G((s, d) -> A[s,d], gs, edgeval_types)

        @testset "correct type" begin
            E_VALS_should_be = (edgeval_types isa Tuple) ?
                Tuple{edgeval_types...} :
                NamedTuple{keys(edgeval_types),
                           Tuple{edgeval_types...}}

            @test g isa G{V, E_VALS_should_be}
        end

        @testset "correct values" begin
            @test all(edges(gs)) do e
                s, d = src(e), dst(e)
                A[s, d] == get_edgevals(g, s, d)
            end
        end

        testset_topological_equivalent(gs, g)
        testset_isvalidgraph(g)
    end
end

# EdgeValGraph((s, d) -> (f(s, d),), gs)
@testset "Constructor $G(undef, \$gs)" for
    G in (EdgeValGraph, EdgeValOutDiGraph, EdgeValDiGraph)

    GS = is_directed(G) ? SimpleDiGraph : SimpleGraph

    @testset "Params: gs = $info" for
                V in TEST_VERTEX_TYPES_SMALL,
       (gs, info) in make_testgraphs(GS{V})

        E_VALS = (default_edgeval_types isa Tuple) ?
                Tuple{default_edgeval_types...} :
                NamedTuple{keys(default_edgeval_types),
                           Tuple{default_edgeval_types...}}

        n = nv(gs)
        A = rand_sample(E_VALS, n, n)

        g = G((s, d) -> A[s,d], gs)

        @testset "correct type" begin
            @test g isa G{V, E_VALS}
        end

        @testset "correct values" begin
            @test all(edges(gs)) do e
                s, d = src(e), dst(e)
                A[s, d] == get_edgevals(g, s, d)
            end
        end

        testset_topological_equivalent(gs, g)
        testset_isvalidgraph(g)
    end
end


text:
using Base.Test
using DataFrames

let
	dv = dataones(3)
	@assert isequal(dv, padNA(dv, 0, 0))
	@assert length(padNA(dv, 2, 0)) == length(dv) + 2
	@assert length(padNA(dv, 0, 2)) == length(dv) + 2
	@assert length(padNA(dv, 2, 2)) == length(dv) + 4
end

ext: jl


text:
"""
    PlanarGradient <: NeutralLandscapeMaker

    PlanarGradient(; direction=360rand())
    PlanarGradient(direction)

This type is used to generate a planar gradient landscape, where values change
as a bilinear function of the *x* and *y* coordinates. The direction is
expressed as a floating point value, which will be in *[0,360]*. The inner
constructor takes the mod of the value passed and 360, so that a value that is
out of the correct interval will be corrected.
"""
@kwdef struct PlanarGradient <: NeutralLandscapeMaker
    direction::Float64 = 360rand()
    PlanarGradient(x::T) where {T <: Real} = new(mod(x, 360.0))
end

function _landscape!(mat, alg::PlanarGradient) where {IT <: Integer}
    eastness = sin(deg2rad(alg.direction))
    southness = -1cos(deg2rad(alg.direction))
    rows, cols = axes(mat)
    mat .= southness .* rows .+ (eastness .* cols)'
    return mat
end


text:
# This file shows the proposed syntax for the Protocol macro

@Prot begin

Protocol Iterable

  # Specify fields the Iterable must have.
  start::Int64

  # Docstrings in Protocol definitions could serve as documentation for functions
  # rather than methods.
  function next(t :~ Iterable) # no default implementation

  # protocol functions could have default implementations
  function 2ndnext(t :~ Iterable) # default implementation
    next(t)
    next(t)
  end

end

# We now define a type...
struct T
  start::Int
  c
end

# and implement the Protocol for it
impl Iterable for T

  # Here we also check the function signature is correct  according to the Protocol
  function next(t::T)
    t.c
  end

end

# We can then define functions that take Iterables and only Iterables of
# arbitrary type as input.
function get_third(b :~ Iterable)
  2ndnext(b)
  next(b)
end

# we get an object of type T
t = T(1, 5)

# and call get_third on it:
get_third(t)

# and calling it this way:
get_third(1)
# raises "Type of argument arr does not implement protocol Iterable"

end #@Prot


text:
using DrWatson
quickactivate(@__DIR__)
@show projectdir()
##
using CovidSurvey
using StatsBase
using StatsPlots
using DataFrames
using Dates
using CSV

plotlyjs()
## ============================================================================
@info "National"

function load_national_data(;kwargs...)

    observables = Dict()
    National.observables!(observables)
    hospit = observables["hospit"]
    cases = observables["cases"]

    fname = projectdir("reports/variable-delays/Rt_cases=2020-06-01_chains=10_hospit=true_model=hospit_observ=2021-02-06_sero=true_steps=4000_warmup=1000.csv")
    rt = CSV.File(fname) |> DataFrame
    "dates" in names(rt) && rename!(rt, "dates"=>"date")

    fname = projectdir("data/raw_contact_rates.csv")
    surv = CSV.File(fname) |> DataFrame

    fname = projectdir("data/google/mobility_denmark.csv")
    mobil = CSV.File(fname) |> DataFrame

    return conform(cases, hospit, rt, surv, mobil; kwargs...)
end

function StatsBase.zscore(df::DataFrame)
    y = similar(df)
    for n in names(df)
        y[!,n] = zscore(df[:,n])
    end
    return y
end

function conform(args...; normalize = false, stopdate=nothing, startdate=nothing)
    s = isnothing(startdate) ? maximum( first.( select.(args, Ref(:date) ) ) ).date : Date(startdate)
    e = isnothing(stopdate) ? minimum( last.( select.(args, Ref(:date) ) ) ).date : Date(stopdate)
    x = s:Day(1):e
    y = filter.(Ref(:date => >=(s)), args)
    y = filter.(Ref(:date => <=(e)), y)
    normalize && ( y = zscore.( select.( y, Ref(Not(:date)) ) ) )
    (x, y...)
end

function plot_comparison(date, cases, hospit, rt, surv, mobil; column=:country)
    plots  = Vector{Plots.Plot}()

    p = plot(; xaxis = true, legend = :outertopright, title="observed cases and hospitalizations", xticks=:native)
    plot!(date, zscore(cases[:,column]), lab="cases", lw=2)
    plot!(date, zscore(hospit[:,column]), lab="hospitalizations", lw=2)
    push!(plots, p)

    p = plot(; xaxis = true, legend = :outertopright, title="reproduction number from hospitalizations", xticks=:native)
    plot!(rt.date, rt.mq, ribbon=(rt.mq - rt.lq, rt.uq - rt.mq), c=:peru, lab="reproduction number", lw=2)
    push!(plots, p)

    p = plot(; xaxis = true, legend = :outertopright, title="contact survey", xticks=:native)
    for c in names(surv, Not(:date))
        plot!(surv.date, surv[:,c], lab=c, lw=2)
    end
    push!(plots, p)

    p = plot(; xaxis = true, legend = :outertopright, title="google mobility", xticks=:native)
    for c in names(mobil, Not(:date))
        plot!(date, mobil[:,c], lab=c, lw=2)
    end
    push!(plots, p)

    return plot(plots..., layout=(4,1), size=(1500, 4*250), sharex=true, link=:x)
end

let
    data  = load_national_data(stopdate="2021-02-01")
    p     = plot_comparison( data...);
    fname = "figures/compare_rt_smothedsurvey_mobility_DENMARK.html"
    savefig(p, projectdir(fname))
    run(`firefox $fname`, wait=false)
end

## ===========================================================================
# regional

function load_regional_data(i; kwargs...)

    observables = Dict()
    Regional.observables!(observables)
    hospit = observables["hospit"]
    cases = observables["cases"]

    # fname = projectdir("reports/2021-08-01/Rt-$(uppercase(Regional.regions[i]))_chains=10_epidemicstart=10_folder=2021-08-01_model=cases_numimpute=6_rwstep=1_steps=100_warmup=500.csv")
    fname = projectdir("/home/and/dev/CovidSurvey/reports/regional_prediction_end_of_peak/2021-09-01/Rt-$(uppercase(Regional.regions[i]))_chains=10_model=hospit_observ=2021-03-01_regional=true_rwstep=1_semipar=true_std=false_steps=1000_warmup=1000.csv")
    rt = CSV.File(fname) |> DataFrame
    rename!(rt, "dates"=>"date")

    # fname = projectdir("data/raw_contact_rates_region=$(i)_aggregation=7.csv")
    fname = projectdir("data/mean_contact_rates_region=$i.csv")
    surv = CSV.File(fname) |> DataFrame
    "dates" in names(surv) && rename!(surv, "dates"=>"date")

    fname = projectdir("data/mobility/mobility_region=$(Regional.regions[i]).csv")
    mobil = CSV.File(fname) |> DataFrame

    return conform(cases, hospit, rt, surv, mobil; kwargs...)
end

for (i,r) in enumerate(Regional.regions)
    data  = load_regional_data(i; stopdate="2021-02-01")
    p     = plot_comparison( data...; column=Regional.regions[i])
    fname = "/home/and/.tmp/compare_rt_meansurvey_mobility_REGION=$(uppercase(r)).html"
    savefig(p, projectdir(fname))
    run(`firefox $fname`, wait=false)
end

## ===========================================================================
# regional with aggregation

function load_aggregated_regional_data(i, aggregation; kwargs...)

    observables = Dict()
    Regional.observables!(observables)
    hospit = observables["hospit"]
    cases = observables["cases"]

    # fname = projectdir("reports/aggregated_random_walk/aggregation=7/")
    fname = projectdir("reports/aggregated_random_walk/aggregation=$(aggregation)/Rt-$(uppercase(Regional.regions[i]))_chains=5_epidemicstart=30_model=hospit_numimpute=6_observationsend=2021-01-13_regional=true_rwstep=$(aggregation)_steps=200_warmup=1000.csv")
    rt = CSV.File(fname) |> DataFrame
    rename!(rt, "dates"=>"date")

    # fname = projectdir("data/raw_contact_rates_region=$(i)_aggregation=7.csv")
    fname = projectdir("data/mean_contact_rates_region=$(i)_aggregation=$(aggregation).csv")
    surv = CSV.File(fname) |> DataFrame
    "dates" in names(surv) && rename!(surv, "dates"=>"date")

    fname = projectdir("data/google/mobility_region=$(Regional.regions[i]).csv")
    mobil = CSV.File(fname) |> DataFrame

    return conform(cases, hospit, rt, surv, mobil; kwargs...)
end

aggregation = 3
for (i,r) in enumerate(Regional.regions)
    data  = load_aggregated_regional_data(i, aggregation; stopdate="2021-02-01")
    p     = plot_comparison( data...; column=Regional.regions[i])
    fname = "figures/compare_rt_meansurvey_mobility_REGION=$(uppercase(r)).html"
    savefig(p, projectdir(fname))
    run(`firefox $fname`, wait=false)
end

## =============================================================================

max_stars_repo_name: andreaskoher/CovidSurvey

max_issues_repo_name: andreaskoher/CovidSurvey

max_forks_repo_name: andreaskoher/CovidSurvey


text:
# -*- coding: utf-8 -*-
# ---
# jupyter:
#   jupytext:
#     formats: ipynb,jl:hydrogen
#     text_representation:
#       extension: .jl
#       format_name: hydrogen
#       format_version: '1.3'
#       jupytext_version: 1.11.2
#   kernelspec:
#     display_name: Julia 1.8.0-DEV
#     language: julia
#     name: julia-1.8
# ---

# %%
a = 1.3; tmax = 25.0; using Distributions, DifferentialEquations, Plots
kuramoto!(dθ, θ, param, t) = (N = length(θ); (K, ω) = param;
    for i in 1:N dθ[i] = ω[i] + K*mean(sin(θ[j] - θ[i]) for j in 1:N) end)
(m, n) = (32, 16); (d, v) = (Normal(0, 2), 1.0); K_c = 2/π/pdf(d, 0)
θ₀ = 2π*rand(m, n); tspan = (0.0, tmax); K = a*K_c; ω = rand(d, m, n) .+ v
sol = solve(ODEProblem(kuramoto!, θ₀, tspan, (K, ω)))
anim = @animate for t in [fill(0, 20); 0:0.1:tmax; fill(tmax, 20)]
    plot(size=(400, 220), title="Kuramoto model K = $(a)K_c: t = $t", titlefontsize=10)
    heatmap!(sin.(sol(t))'; c=:bwr, colorbar=false, frame=false, ticks=false)
end; gif(anim, "kuramoto$(a).gif")

# %%
quote
a = 1.3; tmax = 25.0; using Distributions, DifferentialEquations, Plots
kuramoto!(dθ, θ, param, t) = (N = length(θ); (K, ω) = param;
    for i in 1:N dθ[i] = ω[i] + K*mean(sin(θ[j] - θ[i]) for j in 1:N) end)
(m, n) = (32, 16); (d, v) = (Normal(0, 2), 1.0); K_c = 2/π/pdf(d, 0)
θ₀ = 2π*rand(m, n); tspan = (0.0, tmax); K = a*K_c; ω = rand(d, m, n) .+ v
sol = solve(ODEProblem(kuramoto!, θ₀, tspan, (K, ω)))
anim = @animate for t in [fill(0, 20); 0:0.1:tmax; fill(tmax, 20)]
    plot(size=(400, 220), title="Kuramoto model K = $(a)K_c: t = $t", titlefontsize=10)
    heatmap!(sin.(sol(t))'; c=:bwr, colorbar=false, frame=false, ticks=false)
end; gif(anim, "kuramoto$(a).gif")
end |> Base.remove_linenums! |> x -> display("text/markdown", "```julia\n$x\n```")

# %%
begin
    a = 1.3
    tmax = 25.0
    using Distributions, DifferentialEquations, Plots
    kuramoto!(dθ, θ, param, t) = begin
            N = length(θ)
            (K, ω) = param
            for i = 1:N
                dθ[i] = ω[i] + K * mean((sin(θ[j] - θ[i]) for j = 1:N))
            end
        end
    (m, n) = (32, 16)
    (d, v) = (Normal(0, 2), 1.0)
    K_c = (2 / π) / pdf(d, 0)
    θ₀ = (2π) * rand(m, n)
    tspan = (0.0, tmax)
    K = a * K_c
    ω = rand(d, m, n) .+ v
    sol = solve(ODEProblem(kuramoto!, θ₀, tspan, (K, ω)))
    anim = @animate(for t = [fill(0, 20); 0:0.1:tmax; fill(tmax, 20)]
                plot(size = (400, 220), title = "Kuramoto model K = $(a)K_c: t = $(t)", titlefontsize = 10)
                heatmap!((sin.(sol(t)))'; c = :bwr, colorbar = false, frame = false, ticks = false)
            end)
    gif(anim, "kuramoto$(a).gif")
end

# %%

max_stars_repo_name: genkuroki/public

max_issues_repo_name: genkuroki/public

max_forks_repo_name: genkuroki/public


text:
module ReadCoverageDistributions

include("IslandIterator.jl")
include("HistogramReadCoverages.jl")
include("OceanIslandsDistributions.jl")
include("merge_sort.jl")
include("count_islands_and_append_to_array.jl")

export simulate_and_get_coverage_hist_2,
	simulate_oceansislands,
	no_islands_vs_no_reads_simulation,
	no_oceans_vs_no_reads_simulation,
	avg_length_oceans_vs_no_reads_simulation,
	avg_length_islands_vs_no_reads_simulation,
	simulate_and_get_coverage_hist_3,
	no_reads_vs_no_islands,simulate_readcoverage,
	Para,
	increment!,
	hist_add!,vec_hist_add!,
	simulate_and_get_coverage_hist,
	IslandIterator,
	merge_sorted_arrays

end


text:
module Cobweb

using ..Ahorn, Maple

const placements = Ahorn.PlacementDict(
    "Cobweb" => Ahorn.EntityPlacement(
        Maple.Cobweb,
        "line"
    )
)

cobwebColorHex = "696A6A"
cobwebColor = (41, 42, 42, 1) ./ (255, 255, 255, 1)
cobwebColorSelected = (Ahorn.colors.selection_selected_fc)

function renderCobweb(ctx::Ahorn.Cairo.CairoContext, entity::Maple.Cobweb, color::Ahorn.colorTupleType=cobwebColor)
    x, y = Ahorn.position(entity)

    start = (x, y)
    nodes = get(entity.data, "nodes", [start])
    stop = nodes[1]

    baseCurve = Ahorn.SimpleCurve(start, stop, (start .+ stop) ./ 2 .+ (0, 4))
    middle = Ahorn.getPoint(baseCurve, 0.5)

    for node in nodes
        curve = Ahorn.SimpleCurve(middle, node, (middle .+ node) ./ 2 .+ (0, 4))
        Ahorn.drawSimpleCurve(ctx, curve, color, thickness=1)
    end

    curve = Ahorn.SimpleCurve(middle, start, (middle .+ start) ./ 2 .+ (0, 4))
    Ahorn.drawSimpleCurve(ctx, curve, color, thickness=1)
end

Ahorn.nodeLimits(entity::Maple.Cobweb) = 1, -1

function Ahorn.selection(entity::Maple.Cobweb)
    nodes = get(entity.data, "nodes", ())
    x, y = Ahorn.position(entity)

    res = Ahorn.Rectangle[Ahorn.Rectangle(x - 4, y - 4, 8, 8)]

    for node in nodes
        nx, ny = node

        push!(res, Ahorn.Rectangle(nx - 4, ny - 4, 8, 8))
    end

    return res
end

Ahorn.renderSelectedAbs(ctx::Ahorn.Cairo.CairoContext, entity::Maple.Cobweb) = renderCobweb(ctx, entity, cobwebColorSelected)

function Ahorn.renderAbs(ctx::Ahorn.Cairo.CairoContext, entity::Maple.Cobweb, room::Maple.Room)
    # Make sure Alpha is 1
    rawColor = Ahorn.argb32ToRGBATuple(parse(Int, get(entity.data, "color", cobwebColorHex), base=16))[1:3] ./ 255
    color = (rawColor..., 1.0)

    renderCobweb(ctx, entity, color)
end

end


text:
# ============================================================
# Mirroring Functions
# ============================================================

function bc_mirror!(
    ctr::AbstractMatrix{T},
    ng = 1::Integer;
    dirc,
) where {T<:AbstractControlVolume2D}

    if Symbol(dirc) in (:xl, :xL)
        for j in axes(ctr, 2), i = 1:ng
            bc_mirror!(ctr[1-i, j], ctr[i, j], :x)
        end
    elseif Symbol(dirc) in (:xr, :xR)
        nx = size(ctr, 1) - 2 * ng
        for j in axes(ctr, 2), i = 1:ng
            bc_mirror!(ctr[nx+i, j], ctr[nx-i+1, j], :x)
        end
    elseif Symbol(dirc) in (:yl, :yL)
        for j = 1:ng, i in axes(ctr, 1)
            bc_mirror!(ctr[i, 1-j], ctr[i, j], :y)
        end
    elseif Symbol(dirc) in (:yr, :yR)
        ny = size(ctr, 2) - 2 * ng
        for j = 1:ng, i in axes(ctr, 1)
            bc_mirror!(ctr[i, ny+j], ctr[i, ny-j+1], :y)
        end
    end

    return nothing

end

function bc_mirror!(ctr::ControlVolume2D, ctr0::ControlVolume2D, dirc)
    copy_ctr!(ctr, ctr0)

    if Symbol(dirc) == :x
        ctr.w[2] *= -1.0
        ctr.prim[2] *= -1.0
        ctr.sw[2, 1] *= -1.0
    elseif Symbol(dirc) == :y
        ctr.w[3] *= -1.0
        ctr.prim[3] *= -1.0
        ctr.sw[3, 2] *= -1.0
    end

    return nothing
end

function bc_mirror!(ctr::ControlVolume2D1F, ctr0::ControlVolume2D1F, dirc)
    copy_ctr!(ctr, ctr0)

    nu = size(ctr.f, 1)
    nv = size(ctr.f, 2)

    if Symbol(dirc) == :x
        ctr.w[2] *= -1.0
        ctr.prim[2] *= -1.0
        ctr.sw[2, 1] *= -1.0

        for j = 1:nv, i = 1:nu
            ctr.f[i, j] = ctr0.f[nu+1-i, j]
        end
    elseif Symbol(dirc) == :y
        ctr.w[3] *= -1.0
        ctr.prim[3] *= -1.0
        ctr.sw[3, 2] *= -1.0

        for j = 1:nv, i = 1:nu
            ctr.f[i, j] = ctr0.f[i, nv+1-j]
        end
    end

    return nothing
end

function bc_mirror!(ctr::ControlVolume2D2F, ctr0::ControlVolume2D2F, dirc)
    copy_ctr!(ctr, ctr0)

    nu = size(ctr.h, 1)
    nv = size(ctr.h, 2)

    if Symbol(dirc) == :x
        ctr.w[2] *= -1.0
        ctr.prim[2] *= -1.0
        ctr.sw[2, 1] *= -1.0

        for j = 1:nv, i = 1:nu
            ctr.h[i, j] = ctr0.h[nu+1-i, j]
            ctr.b[i, j] = ctr0.b[nu+1-i, j]
        end
    elseif Symbol(dirc) == :y
        ctr.w[3] *= -1.0
        ctr.prim[3] *= -1.0
        ctr.sw[3, 2] *= -1.0

        for j = 1:nv, i = 1:nu
            ctr.h[i, j] = ctr0.h[i, nv+1-j]
            ctr.b[i, j] = ctr0.b[i, nv+1-j]
        end
    end

    return nothing
end


text:
export @index
export @basic
export @extend

macro index(xstruct, blocks)
    quote
        NerualStruct = $(esc(xstruct))
        Base.length(s::NerualStruct)     = length(s.$blocks)
        Base.lastindex(s::NerualStruct)  = length(s.$blocks)
        Base.firstindex(s::NerualStruct) = 1
        Base.getindex(s::NerualStruct, k...)     =  s.$blocks[k...]
        Base.setindex!(s::NerualStruct, v, k...) = (s.$blocks[k...] = v)
        Base.iterate(s::NerualStruct, i=firstindex(s)) = i>length(s) ? nothing : (s[i], i+1)
    end
end

macro basic(xstruct, blocks)
    quote
        NerualStruct = $(esc(xstruct))

        function Base.show(io::IO, s::NerualStruct)
            print(io, "$NerualStruct(\n")
            join(io, s.$blocks, "\n")
            print(io, "\n)")
        end

        function Delta.paramsof(m::NerualStruct)
            params = Vector{Variable}(undef,0)
            for i = 1:length(m)
                append!(params, paramsof(m[i]))
            end
            return params
        end

        function Delta.xparamsof(m::NerualStruct)
            xparams = Vector{XVariable}(undef,0)
            for i = 1:length(m)
                append!(xparams, xparamsof(m[i]))
            end
            return xparams
        end

        function Delta.nparamsof(m::NerualStruct)
            nparams = 0
            for i = 1:length(m)
                nparams += nparamsof(m[i])
            end
            return nparams
        end

        function Delta.bytesof(model::NerualStruct, unit::String="MB")
            n = nparamsof(model) * elsizeof(model[1].w)
            return blocksize(n, uppercase(unit))
        end
    end
end

macro extend(xstruct, blocks)
    quote
        NerualStruct = $(esc(xstruct))
        Base.length(s::NerualStruct)     = length(s.$blocks)
        Base.lastindex(s::NerualStruct)  = length(s.$blocks)
        Base.firstindex(s::NerualStruct) = 1
        Base.getindex(s::NerualStruct, k...)     =  s.$blocks[k...]
        Base.setindex!(s::NerualStruct, v, k...) = (s.$blocks[k...] = v)
        Base.iterate(s::NerualStruct, i=firstindex(s)) = i>length(s) ? nothing : (s[i], i+1)

        function Base.show(io::IO, s::NerualStruct)
            print(io, "$NerualStruct(\n")
            join(io, s.$blocks, "\n")
            print(io, "\n)")
        end

        function Delta.paramsof(m::NerualStruct)
            params = Vector{Variable}(undef,0)
            for i = 1:length(m)
                append!(params, paramsof(m[i]))
            end
            return params
        end

        function Delta.xparamsof(m::NerualStruct)
            xparams = Vector{XVariable}(undef,0)
            for i = 1:length(m)
                append!(xparams, xparamsof(m[i]))
            end
            return xparams
        end

        function Delta.nparamsof(m::NerualStruct)
            nparams = 0
            for i = 1:length(m)
                nparams += nparamsof(m[i])
            end
            return nparams
        end

        function Delta.bytesof(model::NerualStruct, unit::String="MB")
            n = nparamsof(model) * elsizeof(model[1].w)
            return blocksize(n, uppercase(unit))
        end
    end
end

max_stars_repo_name: sonosole/Delta

max_issues_repo_name: sonosole/Delta

max_forks_repo_name: sonosole/Delta


text:
using Convex
using SCS

function fit(model::Function, target::Array, args...; steps = 2)
    solver = SCSSolver(verbose=0)
    set_default_solver(solver);

    vars = [DiffVariable(a) for a in args]
    progr = [zeros(eltype(a),(length(a),steps+1)) for a in args]

    for j in 1:length(args)
        progr[j][:,1] = args[j][:]
    end
    for i = 1:steps
        problem = minimize(sumsquares(target - model(vars...)))
        solve!(problem)
        for j = eachindex(vars)
            vars[j].v += vars[j].dv.value
            progr[j][:,i+1] = vars[j].v[:]
        end
    end

    [v.v for v in vars], progr
end

export fit


text:
using GeometricAlgebra
using BenchmarkTools
using Profile
Profile.init(500000000, 5e-8)

@basis "+++"

f(v1, v3, v12, v2) = (5v1 + 3v3 + 1v12) * 5v2
h(v1, v3, v12, v2) = 5v1 + 3v3 + 1v2
@benchmark f($v1, $v3, $v12, $v2)
# @profiler f(v1, v3, v12, v2)


text:
# ---
# title: 1647. Minimum Deletions to Make Character Frequencies Unique
# id: problem1647
# author: Tian Jun
# date: 2020-10-31
# difficulty: Medium
# categories: Greedy, Sort
# link: <https://leetcode.com/problems/minimum-deletions-to-make-character-frequencies-unique/description/>
# hidden: true
# ---
#
# A string `s` is called **good** if there are no two different characters in
# `s` that have the same **frequency**.
#
# Given a string `s`, return _the **minimum** number of characters you need to
# delete to make _`s` _**good**._
#
# The **frequency** of a character in a string is the number of times it appears
# in the string. For example, in the string `"aab"`, the **frequency** of `'a'`
# is `2`, while the **frequency** of `'b'` is `1`.
#
#
#
# **Example 1:**
#
#
#
#     Input: s = "aab"
#     Output: 0
#     Explanation: s is already good.
#
#
# **Example 2:**
#
#
#
#     Input: s = "aaabbbcc"
#     Output: 2
#     Explanation: You can delete two 'b's resulting in the good string "aaabcc".
#     Another way it to delete one 'b' and one 'c' resulting in the good string "aaabbc".
#
# **Example 3:**
#
#
#
#     Input: s = "ceabaacb"
#     Output: 2
#     Explanation: You can delete both 'c's resulting in the good string "eabaab".
#     Note that we only care about characters that are still in the string at the end (i.e. frequency of 0 is ignored).
#
#
#
#
# **Constraints:**
#
#   * `1 <= s.length <= 105`
#   * `s` contains only lowercase English letters.
#
#
## @lc code=start
using LeetCode

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


text:
__precompile__(true)
module GLVisualize

using GLFW
using GLWindow
using GLAbstraction
using ModernGL
using StaticArrays
using GeometryTypes
using Colors
using Reactive
using Quaternions
using FixedPointNumbers
using FileIO
using Packing
using SignedDistanceFields
using FreeType
import IterTools
using Base.Markdown
using FreeTypeAbstraction

import ColorVectorSpace
import GLAbstraction: N0f8
export N0f8 # reexport for examples/tests

import Base: merge, convert, show
using Base.Iterators: Repeated, repeated

import AxisArrays, ImageAxes, Images
using IndirectArrays
const HasAxesArray{T, N} = Union{AxisArrays.AxisArray{T, N}, Images.ImageMetadata.ImageMetaAxis{T, N}}
const AxisMatrix{T} = HasAxesArray{T, 2}

const GLBoundingBox = AABB{Float32}

export renderloop

"""
Replacement of Pkg.dir("GLVisualize") --> GLVisualize.dir,
returning the correct path
"""
dir(dirs...) = joinpath(dirname(@__FILE__), "..", dirs...)

"""
returns path relative to the assets folder
"""
assetpath(folders...) = dir("assets", folders...)

"""
Loads a file from the asset folder
"""
function loadasset(folders...; kw_args...)
    path = assetpath(folders...)
    isfile(path) || isdir(path) || error("Could not locate file at $path")
    load(path; kw_args...)
end

export assetpath, loadasset

include("StructsOfArrays.jl")
using .StructsOfArrays

include("types.jl")
export CIRCLE, RECTANGLE, ROUNDED_RECTANGLE, DISTANCEFIELD, TRIANGLE

include("config.jl")
using .Config
import .Config: default

include("boundingbox.jl")

include("visualize_interface.jl")
export _view #push renderobject into renderlist of the default screen, or supplied screen
export visualize # Visualize an object
export visualize_default # get the default parameter for a visualization

include("utils.jl")
export y_partition, y_partition_abs
export x_partition, x_partition_abs
export loop, bounce
export clicked, dragged_on, is_hovering
export OR, AND, isnotempty
export color_lookup

include("renderloop.jl")

include("texture_atlas.jl")

include(joinpath("gui", "color_chooser.jl"))
include(joinpath("gui", "numbers.jl"))
include(joinpath("gui", "line_edit.jl"))
include(joinpath("gui", "buttons.jl"))
include(joinpath("gui", "options.jl"))
include(joinpath("gui", "container.jl"))

export widget # edits some value, name should be changed in the future!

include(joinpath("visualize", "lines.jl"))
include(joinpath("visualize", "containers.jl"))
include(joinpath("visualize", "image_like.jl"))
include(joinpath("visualize", "mesh.jl"))
include(joinpath("visualize", "particles.jl"))
include(joinpath("visualize", "surface.jl"))
include(joinpath("visualize", "text.jl"))

include("camera.jl")
export cubecamera

# Compose/Gadfly  backend has a weird missplaced expression error right now.
# Lets disable it for now
#include("compose_backend.jl")

include("videotool.jl")
export create_video

include("documentation.jl")
export get_docs

#include("../precompile/glv_userimg.jl")

include("parallel.jl")

end # module


text:
using MittagLefflerFunctions
using PyPlot
using SpecialFunctions: erfcx
using Printf

α = 1/2
β = 1.0

x = range(0, 10, length=201)
y = erfcx.(x)

rvals = collect(4:2:10)
maxerr = Float64[]

figure(1)
@printf("%5s  %5s  %10s\n\n", "m", "n", "max error")
style = ("-", "--", ":", "-.")
for row = 1:length(rvals)
    r = rvals[row]
    m = r + 1
    n = r
    E = MLPade(α, β, m, n, :svd)
    err = abs.( y - E.(x) )
    semilogy(x, err, style[row], label="m, n = $m, $n")
    push!(maxerr, maximum(err))
    @printf("%5d  %5d  %10.2e\n", m, n, maxerr[row])
end
legend()
grid(true)
xlabel(L"$x$")
savefig("figure09.pdf")


text:
function testfile(file, kwargs, expected_sz, expected_sch, testfunc; dir=dir)
    println("testing $file")
    if file isa IO
        seekstart(file)
    end
    rows = CSV.Rows(file isa IO ? file : joinpath(dir, file); kwargs...) |> columntable
    actual_sch = Tables.schema(rows)
    @test Tuple(expected_sch.names) == actual_sch.names
    @test (length(rows) == 0 ? 0 : length(rows[1]), length(rows)) == expected_sz
    if file isa IO
        seekstart(file)
    end
    f = CSV.File(file isa IO ? file : joinpath(dir, file); kwargs...)
    t = f |> columntable
    actual_sch = Tables.schema(t)
    @test Tuple(expected_sch.types) == actual_sch.types
    @test Tuple(expected_sch.names) == actual_sch.names
    @test (length(t) == 0 ? 0 : length(t[1]), length(t)) == expected_sz
    if testfunc === nothing
    elseif testfunc isa Function
        testfunc(t)
    else
        @test isequal(t, testfunc)
    end
    if file isa IO
        seekstart(file)
    end
    kwargs = Base.structdiff(kwargs, (types=[],))
    types = haskey(kwargs, :select) ? Dict(nm=>T for (nm, T) in zip(f.names, f.types)) : f.types
    rows = CSV.Rows(file isa IO ? file : joinpath(dir, file); types=types, kwargs...) |> columntable
    actual_sch = Tables.schema(rows)
    @test Tuple(expected_sch.names) == actual_sch.names
    @test Tuple(expected_sch.types) == actual_sch.types
    @test (length(rows) == 0 ? 0 : length(rows[1]), length(rows)) == expected_sz
    return t
end

testfiles = [
    # file, kwargs, expected_sz, expected_sch, testfunc =
    ("test_utf8_with_BOM.csv", NamedTuple(),
        (3, 3),
        NamedTuple{(:col1, :col2, :col3),Tuple{Float64,Float64,Float64}},
        (col1 = [1.0, 4.0, 7.0], col2 = [2.0, 5.0, 8.0], col3 = [3.0, 6.0, 9.0])
    ),
    ("test_utf8.csv", NamedTuple(),
        (3, 3),
        NamedTuple{(:col1, :col2, :col3),Tuple{Float64,Float64,Float64}},
        (col1 = [1.0, 4.0, 7.0], col2 = [2.0, 5.0, 8.0], col3 = [3.0, 6.0, 9.0])
    ),
    ("test_windows.csv", NamedTuple(),
        (3, 3),
        NamedTuple{(:col1, :col2, :col3),Tuple{Float64,Float64,Float64}},
        (col1 = [1.0, 4.0, 7.0], col2 = [2.0, 5.0, 8.0], col3 = [3.0, 6.0, 9.0])
    ),
    ("test_single_column.csv", NamedTuple(),
        (3, 1),
        NamedTuple{(:col1,), Tuple{Int64}},
        (col1=[1,2,3],)
    ),
    ("test_empty_file.csv", NamedTuple(),
        (0, 0),
        NamedTuple{(), Tuple{}},
        NamedTuple()
    ),
    ("test_empty_file_newlines.csv", (normalizenames=true,),
        (9, 1),
        NamedTuple{(:Column1,), Tuple{Missing}},
        (Column1 = Missing[missing, missing, missing, missing, missing, missing, missing, missing, missing],)
    ),
    ("test_simple_quoted.csv", (escapechar='\\', pool=false),
        (1, 2),
        NamedTuple{(:col1, :col2), Tuple{String, String}},
        (col1 = ["quoted field 1"], col2 = ["quoted field 2"])
    ),
    ("test_quoted_delim_and_newline.csv", (escapechar='\\', pool=false),
        (1, 2),
        NamedTuple{(:col1, :col2), Tuple{String, String}},
        (col1 = ["quoted ,field 1"], col2 = ["quoted\n field 2"])
    ),
    ("test_quoted_numbers.csv", (escapechar='\\',),
        (3, 3),
        NamedTuple{(:col1, :col2, :col3),Tuple{String,Int64,Int64}},
        (col1 = ["123", "abc", "123abc"], col2 = [1, 42, 12], col3 = [1, 42, 12])
    ),
    ("test_crlf_line_endings.csv", NamedTuple(),
        (3, 3),
        NamedTuple{(:col1,:col2,:col3), Tuple{Int64, Int64, Int64}},
        (col1 = [1, 4, 7], col2 = [2, 5, 8], col3 = [3, 6, 9])
    ),
    ("test_newline_line_endings.csv", NamedTuple(),
        (3, 3),
        NamedTuple{(:col1,:col2,:col3), Tuple{Int64, Int64, Int64}},
        (col1 = [1, 4, 7], col2 = [2, 5, 8], col3 = [3, 6, 9])
    ),
    ("test_mac_line_endings.csv", NamedTuple(),
        (3, 3),
        NamedTuple{(:col1,:col2,:col3), Tuple{Int64, Int64, Int64}},
        (col1 = [1, 4, 7], col2 = [2, 5, 8], col3 = [3, 6, 9])
    ),
    ("test_no_header.csv", (header=0,),
        (3, 3),
        NamedTuple{(:Column1, :Column2, :Column3), Tuple{Float64, Float64, Float64}},
        (Column1 = [1.0, 4.0, 7.0], Column2 = [2.0, 5.0, 8.0], Column3 = [3.0, 6.0, 9.0])
    ),
    ("test_2_footer_rows.csv", (header=4, footerskip=2),
        (3, 3),
        NamedTuple{(:col1, :col2, :col3), Tuple{Int64, Int64, Int64}},
        (col1 = [1, 4, 7], col2 = [2, 5, 8], col3 = [3, 6, 9])
    ),
    # 418
    ("test_footer_missing.csv", NamedTuple(),
        (5, 3),
        NamedTuple{(:col1, :col2, :col3), Tuple{Union{Missing, Int64}, Union{Missing, Int64}, Union{Missing, Int64}}},
        (col1 = Union{Missing, Int64}[1, 4, 7, 10, missing], col2 = Union{Missing, Int64}[2, 5, 8, 11, missing], col3 = Union{Missing, Int64}[3, 6, 9, 12, missing])
    ),
    ("test_footer_missing.csv", (footerskip=1,),
        (4, 3),
        NamedTuple{(:col1, :col2, :col3), Tuple{Int64, Int64, Int64}},
        (col1 = [1, 4, 7, 10], col2 = [2, 5, 8, 11], col3 = [3, 6, 9, 12])
    ),
    ("test_dates.csv", NamedTuple(),
        (3, 1),
        NamedTuple{(:col1,), Tuple{Date}},
        (col1 = Date[Date("2015-01-01"), Date("2015-01-02"), Date("2015-01-03")],)
    ),
    ("test_excel_date_formats.csv", (dateformat="mm/dd/yy",),
        (3, 1),
        NamedTuple{(:col1,), Tuple{Date}},
        (col1 = Date[Date("2015-01-01"), Date("2015-01-02"), Date("2015-01-03")],)
    ),
    ("test_datetimes.csv", (dateformat="yyyy-mm-dd HH:MM:SS.s",),
        (3, 1),
        NamedTuple{(:col1,), Tuple{DateTime}},
        (col1 = DateTime[DateTime("2015-01-01"), DateTime("2015-01-02T00:00:01"), DateTime("2015-01-03T00:12:00.001")],)
    ),
    ("test_missing_value_NULL.csv", NamedTuple(),
        (3, 3),
        NamedTuple{(:col1, :col2, :col3),Tuple{Float64,String,Float64}},
        (col1 = [1.0, 4.0, 7.0], col2 = ["2.0", "NULL", "8.0"], col3 = [3.0, 6.0, 9.0])
    ),
    ("test_missing_value_NULL.csv", (missingstring="NULL",),
        (3, 3),
        NamedTuple{(:col1, :col2, :col3),Tuple{Float64,Union{Missing, Float64},Float64}},
        (col1 = [1.0, 4.0, 7.0], col2 = Union{Missing, Float64}[2.0, missing, 8.0], col3 = [3.0, 6.0, 9.0])
    ),
    ("test_missing_value.csv", NamedTuple(),
        (3, 3),
        NamedTuple{(:col1, :col2, :col3),Tuple{Float64,Union{Missing, Float64},Float64}},
        (col1 = [1.0, 4.0, 7.0], col2 = Union{Missing, Float64}[2.0, missing, 8.0], col3 = [3.0, 6.0, 9.0])
    ),
    ("test_header_range.csv", (header=1:3,),
        (3, 3),
        NamedTuple{(:col1_sub1_part1, :col2_sub2_part2, :col3_sub3_part3),Tuple{Int64,Int64,Int64}},
        (col1_sub1_part1 = [1, 4, 7], col2_sub2_part2 = [2, 5, 8], col3_sub3_part3 = [3, 6, 9])
    ),
    # 343
    ("test_header_int_list.csv", (header=[1, 3, 5],),
        (3, 3),
        NamedTuple{(:col1_sub1_part1, :col2_sub2_part2, :col3_sub3_part3),Tuple{Int64,Int64,Int64}},
        (col1_sub1_part1 = [1, 4, 7], col2_sub2_part2 = [2, 5, 8], col3_sub3_part3 = [3, 6, 9])
    ),
    ("test_basic.csv", (types=Dict(2=>Float64),),
        (3, 3),
        NamedTuple{(:col1, :col2, :col3),Tuple{Int64,Float64,Int64}},
        (col1 = [1, 4, 7], col2 = [2.0, 5.0, 8.0], col3 = [3, 6, 9])
    ),
    ("test_basic_pipe.csv", (delim='|',),
        (3, 3),
        NamedTuple{(:col1, :col2, :col3), Tuple{Int64, Int64, Int64}},
        (col1 = [1, 4, 7], col2 = [2, 5, 8], col3 = [3, 6, 9])
    ),
    ("test_tab_null_empty.txt", (delim='\t',),
        (2, 4),
        NamedTuple{(:A, :B, :C, :D),Tuple{Int64,Union{Missing, Int64},String,Int64}},
        (A = [1, 2], B = Union{Missing, Int64}[2000, missing], C = ["x", "y"], D = [100, 200])
    ),
    ("test_tab_null_string.txt", (delim='\t', missingstring="NULL"),
        (2, 4),
        NamedTuple{(:A, :B, :C, :D),Tuple{Int64,Union{Missing, Int64},String,Int64}},
        (A = [1, 2], B = Union{Missing, Int64}[2000, missing], C = ["x", "y"], D = [100, 200])
    ),
    # CSV with header and no data is treated the same as an empty buffer with header supplied
    (IOBuffer("a,b,c"), NamedTuple(),
        (0, 3),
        NamedTuple{(:a, :b, :c), Tuple{Missing, Missing, Missing}},
        (a = Missing[], b = Missing[], c = Missing[])
    ),
    (IOBuffer(""), (header=["a", "b", "c"],),
        (0, 3),
        NamedTuple{(:a, :b, :c), Tuple{Missing, Missing, Missing}},
        (a = Missing[], b = Missing[], c = Missing[])
    ),
    # dash as missingstring; #92
    ("dash_as_null.csv", (missingstring="-",),
        (2, 2),
        NamedTuple{(:x, :y),Tuple{Union{Missing, Int64}, Int64}},
        (x = Union{Missing, Int64}[1, missing], y = [2, 4])
    ),
    ("plus_as_null.csv", (missingstring="+",),
        (2, 2),
        NamedTuple{(:x, :y),Tuple{Union{Missing, Int64}, Int64}},
        (x = Union{Missing, Int64}[1, missing], y = [2, 4])
    ),
    # #83
    ("comma_decimal.csv", (delim=';', decimal=','),
        (2, 2),
        NamedTuple{(:x, :y),Tuple{Float64,Int64}},
        (x = [3.14, 1.0], y = [1, 1])
    ),
    # #86
    ("double_quote_quotechar_and_escapechar.csv", (escapechar='"',),
        (24, 5),
        NamedTuple{(:APINo, :FileNo, :CurrentWellName, :LeaseName, :OriginalWellName),Tuple{Float64,Int64,String,String,String}},
        x->x.OriginalWellName[24] == "NORTH DAKOTA STATE \"\"A\"\" #1"
    ),
    # #84
    ("census.txt", (normalizenames=true,),
        (3, 9),
        NamedTuple{(:GEOID, :POP10, :HU10, :ALAND, :AWATER, :ALAND_SQMI, :AWATER_SQMI, :INTPTLAT, :INTPTLONG),Tuple{Int64,Int64,Int64,Int64,Int64,Float64,Float64,Float64,Float64}},
        (GEOID = [601, 602, 603], POP10 = [18570, 41520, 54689], HU10 = [7744, 18073, 25653], ALAND = [166659789, 79288158, 81880442], AWATER = [799296, 4446273, 183425], ALAND_SQMI = [64.348, 30.613, 31.614], AWATER_SQMI = [0.309, 1.717, 0.071], INTPTLAT = [18.180555, 18.362268, 18.455183], INTPTLONG = [-66.749961, -67.17613, -67.119887])
    ),
    # #79
    ("bools.csv", NamedTuple(),
        (4, 3),
        NamedTuple{(:col1, :col2, :col3),Tuple{Bool,Bool,Int64}},
        (col1 = Bool[true, false, true, false], col2 = Bool[false, true, true, false], col3 = [1, 2, 3, 4])
    ),
    # #64
    # #115 (Int64 -> Union{Int64, Missing} -> Union{String, Missing} promotion)
    ("attenu.csv", (missingstring="NA",),
        (182, 5),
        NamedTuple{(:Event, :Mag, :Station, :Dist, :Accel),Tuple{Int64,Float64,Union{Missing, String},Float64,Float64}},
        x->map(y->y[1:10], x|>columntable) == (Event = [1, 2, 2, 2, 2, 2, 2, 2, 2, 2], Mag = [7.0, 7.4, 7.4, 7.4, 7.4, 7.4, 7.4, 7.4, 7.4, 7.4], Station = Union{Missing, String}["117", "1083", "1095", "283", "135", "475", "113", "1008", "1028", "2001"], Dist = [12.0, 148.0, 42.0, 85.0, 107.0, 109.0, 156.0, 224.0, 293.0, 359.0], Accel = [0.359, 0.014, 0.196, 0.135, 0.062, 0.054, 0.014, 0.018, 0.01, 0.004])
    ),
    ("test_null_only_column.csv", (missingstring="NA",),
        (3, 2),
        NamedTuple{(:col1, :col2),Tuple{String,Missing}},
        (col1 = ["123", "abc", "123abc"], col2 = Missing[missing, missing, missing])
    ),
    # #107
    (IOBuffer("1,a,i\n2,b,ii\n3,c,iii"), (datarow=1,),
        (3, 3),
        NamedTuple{(:Column1, :Column2, :Column3),Tuple{Int64,String,String}},
        (Column1 = [1, 2, 3], Column2 = ["a", "b", "c"], Column3 = ["i", "ii", "iii"])
    ),
    ("categorical.csv", (pool=true,),
        (15, 1),
        NamedTuple{(:cat,), Tuple{String}},
        (cat = ["a", "a", "a", "b", "b", "b", "b", "b", "b", "b", "c", "c", "c", "c", "a"],)
    ),
    ("categorical.csv", (pool=0.3,),
        (15, 1),
        NamedTuple{(:cat,), Tuple{String}},
        (cat = ["a", "a", "a", "b", "b", "b", "b", "b", "b", "b", "c", "c", "c", "c", "a"],)
    ),
    ("categorical.csv", (pool=false,),
        (15, 1),
        NamedTuple{(:cat,), Tuple{String}},
        (cat = ["a", "a", "a", "b", "b", "b", "b", "b", "b", "b", "c", "c", "c", "c", "a"],)
    ),
    ("categorical.csv", (pool=0.0,),
        (15, 1),
        NamedTuple{(:cat,), Tuple{String}},
        (cat = ["a", "a", "a", "b", "b", "b", "b", "b", "b", "b", "c", "c", "c", "c", "a"],)
    ),
    # other various files from around the interwebs
    ("baseball.csv", (pool=true, normalizenames=true),
        (35, 15),
        NamedTuple{(:Rk, :Year, :Age, :Tm, :Lg, :Column6, :W, :L, :W_L_, :G, :Finish, :Wpost, :Lpost, :W_L_post, :Column15), Tuple{Union{Int64, Missing},Union{Int64, Missing},Union{Int64, Missing},Union{String, Missing},Union{String, Missing},Union{String, Missing},Union{Int64, Missing},Union{Int64, Missing},Union{Float64, Missing},Union{Int64, Missing},Union{Float64, Missing},Union{Int64, Missing},Union{Int64, Missing},Union{Float64, Missing},Union{String, Missing}}},
        nothing
    ),
    ("FL_insurance_sample.csv", (pool=true,),
        (36634, 18),
        NamedTuple{(:policyID, :statecode, :county, :eq_site_limit, :hu_site_limit, :fl_site_limit, :fr_site_limit, :tiv_2011, :tiv_2012, :eq_site_deductible, :hu_site_deductible, :fl_site_deductible, :fr_site_deductible, :point_latitude, :point_longitude, :line, :construction, :point_granularity),Tuple{Int64,String,String,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Int64,Float64,Float64,String,String,Int64}},
        nothing
    ),
    ("FL_insurance_sample.csv", (pool=true,),
        (36634, 18),
        NamedTuple{(:policyID, :statecode, :county, :eq_site_limit, :hu_site_limit, :fl_site_limit, :fr_site_limit, :tiv_2011, :tiv_2012, :eq_site_deductible, :hu_site_deductible, :fl_site_deductible, :fr_site_deductible, :point_latitude, :point_longitude, :line, :construction, :point_granularity),Tuple{Int64,String,String,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Int64,Float64,Float64,String,String,Int64}},
        nothing
    ),
    ("SacramentocrimeJanuary2006.csv", (pool=true,),
        (7584, 9),
        NamedTuple{(:cdatetime, :address, :district, :beat, :grid, :crimedescr, :ucr_ncic_code, :latitude, :longitude),Tuple{String,String,Int64,String,Int64,String,Int64,Float64,Float64}},
        nothing
    ),
    ("Sacramentorealestatetransactions.csv", (pool=true, normalizenames=false),
        (985, 12),
        NamedTuple{(:street, :city, :zip, :state, :beds, :baths, :sq__ft, :type, :sale_date, :price, :latitude, :longitude),Tuple{String,String,Int64,String,Int64,Int64,Int64,String,String,Int64,Float64,Float64}},
        nothing
    ),
    ("SalesJan2009.csv", (pool=true,),
        (998, 12),
        NamedTuple{(:Transaction_date, :Product, :Price, :Payment_Type, :Name, :City, :State, :Country, :Account_Created, :Last_Login, :Latitude, :Longitude),Tuple{String,String,String,String,String,String,Union{Missing, String},String,String,String,Float64,Float64}},
        nothing
    ),
    ("stocks.csv", (normalizenames=true,),
        (30, 2),
        NamedTuple{(:Stock_Name, :Company_Name), Tuple{String, String}},
        nothing
    ),
    ("TechCrunchcontinentalUSA.csv", (pool=true,),
        (1460, 10),
        NamedTuple{(:permalink, :company, :numEmps, :category, :city, :state, :fundedDate, :raisedAmt, :raisedCurrency, :round),Tuple{String,String,Union{Missing, Int64},Union{Missing, String},Union{Missing, String},String,String,Int64,String,String}},
        nothing
    ),
    ("Fielding.csv", (pool=false,),
        (167938, 18),
        NamedTuple{(:playerID, :yearID, :stint, :teamID, :lgID, :POS, :G, :GS, :InnOuts, :PO, :A, :E, :DP, :PB, :WP, :SB, :CS, :ZR),Tuple{String,Int64,Int64,String,String,String,Int64,Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64}}},
        nothing
    ),
    ("latest (1).csv", (header=0, missingstring="\\N", pool=true),
        (1000, 25),
        NamedTuple{(:Column1, :Column2, :Column3, :Column4, :Column5, :Column6, :Column7, :Column8, :Column9, :Column10, :Column11, :Column12, :Column13, :Column14, :Column15, :Column16, :Column17, :Column18, :Column19, :Column20, :Column21, :Column22, :Column23, :Column24, :Column25),Tuple{String,String,Int64,Int64,String,Int64,String,Int64,Date,Date,Int64,String,Union{Missing, Float64},Union{Missing, Float64},Union{Missing, Float64},Union{Missing, Float64},Union{Missing, Int64},Union{Missing, Float64},Float64,Union{Missing, Float64},Union{Missing, Float64},Union{Missing, Int64},Float64,Union{Missing, Float64},Union{Missing, Float64}}},
        nothing
    ),
    # #217
    (IOBuffer("aa,bb\n1,\"1,b,c\"\n"), (pool=false,),
        (1, 2),
        NamedTuple{(:aa, :bb), Tuple{Int64, String}},
        (aa = [1], bb = ["1,b,c"])
    ),
    # #198
    ("issue_198.csv", (decimal=',', delim=';', missingstring="-", datarow = 2, header = ["Date", "EONIA", "1m", "12m", "3m", "6m", "9m"], normalizenames=false),
        (6, 7),
        NamedTuple{(:Date, :EONIA, Symbol("1m"), Symbol("12m"), Symbol("3m"), Symbol("6m"), Symbol("9m")),Tuple{String,Union{Missing, Float64},Union{Missing, Float64},Union{Missing, Float64},Union{Missing, Float64},Union{Missing, Float64},Union{Missing, Float64}}},
        NamedTuple{(:Date, :EONIA, Symbol("1m"), Symbol("12m"), Symbol("3m"), Symbol("6m"), Symbol("9m"))}((String["18/04/2018", "17/04/2018", "16/04/2018", "15/04/2018", "14/04/2018", "13/04/2018"], Union{Missing, Float64}[-0.368, -0.368, -0.367, missing, missing, -0.364], Union{Missing, Float64}[-0.371, -0.371, -0.371, missing, missing, -0.371], Union{Missing, Float64}[-0.189, -0.189, -0.189, missing, missing, -0.19], Union{Missing, Float64}[-0.328, -0.328, -0.329, missing, missing, -0.329], Union{Missing, Float64}[-0.271, -0.27, -0.27, missing, missing, -0.271], Union{Missing, Float64}[-0.219, -0.219, -0.219, missing, missing, -0.219]))
    ),
    # #198 part 2
    ("issue_198_part2.csv", (missingstring="++", delim=';', decimal=','),
        (4, 3),
        NamedTuple{(:A, :B, :C),Tuple{String,Union{Missing, Float64},Union{Missing, Float64}}},
        (A = ["a", "b", "c", "d"], B = Union{Missing, Float64}[-0.367, missing, missing, -0.364], C = Union{Missing, Float64}[-0.371, missing, missing, -0.371])
    ),
    # #207
    ("issue_207.csv", NamedTuple(),
        (2, 6),
        NamedTuple{(:a, :b, :c, :d, :e, :f),Tuple{Int64,Int64,Int64,Float64,String,Union{Missing, Float64}}},
        (a = [1863001, 1863209], b = [134, 137], c = [10000, 0], d = [1.0009, 1.0], e = ["1.0000", "2,773.9000"], f = Union{Missing, Float64}[-0.002033899, missing])
    ),
    # #120
    ("issue_120.csv", (header=0,),
        (5, 20),
        NamedTuple{(:Column1, :Column2, :Column3, :Column4, :Column5, :Column6, :Column7, :Column8, :Column9, :Column10, :Column11, :Column12, :Column13, :Column14, :Column15, :Column16, :Column17, :Column18, :Column19, :Column20),Tuple{Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Int64,Int64,Int64,Int64,Missing,Float64,Float64,Float64,Float64,Float64,Float64}},
        (Column1 = [3.52848962348857e9, 3.52848962448866e9, 3.52848962548857e9, 3.52848962648866e9, 3.52848962748875e9], Column2 = [312.73, 312.49, 312.74, 312.49, 312.62], Column3 = [0.0, 0.0, 0.0, 0.0, 0.0], Column4 = [41.87425, 41.87623, 41.87155, 41.86422, 41.87615], Column5 = [297.6302, 297.6342, 297.6327, 297.632, 297.6324], Column6 = [0.0, 0.0, 0.0, 0.0, 0.0], Column7 = [286.3423, 286.3563, 286.3723, 286.3837, 286.397], Column8 = [-99.99, -99.99, -99.99, -99.99, -99.99], Column9 = [-99.99, -99.99, -99.99, -99.99, -99.99], Column10 = [12716, 12716, 12716, 12716, 12716], Column11 = [0, 0, 0, 0, 0], Column12 = [0, 0, 0, 0, 0], Column13 = [0, 0, 0, 0, 0], Column14 = Missing[missing, missing, missing, missing, missing], Column15 = [-24.81942, -24.8206, -24.82111, -24.82091, -24.82035], Column16 = [853.8073, 852.1921, 853.4257, 854.1342, 851.171], Column17 = [0.0, 0.0, 0.0, 0.0, 0.0], Column18 = [0.0, 0.0, 0.0, 0.0, 0.0], Column19 = [60.07, 38.27, 61.38, 49.23, 42.49], Column20 = [132.356, 132.356, 132.356, 132.356, 132.356])
    ),
    ("pandas_zeros.csv", (normalizenames=true,),
        (100000, 50),
        NamedTuple{Tuple(Symbol("_$i") for i = 0:49), NTuple{50, Int64}},
        nothing
    ),
    # ("table_test.txt", NamedTuple(),
    #     (49, 770),
    #     NamedTuple{(:ind_50km, :nse_gsurf_cfg1, :r_gsurf_cfg1, :bias_gsurf_cfg1, :ngrids, :nse_hatmo_cfg1, :r_hatmo_cfg1, :bias_hatmo_cfg1, :nse_latmo_cfg1, :r_latmo_cfg1, :bias_latmo_cfg1, :nse_melt_cfg1, :r_melt_cfg1, :bias_melt_cfg1, :nse_rnet_cfg1, :r_rnet_cfg1, :bias_rnet_cfg1, :nse_rof_cfg1, :r_rof_cfg1, :bias_rof_cfg1, :nse_snowdepth_cfg1, :r_snowdepth_cfg1, :bias_snowdepth_cfg1, :nse_swe_cfg1, :r_swe_cfg1, :bias_swe_cfg1, :nse_gsurf_cfg2, :r_gsurf_cfg2, :bias_gsurf_cfg2, :nse_hatmo_cfg2, :r_hatmo_cfg2, :bias_hatmo_cfg2, :nse_latmo_cfg2, :r_latmo_cfg2, :bias_latmo_cfg2, :nse_melt_cfg2, :r_melt_cfg2, :bias_melt_cfg2, :nse_rnet_cfg2, :r_rnet_cfg2, :bias_rnet_cfg2, :nse_rof_cfg2, :r_rof_cfg2, :bias_rof_cfg2, :nse_snowdepth_cfg2, :r_snowdepth_cfg2, :bias_snowdepth_cfg2, :nse_swe_cfg2, :r_swe_cfg2, :bias_swe_cfg2, :nse_gsurf_cfg3, :r_gsurf_cfg3, :bias_gsurf_cfg3, :nse_hatmo_cfg3, :r_hatmo_cfg3, :bias_hatmo_cfg3, :nse_latmo_cfg3, :r_latmo_cfg3, :bias_latmo_cfg3, :nse_melt_cfg3, :r_melt_cfg3, :bias_melt_cfg3, :nse_rnet_cfg3, :r_rnet_cfg3, :bias_rnet_cfg3, :nse_rof_cfg3, :r_rof_cfg3, :bias_rof_cfg3, :nse_snowdepth_cfg3, :r_snowdepth_cfg3, :bias_snowdepth_cfg3, :nse_swe_cfg3, :r_swe_cfg3, :bias_swe_cfg3, :nse_gsurf_cfg4, :r_gsurf_cfg4, :bias_gsurf_cfg4, :nse_hatmo_cfg4, :r_hatmo_cfg4, :bias_hatmo_cfg4, :nse_latmo_cfg4, :r_latmo_cfg4, :bias_latmo_cfg4, :nse_melt_cfg4, :r_melt_cfg4, :bias_melt_cfg4, :nse_rnet_cfg4, :r_rnet_cfg4, :bias_rnet_cfg4, :nse_rof_cfg4, :r_rof_cfg4, :bias_rof_cfg4, :nse_snowdepth_cfg4, :r_snowdepth_cfg4, :bias_snowdepth_cfg4, :nse_swe_cfg4, :r_swe_cfg4, :bias_swe_cfg4, :nse_gsurf_cfg5, :r_gsurf_cfg5, :bias_gsurf_cfg5, :nse_hatmo_cfg5, :r_hatmo_cfg5, :bias_hatmo_cfg5, :nse_latmo_cfg5, :r_latmo_cfg5, :bias_latmo_cfg5, :nse_melt_cfg5, :r_melt_cfg5, :bias_melt_cfg5, :nse_rnet_cfg5, :r_rnet_cfg5, :bias_rnet_cfg5, :nse_rof_cfg5, :r_rof_cfg5, :bias_rof_cfg5, :nse_snowdepth_cfg5, :r_snowdepth_cfg5, :bias_snowdepth_cfg5, :nse_swe_cfg5, :r_swe_cfg5, :bias_swe_cfg5, :nse_gsurf_cfg6, :r_gsurf_cfg6, :bias_gsurf_cfg6, :nse_hatmo_cfg6, :r_hatmo_cfg6, :bias_hatmo_cfg6, :nse_latmo_cfg6, :r_latmo_cfg6, :bias_latmo_cfg6, :nse_melt_cfg6, :r_melt_cfg6, :bias_melt_cfg6, :nse_rnet_cfg6, :r_rnet_cfg6, :bias_rnet_cfg6, :nse_rof_cfg6, :r_rof_cfg6, :bias_rof_cfg6, :nse_snowdepth_cfg6, :r_snowdepth_cfg6, :bias_snowdepth_cfg6, :nse_swe_cfg6, :r_swe_cfg6, :bias_swe_cfg6, :nse_gsurf_cfg7, :r_gsurf_cfg7, :bias_gsurf_cfg7, :nse_hatmo_cfg7, :r_hatmo_cfg7, :bias_hatmo_cfg7, :nse_latmo_cfg7, :r_latmo_cfg7, :bias_latmo_cfg7, :nse_melt_cfg7, :r_melt_cfg7, :bias_melt_cfg7, :nse_rnet_cfg7, :r_rnet_cfg7, :bias_rnet_cfg7, :nse_rof_cfg7, :r_rof_cfg7, :bias_rof_cfg7, :nse_snowdepth_cfg7, :r_snowdepth_cfg7, :bias_snowdepth_cfg7, :nse_swe_cfg7, :r_swe_cfg7, :bias_swe_cfg7, :nse_gsurf_cfg8, :r_gsurf_cfg8, :bias_gsurf_cfg8, :nse_hatmo_cfg8, :r_hatmo_cfg8, :bias_hatmo_cfg8, :nse_latmo_cfg8, :r_latmo_cfg8, :bias_latmo_cfg8, :nse_melt_cfg8, :r_melt_cfg8, :bias_melt_cfg8, :nse_rnet_cfg8, :r_rnet_cfg8, :bias_rnet_cfg8, :nse_rof_cfg8, :r_rof_cfg8, :bias_rof_cfg8, :nse_snowdepth_cfg8, :r_snowdepth_cfg8, :bias_snowdepth_cfg8, :nse_swe_cfg8, :r_swe_cfg8, :bias_swe_cfg8, :nse_gsurf_cfg9, :r_gsurf_cfg9, :bias_gsurf_cfg9, :nse_hatmo_cfg9, :r_hatmo_cfg9, :bias_hatmo_cfg9, :nse_latmo_cfg9, :r_latmo_cfg9, :bias_latmo_cfg9, :nse_melt_cfg9, :r_melt_cfg9, :bias_melt_cfg9, :nse_rnet_cfg9, :r_rnet_cfg9, :bias_rnet_cfg9, :nse_rof_cfg9, :r_rof_cfg9, :bias_rof_cfg9, :nse_snowdepth_cfg9, :r_snowdepth_cfg9, :bias_snowdepth_cfg9, :nse_swe_cfg9, :r_swe_cfg9, :bias_swe_cfg9, :nse_gsurf_cfg10, :r_gsurf_cfg10, :bias_gsurf_cfg10, :nse_hatmo_cfg10, :r_hatmo_cfg10, :bias_hatmo_cfg10, :nse_latmo_cfg10, :r_latmo_cfg10, :bias_latmo_cfg10, :nse_melt_cfg10, :r_melt_cfg10, :bias_melt_cfg10, :nse_rnet_cfg10, :r_rnet_cfg10, :bias_rnet_cfg10, :nse_rof_cfg10, :r_rof_cfg10, :bias_rof_cfg10, :nse_snowdepth_cfg10, :r_snowdepth_cfg10, :bias_snowdepth_cfg10, :nse_swe_cfg10, :r_swe_cfg10, :bias_swe_cfg10, :nse_gsurf_cfg11, :r_gsurf_cfg11, :bias_gsurf_cfg11, :nse_hatmo_cfg11, :r_hatmo_cfg11, :bias_hatmo_cfg11, :nse_latmo_cfg11, :r_latmo_cfg11, :bias_latmo_cfg11, :nse_melt_cfg11, :r_melt_cfg11, :bias_melt_cfg11, :nse_rnet_cfg11, :r_rnet_cfg11, :bias_rnet_cfg11, :nse_rof_cfg11, :r_rof_cfg11, :bias_rof_cfg11, :nse_snowdepth_cfg11, :r_snowdepth_cfg11, :bias_snowdepth_cfg11, :nse_swe_cfg11, :r_swe_cfg11, :bias_swe_cfg11, :nse_gsurf_cfg12, :r_gsurf_cfg12, :bias_gsurf_cfg12, :nse_hatmo_cfg12, :r_hatmo_cfg12, :bias_hatmo_cfg12, :nse_latmo_cfg12, :r_latmo_cfg12, :bias_latmo_cfg12, :nse_melt_cfg12, :r_melt_cfg12, :bias_melt_cfg12, :nse_rnet_cfg12, :r_rnet_cfg12, :bias_rnet_cfg12, :nse_rof_cfg12, :r_rof_cfg12, :bias_rof_cfg12, :nse_snowdepth_cfg12, :r_snowdepth_cfg12, :bias_snowdepth_cfg12, :nse_swe_cfg12, :r_swe_cfg12, :bias_swe_cfg12, :nse_gsurf_cfg13, :r_gsurf_cfg13, :bias_gsurf_cfg13, :nse_hatmo_cfg13, :r_hatmo_cfg13, :bias_hatmo_cfg13, :nse_latmo_cfg13, :r_latmo_cfg13, :bias_latmo_cfg13, :nse_melt_cfg13, :r_melt_cfg13, :bias_melt_cfg13, :nse_rnet_cfg13, :r_rnet_cfg13, :bias_rnet_cfg13, :nse_rof_cfg13, :r_rof_cfg13, :bias_rof_cfg13, :nse_snowdepth_cfg13, :r_snowdepth_cfg13, :bias_snowdepth_cfg13, :nse_swe_cfg13, :r_swe_cfg13, :bias_swe_cfg13, :nse_gsurf_cfg14, :r_gsurf_cfg14, :bias_gsurf_cfg14, :nse_hatmo_cfg14, :r_hatmo_cfg14, :bias_hatmo_cfg14, :nse_latmo_cfg14, :r_latmo_cfg14, :bias_latmo_cfg14, :nse_melt_cfg14, :r_melt_cfg14, :bias_melt_cfg14, :nse_rnet_cfg14, :r_rnet_cfg14, :bias_rnet_cfg14, :nse_rof_cfg14, :r_rof_cfg14, :bias_rof_cfg14, :nse_snowdepth_cfg14, :r_snowdepth_cfg14, :bias_snowdepth_cfg14, :nse_swe_cfg14, :r_swe_cfg14, :bias_swe_cfg14, :nse_gsurf_cfg15, :r_gsurf_cfg15, :bias_gsurf_cfg15, :nse_hatmo_cfg15, :r_hatmo_cfg15, :bias_hatmo_cfg15, :nse_latmo_cfg15, :r_latmo_cfg15, :bias_latmo_cfg15, :nse_melt_cfg15, :r_melt_cfg15, :bias_melt_cfg15, :nse_rnet_cfg15, :r_rnet_cfg15, :bias_rnet_cfg15, :nse_rof_cfg15, :r_rof_cfg15, :bias_rof_cfg15, :nse_snowdepth_cfg15, :r_snowdepth_cfg15, :bias_snowdepth_cfg15, :nse_swe_cfg15, :r_swe_cfg15, :bias_swe_cfg15, :nse_gsurf_cfg16, :r_gsurf_cfg16, :bias_gsurf_cfg16, :nse_hatmo_cfg16, :r_hatmo_cfg16, :bias_hatmo_cfg16, :nse_latmo_cfg16, :r_latmo_cfg16, :bias_latmo_cfg16, :nse_melt_cfg16, :r_melt_cfg16, :bias_melt_cfg16, :nse_rnet_cfg16, :r_rnet_cfg16, :bias_rnet_cfg16, :nse_rof_cfg16, :r_rof_cfg16, :bias_rof_cfg16, :nse_snowdepth_cfg16, :r_snowdepth_cfg16, :bias_snowdepth_cfg16, :nse_swe_cfg16, :r_swe_cfg16, :bias_swe_cfg16, :nse_gsurf_cfg17, :r_gsurf_cfg17, :bias_gsurf_cfg17, :nse_hatmo_cfg17, :r_hatmo_cfg17, :bias_hatmo_cfg17, :nse_latmo_cfg17, :r_latmo_cfg17, :bias_latmo_cfg17, :nse_melt_cfg17, :r_melt_cfg17, :bias_melt_cfg17, :nse_rnet_cfg17, :r_rnet_cfg17, :bias_rnet_cfg17, :nse_rof_cfg17, :r_rof_cfg17, :bias_rof_cfg17, :nse_snowdepth_cfg17, :r_snowdepth_cfg17, :bias_snowdepth_cfg17, :nse_swe_cfg17, :r_swe_cfg17, :bias_swe_cfg17, :nse_gsurf_cfg18, :r_gsurf_cfg18, :bias_gsurf_cfg18, :nse_hatmo_cfg18, :r_hatmo_cfg18, :bias_hatmo_cfg18, :nse_latmo_cfg18, :r_latmo_cfg18, :bias_latmo_cfg18, :nse_melt_cfg18, :r_melt_cfg18, :bias_melt_cfg18, :nse_rnet_cfg18, :r_rnet_cfg18, :bias_rnet_cfg18, :nse_rof_cfg18, :r_rof_cfg18, :bias_rof_cfg18, :nse_snowdepth_cfg18, :r_snowdepth_cfg18, :bias_snowdepth_cfg18, :nse_swe_cfg18, :r_swe_cfg18, :bias_swe_cfg18, :nse_gsurf_cfg19, :r_gsurf_cfg19, :bias_gsurf_cfg19, :nse_hatmo_cfg19, :r_hatmo_cfg19, :bias_hatmo_cfg19, :nse_latmo_cfg19, :r_latmo_cfg19, :bias_latmo_cfg19, :nse_melt_cfg19, :r_melt_cfg19, :bias_melt_cfg19, :nse_rnet_cfg19, :r_rnet_cfg19, :bias_rnet_cfg19, :nse_rof_cfg19, :r_rof_cfg19, :bias_rof_cfg19, :nse_snowdepth_cfg19, :r_snowdepth_cfg19, :bias_snowdepth_cfg19, :nse_swe_cfg19, :r_swe_cfg19, :bias_swe_cfg19, :nse_gsurf_cfg20, :r_gsurf_cfg20, :bias_gsurf_cfg20, :nse_hatmo_cfg20, :r_hatmo_cfg20, :bias_hatmo_cfg20, :nse_latmo_cfg20, :r_latmo_cfg20, :bias_latmo_cfg20, :nse_melt_cfg20, :r_melt_cfg20, :bias_melt_cfg20, :nse_rnet_cfg20, :r_rnet_cfg20, :bias_rnet_cfg20, :nse_rof_cfg20, :r_rof_cfg20, :bias_rof_cfg20, :nse_snowdepth_cfg20, :r_snowdepth_cfg20, :bias_snowdepth_cfg20, :nse_swe_cfg20, :r_swe_cfg20, :bias_swe_cfg20, :nse_gsurf_cfg21, :r_gsurf_cfg21, :bias_gsurf_cfg21, :nse_hatmo_cfg21, :r_hatmo_cfg21, :bias_hatmo_cfg21, :nse_latmo_cfg21, :r_latmo_cfg21, :bias_latmo_cfg21, :nse_melt_cfg21, :r_melt_cfg21, :bias_melt_cfg21, :nse_rnet_cfg21, :r_rnet_cfg21, :bias_rnet_cfg21, :nse_rof_cfg21, :r_rof_cfg21, :bias_rof_cfg21, :nse_snowdepth_cfg21, :r_snowdepth_cfg21, :bias_snowdepth_cfg21, :nse_swe_cfg21, :r_swe_cfg21, :bias_swe_cfg21, :nse_gsurf_cfg22, :r_gsurf_cfg22, :bias_gsurf_cfg22, :nse_hatmo_cfg22, :r_hatmo_cfg22, :bias_hatmo_cfg22, :nse_latmo_cfg22, :r_latmo_cfg22, :bias_latmo_cfg22, :nse_melt_cfg22, :r_melt_cfg22, :bias_melt_cfg22, :nse_rnet_cfg22, :r_rnet_cfg22, :bias_rnet_cfg22, :nse_rof_cfg22, :r_rof_cfg22, :bias_rof_cfg22, :nse_snowdepth_cfg22, :r_snowdepth_cfg22, :bias_snowdepth_cfg22, :nse_swe_cfg22, :r_swe_cfg22, :bias_swe_cfg22, :nse_gsurf_cfg23, :r_gsurf_cfg23, :bias_gsurf_cfg23, :nse_hatmo_cfg23, :r_hatmo_cfg23, :bias_hatmo_cfg23, :nse_latmo_cfg23, :r_latmo_cfg23, :bias_latmo_cfg23, :nse_melt_cfg23, :r_melt_cfg23, :bias_melt_cfg23, :nse_rnet_cfg23, :r_rnet_cfg23, :bias_rnet_cfg23, :nse_rof_cfg23, :r_rof_cfg23, :bias_rof_cfg23, :nse_snowdepth_cfg23, :r_snowdepth_cfg23, :bias_snowdepth_cfg23, :nse_swe_cfg23, :r_swe_cfg23, :bias_swe_cfg23, :nse_gsurf_cfg24, :r_gsurf_cfg24, :bias_gsurf_cfg24, :nse_hatmo_cfg24, :r_hatmo_cfg24, :bias_hatmo_cfg24, :nse_latmo_cfg24, :r_latmo_cfg24, :bias_latmo_cfg24, :nse_melt_cfg24, :r_melt_cfg24, :bias_melt_cfg24, :nse_rnet_cfg24, :r_rnet_cfg24, :bias_rnet_cfg24, :nse_rof_cfg24, :r_rof_cfg24, :bias_rof_cfg24, :nse_snowdepth_cfg24, :r_snowdepth_cfg24, :bias_snowdepth_cfg24, :nse_swe_cfg24, :r_swe_cfg24, :bias_swe_cfg24, :nse_gsurf_cfg25, :r_gsurf_cfg25, :bias_gsurf_cfg25, :nse_hatmo_cfg25, :r_hatmo_cfg25, :bias_hatmo_cfg25, :nse_latmo_cfg25, :r_latmo_cfg25, :bias_latmo_cfg25, :nse_melt_cfg25, :r_melt_cfg25, :bias_melt_cfg25, :nse_rnet_cfg25, :r_rnet_cfg25, :bias_rnet_cfg25, :nse_rof_cfg25, :r_rof_cfg25, :bias_rof_cfg25, :nse_snowdepth_cfg25, :r_snowdepth_cfg25, :bias_snowdepth_cfg25, :nse_swe_cfg25, :r_swe_cfg25, :bias_swe_cfg25, :nse_gsurf_cfg26, :r_gsurf_cfg26, :bias_gsurf_cfg26, :nse_hatmo_cfg26, :r_hatmo_cfg26, :bias_hatmo_cfg26, :nse_latmo_cfg26, :r_latmo_cfg26, :bias_latmo_cfg26, :nse_melt_cfg26, :r_melt_cfg26, :bias_melt_cfg26, :nse_rnet_cfg26, :r_rnet_cfg26, :bias_rnet_cfg26, :nse_rof_cfg26, :r_rof_cfg26, :bias_rof_cfg26, :nse_snowdepth_cfg26, :r_snowdepth_cfg26, :bias_snowdepth_cfg26, :nse_swe_cfg26, :r_swe_cfg26, :bias_swe_cfg26, :nse_gsurf_cfg27, :r_gsurf_cfg27, :bias_gsurf_cfg27, :nse_hatmo_cfg27, :r_hatmo_cfg27, :bias_hatmo_cfg27, :nse_latmo_cfg27, :r_latmo_cfg27, :bias_latmo_cfg27, :nse_melt_cfg27, :r_melt_cfg27, :bias_melt_cfg27, :nse_rnet_cfg27, :r_rnet_cfg27, :bias_rnet_cfg27, :nse_rof_cfg27, :r_rof_cfg27, :bias_rof_cfg27, :nse_snowdepth_cfg27, :r_snowdepth_cfg27, :bias_snowdepth_cfg27, :nse_swe_cfg27, :r_swe_cfg27, :bias_swe_cfg27, :nse_gsurf_cfg28, :r_gsurf_cfg28, :bias_gsurf_cfg28, :nse_hatmo_cfg28, :r_hatmo_cfg28, :bias_hatmo_cfg28, :nse_latmo_cfg28, :r_latmo_cfg28, :bias_latmo_cfg28, :nse_melt_cfg28, :r_melt_cfg28, :bias_melt_cfg28, :nse_rnet_cfg28, :r_rnet_cfg28, :bias_rnet_cfg28, :nse_rof_cfg28, :r_rof_cfg28, :bias_rof_cfg28, :nse_snowdepth_cfg28, :r_snowdepth_cfg28, :bias_snowdepth_cfg28, :nse_swe_cfg28, :r_swe_cfg28, :bias_swe_cfg28, :nse_gsurf_cfg29, :r_gsurf_cfg29, :bias_gsurf_cfg29, :nse_hatmo_cfg29, :r_hatmo_cfg29, :bias_hatmo_cfg29, :nse_latmo_cfg29, :r_latmo_cfg29, :bias_latmo_cfg29, :nse_melt_cfg29, :r_melt_cfg29, :bias_melt_cfg29, :nse_rnet_cfg29, :r_rnet_cfg29, :bias_rnet_cfg29, :nse_rof_cfg29, :r_rof_cfg29, :bias_rof_cfg29, :nse_snowdepth_cfg29, :r_snowdepth_cfg29, :bias_snowdepth_cfg29, :nse_swe_cfg29, :r_swe_cfg29, :bias_swe_cfg29, :nse_gsurf_cfg30, :r_gsurf_cfg30, :bias_gsurf_cfg30, :nse_hatmo_cfg30, :r_hatmo_cfg30, :bias_hatmo_cfg30, :nse_latmo_cfg30, :r_latmo_cfg30, :bias_latmo_cfg30, :nse_melt_cfg30, :r_melt_cfg30, :bias_melt_cfg30, :nse_rnet_cfg30, :r_rnet_cfg30, :bias_rnet_cfg30, :nse_rof_cfg30, :r_rof_cfg30, :bias_rof_cfg30, :nse_snowdepth_cfg30, :r_snowdepth_cfg30, :bias_snowdepth_cfg30, :nse_swe_cfg30, :r_swe_cfg30, :bias_swe_cfg30, :nse_gsurf_cfg31, :r_gsurf_cfg31, :bias_gsurf_cfg31, :nse_hatmo_cfg31, :r_hatmo_cfg31, :bias_hatmo_cfg31, :nse_latmo_cfg31, :r_latmo_cfg31, :bias_latmo_cfg31, :nse_melt_cfg31, :r_melt_cfg31, :bias_melt_cfg31, :nse_rnet_cfg31, :r_rnet_cfg31, :bias_rnet_cfg31, :nse_rof_cfg31, :r_rof_cfg31, :bias_rof_cfg31, :nse_snowdepth_cfg31, :r_snowdepth_cfg31, :bias_snowdepth_cfg31, :nse_swe_cfg31, :r_swe_cfg31, :bias_swe_cfg31, :nse_gsurf_cfg32, :r_gsurf_cfg32, :bias_gsurf_cfg32, :nse_hatmo_cfg32, :r_hatmo_cfg32, :bias_hatmo_cfg32, :nse_latmo_cfg32, :r_latmo_cfg32, :bias_latmo_cfg32, :nse_melt_cfg32, :r_melt_cfg32, :bias_melt_cfg32, :nse_rnet_cfg32, :r_rnet_cfg32, :bias_rnet_cfg32, :nse_rof_cfg32, :r_rof_cfg32, :bias_rof_cfg32, :nse_snowdepth_cfg32, :r_snowdepth_cfg32, :bias_snowdepth_cfg32, :nse_swe_cfg32, :r_swe_cfg32, :bias_swe_cfg32),Tuple{Int64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64,Float64}},
    #     nothing
    # ),
    ("transposed.csv", (transpose=true,),
        (3, 3),
        NamedTuple{(:col1, :col2, :col3),Tuple{Int64,Int64,Int64}},
        (col1 = [1, 2, 3], col2 = [4, 5, 6], col3 = [7, 8, 9])
    ),
    ("transposed_1row.csv", (transpose=true,),
        (1, 1),
        NamedTuple{(:col1,),Tuple{Int64}},
        (col1 = [1],)
    ),
    ("transposed_emtpy.csv", (transpose=true,),
        (0, 1),
        NamedTuple{(:col1,),Tuple{Missing}},
        (col1 = Missing[],)
    ),
    ("transposed_extra_newline.csv", (transpose=true,),
        (2, 2),
        NamedTuple{(:col1, :col2),Tuple{Int64,Int64}},
        (col1 = [1, 2], col2 = [3, 4])
    ),
    ("transposed_noheader.csv", (transpose=true, header=0),
        (2, 3),
        NamedTuple{(:Column1, :Column2, :Column3),Tuple{Int64,Int64,Int64}},
        (Column1 = [1, 2], Column2 = [3, 4], Column3 = [5, 6])
    ),
    ("transposed_noheader.csv", (transpose=true, header=["c1", "c2", "c3"]),
        (2, 3),
        NamedTuple{(:c1, :c2, :c3),Tuple{Int64,Int64,Int64}},
        (c1 = [1, 2], c2 = [3, 4], c3 = [5, 6])
    ),
    ("test_utf8.csv", (limit=2,),
        (2, 3),
        NamedTuple{(:col1, :col2, :col3),Tuple{Float64,Float64,Float64}},
        (col1 = Union{Missing, Float64}[1.0, 4.0], col2 = Union{Missing, Float64}[2.0, 5.0], col3 = Union{Missing, Float64}[3.0, 6.0])
    ),
    ("test_utf8.csv", (limit=4,),
        (3, 3),
        NamedTuple{(:col1, :col2, :col3),Tuple{Float64,Float64,Float64}},
        (col1 = Union{Missing, Float64}[1.0, 4.0, 7.0], col2 = Union{Missing, Float64}[2.0, 5.0, 8.0], col3 = Union{Missing, Float64}[3.0, 6.0, 9.0])
    ),
    ("test_multiple_missing.csv", (missingstrings=["NA", "NULL", "\\N"],),
        (4, 3),
        NamedTuple{(:col1, :col2, :col3), Tuple{Float64, Union{Missing, Float64}, Float64}},
        (col1 = [1.0, 4.0, 7.0, 7.0], col2 = Union{Missing, Float64}[2.0, missing, missing, missing], col3 = [3.0, 6.0, 9.0, 9.0])
    ),
    ("test_openclosequotes.csv", (missingstrings=["NA", "NULL"], openquotechar='{', closequotechar='}'),
        (3, 3),
        NamedTuple{(:col1, :col2, :col3), Tuple{Float64, Union{Missing, Float64}, Float64}},
        (col1 = [1.0, 4.0, 7.0], col2 = Union{Missing, Float64}[2.0, missing, missing], col3 = [3.0, 6.0, 9.0])
    ),
    ("test_truestrings.csv", (truestrings=["T", "TRUE", "true"], falsestrings=["F", "FALSE", "false"]),
        (6, 2),
        NamedTuple{(:int, :bools), Tuple{Int64, Bool}},
        (int = [1, 2, 3, 4, 5, 6], bools = Bool[true, true, true, false, false, false])
    ),
    ("test_truestrings.csv", (truestrings=["T", "TRUE", "true"], falsestrings=["F", "FALSE", "false"], typemap=Dict(Bool=>String)),
        (6, 2),
        NamedTuple{(:int, :bools), Tuple{Int64, String}},
        (int = [1, 2, 3, 4, 5, 6], bools = ["T", "TRUE", "true", "F", "FALSE", "false"])
    ),
    ("test_string_delimiters.csv", (delim="::",),
        (2, 4),
        NamedTuple{(:num1, :num2, :num3, :num4), Tuple{Int64, Int64, Int64, Int64}},
        (num1 = [1, 1], num2 = [1193, 661], num3 = [5, 3], num4 = [978300760, 978302109])
    ),
    (IOBuffer("1,a,i\n2,b,ii\n3,c,iii"), (skipto=1,),
        (3, 3),
        NamedTuple{(:Column1, :Column2, :Column3),Tuple{Int64,String,String}},
        (Column1 = [1, 2, 3], Column2 = ["a", "b", "c"], Column3 = ["i", "ii", "iii"])
    ),
    # #249
    ("test_basic.csv", (types=Dict(:col2=>Float64),),
        (3, 3),
        NamedTuple{(:col1, :col2, :col3),Tuple{Int64,Float64,Int64}},
        (col1 = [1, 4, 7], col2 = [2.0, 5.0, 8.0], col3 = [3, 6, 9])
    ),
    # #251
    ("test_basic.csv", (types=Dict(:col2=>Union{Float64, Missing}),),
        (3, 3),
        NamedTuple{(:col1, :col2, :col3),Tuple{Int64,Union{Missing,Float64},Int64}},
        (col1 = [1, 4, 7], col2 = Union{Missing,Float64}[2.0, 5.0, 8.0], col3 = [3, 6, 9])
    ),
    ("test_truestrings.csv", (truestrings=["T", "TRUE", "true"], falsestrings=["F", "FALSE", "false"]),
        (6, 2),
        NamedTuple{(:int, :bools), Tuple{Int64, Bool}},
        (int = [1, 2, 3, 4, 5, 6], bools = [true, true, true, false, false, false])
    ),
    ("test_repeated_delimiters.csv", (delim=" ", ignorerepeated=true),
        (3, 5),
        NamedTuple{(:a, :b, :c, :d, :e), Tuple{Int64, Int64, Int64, Int64, Int64}},
        (a = [1, 1, 1], b = [2, 2, 2], c = [3, 3, 3], d = [4, 4, 4], e = [5, 5, 5])
    ),
    ("test_comments1.csv", (comment="#",),
        (2, 3),
        NamedTuple{(:a, :b, :c), Tuple{Int64, Int64, Int64}},
        (a=[1,7], b=[2,8], c=[3,9])
    ),
    ("test_comments_multiple.csv", (comment="#",),
        (4, 3),
        NamedTuple{(:a, :b, :c), Tuple{Int64, Int64, Int64}},
        (a = [1, 7, 10, 13], b = [2, 8, 11, 14], c = [3, 9, 12, 15])
    ),
    ("test_comments_multichar.csv", (comment="//",),
        (2, 3),
        NamedTuple{(:a, :b, :c), Tuple{Int64, Int64, Int64}},
        (a=[1,7], b=[2,8], c=[3,9])
    ),
    # #230
    ("test_not_enough_columns.csv", NamedTuple(),
        (2, 5),
        NamedTuple{(:A, :B, :C, :D, :E),Tuple{Int64,Int64,Int64,Missing,Missing}},
        (A = [1, 4], B = [2, 5], C = [3, 6], D = Missing[missing, missing], E = Missing[missing, missing])
    ),
    ("test_not_enough_columns2.csv", NamedTuple(),
        (2, 5),
        NamedTuple{(:A, :B, :C, :D, :E),Tuple{Int64,Int64,Int64,Union{Int64, Missing},Union{Int64, Missing}}},
        (A = [1, 6], B = [2, 7], C = [3, 8], D = [4, missing], E = [5, missing])
    ),
    ("test_correct_trailing_missings.csv", NamedTuple(),
        (2, 5),
        NamedTuple{(:A, :B, :C, :D, :E),Tuple{Int64,Int64,Int64,Missing,Missing}},
        (A = [1, 4], B = [2, 5], C = [3, 6], D = Missing[missing, missing], E = Missing[missing, missing])
    ),
    ("norwegian_data.csv", (delim=';', decimal=',', missingstring="NULL", dateformat="yyyy-mm-dd HH:MM:SS.s", pool=false),
        (1230, 83),
        NamedTuple{(:regine_area, :main_no, :point_no, :param_key, :version_no_end, :station_name, :station_status_name, :dt_start_date, :dt_end_date, :percent_missing_days, :first_year_regulation, :start_year, :end_year, :aktuell_avrenningskart, :excluded_years, :tilgang, :latitude, :longitude, :utm_east_z33, :utm_north_z33, :regulation_part_area, :regulation_part_reservoirs, :transfer_area_in, :transfer_area_out, :drainage_basin_key, :area_norway, :area_total, :comment, :drainage_dens, :dt_registration_date, :dt_regul_date, :gradient_1085, :gradient_basin, :gradient_river, :height_minimum, :height_hypso_10, :height_hypso_20, :height_hypso_30, :height_hypso_40, :height_hypso_50, :height_hypso_60, :height_hypso_70, :height_hypso_80, :height_hypso_90, :height_maximum, :length_km_basin, :length_km_river, :ocean_polar_angle, :ocean_polar_distance, :perc_agricul, :perc_bog, :perc_eff_bog, :perc_eff_lake, :perc_forest, :perc_glacier, :perc_lake, :perc_mountain, :perc_urban, :prec_intens_max, :utm_zone_gravi, :utm_east_gravi, :utm_north_gravi, :utm_zone_inlet, :utm_east_inlet, :utm_north_inlet, :br1_middelavrenning_1930_1960, :br2_Tilsigsberegning, :br3_Regional_flomfrekvensanalyse, :br5_Regional_lavvannsanalyse, :br6_Klimastudier, :br7_Klimascenarier, :br9_Flomvarsling, :br11_FRIEND, :br12_GRDC, :br23_HBV, :br24_middelavrenning_1961_1990, :br26_TotalAvlop, :br31_FlomserierPrim, :br32_FlomserierSekundar, :br33_Flomkart_aktive_ureg, :br34_Hydrologisk_referanseserier_klimastudier, :br38_Flomkart_aktive_ureg_periode, :br39_Flomkart_nedlagt_stasjon),Tuple{Int64,Int64,Int64,Int64,Int64,String,String,DateTime,Union{Missing, DateTime},Union{Missing, Float64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, String},Union{Missing, String},String,Float64,Float64,Int64,Int64,Union{Missing, Float64},Union{Missing, Float64},Union{Missing, Float64},Union{Missing, Float64},Union{Missing, Int64},Union{Missing, Float64},Union{Missing, Float64},Union{Missing, String},Missing,Union{Missing, DateTime},Union{Missing, DateTime},Union{Missing, Float64},Union{Missing, Float64},Union{Missing, Float64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Float64},Union{Missing, Float64},Union{Missing, Float64},Missing,Union{Missing, Float64},Union{Missing, Float64},Missing,Union{Missing, Float64},Union{Missing, Float64},Union{Missing, Float64},Union{Missing, Float64},Union{Missing, Float64},Union{Missing, Float64},Missing,Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, Int64},Union{Missing, String},Union{Missing, String},Union{Missing, String},Union{Missing, String},Union{Missing, String},Union{Missing, String},Union{Missing, String},Union{Missing, String},Missing,Union{Missing, String},Union{Missing, String},Union{Missing, String},Union{Missing, String},Union{Missing, String},Union{Missing, String},Union{Missing, String},Union{Missing, String},Union{Missing, String}}},
        nothing
    ),
    # #276
    ("test_duplicate_columnnames.csv", NamedTuple(),
        (2, 8),
        NamedTuple{(:a, :b, :c, :a_1, :a_2, :a_3, :a_4, :b_1), Tuple{Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64}},
        (a = [1, 9], b = [2, 10], c = [3, 11], a_1 = [4, 12], a_2 = [5, 13], a_3 = [6, 14], a_4 = [7, 15], b_1 = [8, 16])
    ),
    # #310
    ("test_bad_datetime.csv", NamedTuple(),
        (2, 3),
        NamedTuple{(:event,:time,:typ), Tuple{String, String, String}},
        (event = ["StartMovie", "Type"], time = ["2018-09-20T18:00:30.12345+00:00", "2018-09-20T18:02:13.67188+00:00"], typ = ["Event", "Event"])
    ),
    ("test_types.csv", (pool=false,),
        (1, 8),
        NamedTuple{(:int,:float,:date,:datetime,:bool,:string,:weakrefstring,:missing), Tuple{Int64,Float64,Date,DateTime,Bool,String,String,Missing}},
        (int = [1], float = [1.0], date = [Date("2018-01-01")], datetime = [DateTime("2018-01-01T00:00:00")], bool = [true], string = ["hey"], weakrefstring = ["there"], missing = [missing])
    ),
    # #326
    ("test_issue_326.wsv", (delim=" ", ignorerepeated=true),
        (2, 2),
        NamedTuple{(:A, :B),Tuple{Int64,Int64}},
        (A = [1, 11], B = [2, 22])
    ),
    ("test_missing_last_field.csv", NamedTuple(),
        (2, 3),
        NamedTuple{(:col1, :col2, :col3),Tuple{Float64,Float64,Union{Float64, Missing}}},
        (col1 = [1.0, 4.0], col2 = [2.0, 5.0], col3 = [3.0, missing])
    ),
    # #340
    ("test_delim.tsv", NamedTuple(),
        (3, 3),
        NamedTuple{(:col1, :col2, :col3),Tuple{Int64,Int64,Int64}},
        (col1 = [1, 4, 7], col2 = [2, 5, 8], col3 = [3, 6, 9])
    ),
    ("test_delim.wsv", NamedTuple(),
        (3, 3),
        NamedTuple{(:col1, :col2, :col3),Tuple{Int64,Int64,Int64}},
        (col1 = [1, 4, 7], col2 = [2, 5, 8], col3 = [3, 6, 9])
    ),
    # #351
    ("test_comment_first_row.csv", (comment="#",),
        (2, 3),
        NamedTuple{(:a, :b, :c), Tuple{Int64, Int64, Int64}},
        (a=[1,7], b=[2,8], c=[3,9])
    ),
    ("test_comment_first_row.csv", (comment="#", header=2),
        (2, 3),
        NamedTuple{(:a, :b, :c), Tuple{Int64, Int64, Int64}},
        (a=[1,7], b=[2,8], c=[3,9])
    ),
    # #371
    ("test_repeated_delim_371.csv", (ignorerepeated=true, delim=' ',),
        (15, 4),
        NamedTuple{(:FAMILY, :PERSON, :MARKER, :RATIO), Tuple{String, String, String, Float64}},
        (FAMILY = ["A", "A", "A", "A", "A", "A", "EPGP013951", "EPGP014065", "EPGP014065", "EPGP014065", "EP07", "83346_EPGP014244", "83346_EPGP014244", "83506", "87001"], PERSON = ["EP01223", "EP01227", "EP01228", "EP01228", "EP01227", "EP01228", "EPGP013952", "EPGP014066", "EPGP014065", "EPGP014068", "706", "T3011", "T3231", "T17255", "301"], MARKER = ["rs710865", "rs11249215", "rs11249215", "rs10903129", "rs621559", "rs1514175", "rs773564", "rs2794520", "rs296547", "rs296547", "rs10927875", "rs2251760", "rs2251760", "rs2475335", "rs2413583"], RATIO = [0.0214, 0.0107, 0.00253, 0.0116, 0.00842, 0.0202, 0.00955, 0.0193, 0.0135, 0.0239, 0.0157, 0.0154, 0.0154, 0.00784, 0.0112])
    ),
    # #154
    ("test_file_issue_154.csv", (normalizenames=true,),
        (2, 4),
        NamedTuple{(:a, :b, :_, :Column4), Tuple{Int64, Int64, String, Union{Missing, String}}},
        (a = [0, 12], b = [1, 5], _ = [" ", " "], Column4 = Union{Missing, String}[" comment ", missing])
    ),
    (IOBuffer("""A,B,C\n1,1,10\n6,1"""), NamedTuple(),
        (2, 3),
        NamedTuple{(:A, :B, :C), Tuple{Int64, Int64, Union{Int64, Missing}}},
        (A = [1, 6], B = [1, 1], C = [10, missing])
    ),
    (IOBuffer("""A;B;C\n1,1,10\n2,0,16"""), (normalizenames=true,),
        (2, 3),
        NamedTuple{(:A, :B, :C), Tuple{String, Missing, Missing}},
        (A = ["1,1,10", "2,0,16"], B = [missing, missing], C = [missing, missing])
    ),
    (IOBuffer("""A;B;C\n1,1,10\n2,0,16"""), (delim=';',),
        (2, 3),
        NamedTuple{(:A, :B, :C), Tuple{String, Missing, Missing}},
        (A = ["1,1,10", "2,0,16"], B = [missing, missing], C = [missing, missing])
    ),
    (IOBuffer("""a b c d e\n1 2  3 4 5\n1 2 3  4 5\n1  2 3  4 5"""), (delim=' ',),
        (3, 5),
        NamedTuple{(:a, :b, :c, :d, :e), Tuple{Int64, Union{Int64, Missing}, Union{Int64, Missing}, Union{Int64, Missing}, Union{Int64, Missing}}},
        (a = [1, 1, 1], b = [2, 2, missing], c = [missing, 3, 2], d = [3, missing, 3], e = [4, 4, missing])
    ),
    # 323
    (IOBuffer("a0001000\na0001000"), (datarow=1, pool=true),
        (2, 1),
        NamedTuple{(:Column1,), Tuple{String}},
        (Column1 = ["a0001000", "a0001000"],)
    ),
    # 396
    ("heat_flux.dat", (delim=' ', ignorerepeated=true, datarow=2, header=[:t, :heat_flux]),
        (16001, 2),
        NamedTuple{(:t, :heat_flux), Tuple{Float64, Float64}},
        nothing
    ),
    # #422
    ("log001_vehicle_status_flags_0.txt", NamedTuple(),
        (281, 31),
        NamedTuple{(:timestamp, :condition_calibration_enabled, :condition_system_sensors_initialized, :condition_system_hotplug_timeout, :condition_system_returned_to_home, :condition_auto_mission_available, :condition_global_position_valid, :condition_home_position_valid, :condition_local_position_valid, :condition_local_velocity_valid, :condition_local_altitude_valid, :condition_power_input_valid, :condition_battery_healthy, :circuit_breaker_engaged_power_check, :circuit_breaker_engaged_airspd_check, :circuit_breaker_engaged_enginefailure_check, :circuit_breaker_engaged_gpsfailure_check, :circuit_breaker_flight_termination_disabled, :circuit_breaker_engaged_usb_check, :circuit_breaker_engaged_posfailure_check, :offboard_control_signal_found_once, :offboard_control_signal_lost, :offboard_control_set_by_command, :offboard_control_loss_timeout, :rc_signal_found_once, :rc_input_blocked, :rc_calibration_valid, :vtol_transition_failure, :usb_connected, :avoidance_system_required, :avoidance_system_valid), Tuple{Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64}},
        nothing
    ),
    # tape re-allocation
    ("fecal_samples.csv", (debug=true, normalizenames=true),
        (1079, 39),
        NamedTuple{(:SampleID, :Mother_Child, :SubjectID, :MaternalID, :TimePoint, :Fecal_EtOH, :CollectionRep, :DOC, :RAInitials_DOC, :DOF, :RAInitials_DOF, :Date_Brought_In, :RAInitials_Brought, :Date_Shipped, :RAInitials_Shipped, :Date_Aliquoted, :Number_Replicates, :RAInitials_Aliquot, :StorageBox, :DOE, :Extract_number, :AliquotRep, :DNABox, :KitUsed, :RAInitials_Extract, :DNAConc, :DOM, :Mgx_processed, :Mgx_batch, :DO16S, :_16S_processed, :_16S_batch, :_16S_plate, :Notes, :Discrepancies, :Batch_1_Mapping, :Mgx_batch_Mapping, :_16S_batch_Mapping, :Mother_Child_Dyads), Tuple{String, String, Int64, String, Int64, String, Int64, Dates.Date, Union{Missing, String}, Union{Missing, Date}, Union{Missing, String}, Union{Missing, Date}, Union{Missing, String}, Union{Missing, Date}, Union{Missing, String}, Union{Missing, Date}, Union{Missing, String}, Union{Missing, String}, Union{Missing, String}, Union{Missing, Date}, Union{Missing, String}, Union{Missing, String}, Union{Missing, String}, Union{Missing, String}, Union{Missing, String}, Union{Missing, Float64}, Union{Missing, Date}, Union{Missing, String}, Union{Missing, String}, Union{Missing, Date}, Union{Missing, String}, Union{Missing, String}, Union{Missing, String}, Union{Missing, String}, Union{Missing, String}, Union{Missing, String}, Union{Missing, String}, Union{Missing, String}, Union{Missing, Int64}}},
        nothing
    ),
    # 459, support parsing Time
    ("time.csv", (dateformat="H:M:S",),
        (2, 2),
        NamedTuple{(:time, :value), Tuple{Time, Int64}},
        (time = [Time(0), Time(0, 10)], value = [1, 2])
    ),
    # https://github.com/JuliaData/DataFrames.jl/issues/1880
    ("escaped_pooled.csv", (header=[:a, :b, :c], types=Dict(1=>CSV.PooledString)),
        (2, 3),
        NamedTuple{(:a, :b, :c), Tuple{String, String, Float64}},
        (a = ["\\孕晚期下午和晚上血压高\"", "\\孕晚期下午和晚上血压高\""], b = ["为什么中老年人血压不高也要定期测量血压", "晚上睡眠不好会导致血压升高吗"], c = [0.744359, 0.714016])
    ),
    # https://github.com/JuliaData/CSV.jl/issues/478
    ("error_comment.txt", (comment="#",),
        (8, 4),
        NamedTuple{(:fluid, :col2, :col3, :acentric_factor), Tuple{String, Float64, Float64, Float64}},
        (fluid = ["Ar", "C2H4", "CO2", "CO", "CH4", "H2", "Kr", "Xe"], col2 = [150.86, 282.34, 304.12, 132.85, 190.56, 32.98, 209.4, 289.74], col3 = [48.98, 50.41, 73.74, 34.94, 45.99, 12.93, 55.0, 58.4], acentric_factor = [-0.002, 0.087, 0.225, 0.045, 0.011, -0.217, 0.005, 0.008])
    ),
    # https://github.com/JuliaData/CSV.jl/issues/508
    ("test_508.csv", (comment="#", header=[:eats_steak, :how_cooked]),
        (6, 2),
        NamedTuple{(:eats_steak, :how_cooked), Tuple{String, Union{String, Missing}}},
        (eats_steak=["Yes", "Yes", "Yes", "Yes", "No", "Yes"], how_cooked=["Medium rare", "Medium", "Medium", "Medium rare", missing, "Rare"])
    ),
    # https://github.com/JuliaData/CSV.jl/issues/555
    ("bug555.txt", (header=true,ignorerepeated=true,delim=' '),
        (3, 9),
        NamedTuple{(:RESULTAT, :NOM_CHAM, :INST, :NUME_ORDRE, :NOEUD, :COOR_X, :COOR_Y, :COOR_Z, :TEMP), Tuple{String, String, Float64, Int64, String, Float64, Float64, Float64, Float64}},
        (RESULTAT = ["A0", "B0", "C0"], NOM_CHAM = ["A1", "B1", "C1"], INST = [0.0, 0.0, 0.0], NUME_ORDRE = [0, 0, 0], NOEUD = ["N1", "N2", "N3"], COOR_X = [0.0, 2.3, 2.5], COOR_Y = [2.27374e-15, 0.0, 0.0], COOR_Z = [0.0, 0.0, 0.0], TEMP = [0.0931399, 0.311013, 0.424537])
    ),
    # https://github.com/JuliaData/CSV.jl/issues/577
    ("csv_segfault.txt", (delim="\t", ignoreemptylines=true),
        (468, 9),
        NamedTuple{(Symbol("Time (CEST)"), :Latitude, :Longitude, :Course, :kts, :mph, :feet, :Rate, Symbol("Reporting Facility")),Tuple{String,Union{Missing, String},Union{Missing, String},Union{Missing, String},Union{Missing, String},Union{Missing, String},Union{Missing, String},Union{Missing, String},Union{Missing, String}}},
        nothing
    ),
    # https://github.com/JuliaData/CSV.jl/issues/575
    ("types_override.csv", (type=Int, types=Dict(:col1 => String)),
        (3, 5),
        NamedTuple{(:col1,:col2,:col3,:col4,:col5), Tuple{String, Int64, Int64, Int64, Int64}},
        (col1 = ["A", "B", "C"], col2 = [1, 5, 9], col3 = [2, 6, 10], col4 = [3, 7, 11], col5 = [4, 8, 12])
    ),
    # https://github.com/JuliaData/CSV.jl/issues/592
    ("select.csv", (select = [:state, :dateChecked, :positive, :negative, :pending, :hospitalized, :death],),
        (1485, 7),
        NamedTuple{(:state, :positive, :negative, :pending, :hospitalized, :death, :dateChecked), Tuple{String, Union{Missing, Int64}, Union{Missing, Int64}, Union{Missing, Int64}, Union{Missing, Int64}, Union{Missing, Int64}, String}},
        nothing
    )
];

for test in testfiles
    testfile(test...)
end
# Test file with FilePaths
testfile("test_basic.csv", (types=Dict(2=>Float64),),
    (3, 3),
    NamedTuple{(:col1, :col2, :col3),Tuple{Int64,Float64,Int64}},
    (col1 = [1, 4, 7], col2 = [2.0, 5.0, 8.0], col3 = [3, 6, 9]);
    dir=Path(dir)
)


text:
# To be able to test gpu memory usage
using Knet

include("../bilstm.jl")
include("../infst.jl")
#atype = Array{Float64}
const atype = (gpu() >= 0 ? KnetArray{Float32} : Array{Float32})
#const datafile = "/Users/okirnap/bilstm-in-Knet8/data/ukwac/ukwac.txt"
#const vocabfile = "/Users/okirnap/bilstm-in-Knet8/data/ukwac/ukwac_vocab_100k"
#global stream_f = open(datafile)

function randseq(V,B,T)
    s = Vector{Vector{Int}}()
    #slen = rand(50:T)
    slen = T
    for t in 1:slen
        push!(s, rand(2:V,B))
    end
    return s
end

function test_load()
    batchsize = 25;slen = 30;vocabsize = 20004;hiddens = [300];embedding = 256;
    data = randseq(vocabsize, batchsize, slen)
    m = initmodel(atype, hiddens, embedding, vocabsize)
    s = initstate(atype, hiddens, batchsize)
    opts = oparams(m, Adam; gclip=5.0)
    #gradcheck(bilstm, m, s, data; gcheck=15, verbose=true, atol=0.01)
    if !isinteractive()
        for i=1:5
            #@time gloss = bilstmgrad(m, s, data)
            #bilstm(m, s, data)
            @time train(m, s, data, opts)
        end
    end
    return (m, s, data)
end
!isinteractive() && test_load()

# function main()
#     # regular steps for creating train data
#     vocabulary = create_vocab(vocabfile)
#     sdict = Dict{Int64, Array{Any, 1}}();
#     res = nextbatch(stream_f, sdict, vocabulary, 20)
#     global index_to_word = Array(AbstractString, length(vocabulary))
#     for (k, v) in vocabulary; index_to_word[v] = k;end;
#     return res
# end

# Here are some notes on gpu usage:
# Configuration sequence length : vocabsize : batchsize
# 25 : 100001 : 20 -> OutOfMemory
# 50 :  50001 : 20 -> OutOfMemory
#

max_stars_repo_name: kirnap/wordsubs

max_issues_repo_name: kirnap/wordsubs

max_forks_repo_name: kirnap/wordsubs