text:
const Optional{T} = Union{Some{T},Nothing}
@nospecialize
abstract type RowT end
abstract type HMT end

ImDict = Base.ImmutableDict

abstract type TVar end
@data TVar begin
    Refvar(i::UInt)
    Genvar(g::UInt, n::Symbol)
end

function Base.show(io::IO, x::TVar)
    @match x begin
        Genvar(g, n) => print(io, "'$n($g)")
        Refvar(i) => print(io, '\'', i)
    end
end

@data RowT begin
    RowMono
    RowCons(Symbol, HMT, RowT)
    RowPoly(HMT)
end

# Write your package code here.
@data HMT begin
    Var(var::TVar)
    Nom(n::Symbol)
    Fresh(Symbol)
    App(f::HMT, arg::HMT)
    Arrow(from::HMT, to::HMT)
    Tup{N}::(NTuple{N,HMT}) => HMT
    Forall{N}::(NTuple{N,Symbol}, HMT) => HMT
    Record(RowT)
end

Base.show(io::IO, rowt::RowT) =
    @switch rowt begin
    @case RowMono
        return
    @case RowCons(k, t, r)
        print(io, k, "::")
        Base.show(io, t)
        print(io, " {")
        Base.show(io, r)
        print(io, '}')
        return
    @case RowPoly(t)
        print(io, '|')
        Base.show(io, t)
        return
    end

need_parens(hmt::HMT) =
    @match hmt begin
        ::App || ::Arrow || ::Forall => true
        _ => false
    end

with_parens(f::Function, io::IO, need_parens::Bool) =
    if need_parens
        print(io, '(')
        f()
        print(io, ')')
    else
        f()
    end

Base.show(io::IO, hmt::HMT) =
    @switch hmt begin
    @case Var(v)
        print(io, v)
        return
    @case Nom(n)
        print(io, n)
        return

    @case Fresh(n)
        print(io, n)
        return

    @case App(f, a)
        Base.show(io, f)
        print(io, " ")
        with_parens(io, need_parens(a)) do
            Base.show(io, a)
        end
        return
    @case Arrow(a, r)
        with_parens(io, need_parens(a)) do
            Base.show(io, a)
        end
        print(io, "->")
        Base.show(io, r)
        return
    @case Tup(xs)
        print(io, "{")
        print(io, join(repr.(xs), ", "))
        print(io, "}")
        return
    @case Forall(ns, t)
        print(io, "forall ")
        print(io, join(string.(ns), " "), ".")
        Base.show(io, t)
        return
    @case Record(rec)
       m, ex = extract_row(rec)
       print(io, '{')
       print(io, join(String["$k::$(repr(v))" for (k, v) in m], ", "))
       @when Some(ex) = ex begin
         Base.show(io, RowPoly(ex))
       end
       print(io, '}')
       return
    end

TypeScope = ImDict{Symbol,HMT}

function mk_type_scope(xs::AbstractVector{Pair{Symbol, T}}) where {T <: HMT}
    ret = TypeScope()
    for x in xs
        ret = ImDict(ret, Pair{Symbol, HMT}(x.first, x.second))
    end
    ret
end

function previsit(f::Function, ctx′, root)
    function visit_t(ctx′, root)
        ctx, root = f(ctx′, root)
        eval_t(node::HMT)::HMT = visit_t(ctx, node)
        eval_row(root::RowT)::RowT =
            @match root begin
            RowMono => RowMono
            RowPoly(t) => RowPoly(eval_t(t))
            RowCons(k, t, row) =>
                    RowCons(k, eval_t(t), eval_row(row))

        end
        @match root begin
            Var(_) || Nom(_) || Fresh(_) => root
            App(a, b) => App(eval_t(a), eval_t(b))
            Arrow(a, b) => Arrow(eval_t(a), eval_t(b))
            Tup(xs) => Tup(map(eval_t, xs))
            Forall(ns, t) => Forall(ns, eval_t(t))
            Record(rowt) =>
                @match eval_row(rowt) begin
                    RowPoly(t) => t
                    a => Record(a)
                end
        end
    end
    visit_t(ctx′, root)
end

function row_of_pairs(pairs, row)
    for (k, v) in pairs
        row = RowCons(k, v, row)
    end
    row
end

function visit_check(pred::Function, t::HMT)
    function eval_t(root)
        pred(root) && begin
            eval_row(root::RowT)::Bool =
                @match root begin
                RowMono => true
                RowPoly(t) => eval_t(t)
                RowCons(k, t, row) =>
                        eval_t(t) && eval_row(row)
            end
            @match root begin
                Var(_) || Nom(_) || Fresh(_) => true
                App(a, b) || Arrow(a, b) => eval_t(a) && eval_t(b)
                Tup(xs) => all(eval_t, xs)
                Forall(ns, t) => eval_t(t)
                Record(rowt) => eval_row(rowt)
            end
        end
    end
    eval_t(t)
end

struct IllFormedType <: Exception
    msg::String
end

struct UnboundTypeVar <: Exception
    scopedvar::Symbol
end

struct RowFieldMismatch <: Exception
    field::Symbol
end

struct RowFieldDuplicate <: Exception
    field::Symbol
end

function ftv(h::HMT)
    typevars = Set{UInt}()
    previsit(nothing, h) do ::Nothing, root::HMT
        @switch root begin
        @case Var(Refvar(i))
            push!(typevars, i)
            return nothing, root
        @case _
            return nothing, root
        end
    end
    typevars
end

function unbound(root::HMT)
    collected = Set{Symbol}()
    visitor(shadow::Set{Symbol}, root::HMT) =
        @match root begin
            Fresh(s) =>
                if s in shadow
                    shadow, root
                else
                    push!(collected, s)
                    shadow, root
                end
            Forall(ns, p) =>
                let shadow = union(shadow, Tuple(ns))
                    shadow, root
                end
            _ => (shadow, root)
        end
    previsit(visitor, Set{Symbol}(), root)
    collected
end


text:
module CollabUtils2SilverBerry

using ..Ahorn, Maple

@mapdef Entity "CollabUtils2/SilverBerry" SilverBerry(x::Integer, y::Integer)

const placements = Ahorn.PlacementDict(
    "Silver Berry (Collab Utils 2 / READ DOCS)" => Ahorn.EntityPlacement(
        SilverBerry
    )
)

const sprite = "CollabUtils2/silverBerry/idle00.png"

function Ahorn.selection(entity::SilverBerry)
    x, y = Ahorn.position(entity)
    return Ahorn.getSpriteRectangle(sprite, x, y)
end

Ahorn.render(ctx::Ahorn.Cairo.CairoContext, entity::SilverBerry, room::Maple.Room) = Ahorn.drawSprite(ctx, sprite, 0, 0)

end

ext: jl


text:
fun bad() {
    var a = "first";
    var a = "second"; // <-- boom!
    // Expect: "Variable with this name already declared in this scope."
}
bad();


text:
import DelayEmbeddings: reconstruct

#####################################################################################
#                                   Reconstruction                                  #
#####################################################################################
"""
	reconstruct(s::AbstractArray{<:AbstractArray{T,Φ}}, em)
Reconstruct the spatial timeseries `s` represented by a `Vector` of `AbstractArray`
states using the embedding struct `em` of type [`AbstractSpatialEmbedding`](@ref).

Returns the reconstruction in the form of a `Dataset` (from `DelayEmbeddings`) where each
row is a reconstructed state and they are ordered first through linear
indexing into each state and then incrementing in time.
"""
function reconstruct(s::AbstractArray{<:AbstractArray{T,Φ}},
	em::AbstractSpatialEmbedding{Φ,BC,X}
	) where {T<:Number,Φ,BC,X}
	timesteps = (length(s) - get_τmax(em))
	num_pt    = get_num_pt(em)
	L         = timesteps*num_pt

	pt_in_space = CartesianIndices(s[1])
	lin_idxs    = LinearIndices(s[1])
	data = Vector{SVector{X,T}}(undef,L)
	recv = zeros(T,X)
	@inbounds for t in 1:timesteps, α in pt_in_space
		n = (t-1)*num_pt+lin_idxs[α]
		em(recv,s,t,α)
		data[n] = recv
	end
	return Dataset(data)
end


text:
# Only used by bigfish if option use_generated_assets is set to true

include("game.jl")
include("resources.jl")

mutable struct ColorGen
    rand_gen::RandGen
    rgb_start::Vector{Float32}
    rgb_len::Vector{Float32}
    rgb_choice::Vector{Int}
    p_rect::Float32

    function ColorGen(rg::RandGen)

        rand_gen = rg
        rgb_start = []
        resize!(rgb_start, 3)
        rgb_len = []
        resize!(rgb_len, 3)
        rgb_choice = []
        resize!(rgb_choice, 3)
        p_rect = 0.0

        new(
            rand_gen,
            rgb_start,
            rgb_len,
            rgb_choice,
            p_rect,
        )
    end
end

function roll(cgen::ColorGen)

    for i in 1:3
        cgen.rgb_len[i] = rand01(cgen.rand_gen)
    end

    for i in 1:3
        cgen.rgb_start[i] = rand01(cgen.rand_gen) * (1 - cgen.rgb_len[i])
    end

    cgen.p_rect = rand01(cgen.rand_gen)
    return nothing
end

function rand_color(cgen::ColorGen)

    for i in 1:3
        cgen.rgb_choice[i] = trunc(Int, 255 * (rand01(cgen.rand_gen) * cgen.rgb_len[i] + cgen.rgb_start[i]))
    end

    return cgen.rgb_choice
end

mutable struct AssetGen
    rand_gen::RandGen

    function AssetGen(rg::RandGen)

        rand_gen = rg

        new(
            rand_gen,
        )
    end
end

function choose_sub_rect(asset_gen::AssetGen, rectangle, min_dim::Float32, max_dim::Float32)

    w = trunc(Int, rectangle[3].x - rectangle[2].x)
    h = trunc(Int, rectangle[1].y - rectangle[2].y)

    smaller = (w > h) ? h : w

    del_dim = max_dim - min_dim

    rdx = (rand01(asset_gen.rand_gen) * del_dim + min_dim) * smaller
    rdy = (rand01(asset_gen.rand_gen) * del_dim + min_dim) * smaller
    rx_off = rand01(asset_gen.rand_gen) * (w - rdx)
    ry_off = rand01(asset_gen.rand_gen) * (h - rdy)

    dst3 = rect(Point(rx_off + rectangle[2].x, ry_off + rectangle[2].y), rdx, rdy, vertices = true)

    return dst3
end

function split_rect(asset_gen::AssetGen, rectangle, num_splits::Int, is_horizontal::Bool)

    split_rects::Vector{Any} = []

    x = rectangle[2].x
    y = rectangle[2].y
    w = rectangle[3].x - x
    h = rectangle[1].y - y

    dw = w / num_splits
    dh = h / num_splits

    for i in 0:(num_splits - 1)
        if is_horizontal
            push!(split_rects, rect(Point(x + i * dw, y), dw, h, vertices = true))
        else
            push!(split_rects, rect(Point(x, y + i * dh), w, dh, vertices = true))
        end
    end

    return split_rects
end

function paint_shape(asset_gen::AssetGen, main_rectangle, cgen::ColorGen)

    k = randn(asset_gen.rand_gen, 10)
    num_splits = div((k * k), 50) + 1
    split_rects = split_rect(asset_gen, main_rectangle, num_splits, randbool(asset_gen.rand_gen))

    use_rect = randbool(asset_gen.rand_gen)
    regen_colors = randbool(asset_gen.rand_gen)

    c1 = rand_color(cgen)
    c2 = rand_color(cgen)

    for rectangle in split_rects
        if regen_colors
            c1 = rand_color(cgen)
            c2 = rand_color(cgen)
        end

        if use_rect
            setcolor(c1[1] / 255, c1[2] / 255, c1[3] / 255)
            rectangle_large = ENLARGEMENT * rectangle
            x = rectangle_large[2].x
            y = rectangle_large[2].y
            w = rectangle_large[3].x - x
            h = rectangle_large[1].y - y
            rect(Point(x, y), w, h, :fill)
        else
            # Missing Code
        end
    end
    return nothing
end

function paint_rect_resource(asset_gen::AssetGen, rectangle, num_recurse::Int, blotch_scale::Int)

    cgen = ColorGen(asset_gen.rand_gen)
    cgen.roll(cgen)

    # Missing Code

    return nothing
end

function create_bar(asset_gen::AssetGen, rectangle, is_horizontal::Bool)

    k1 = (Float32(0.45) + rand01(asset_gen.rand_gen) * Float32(0.4))
    k2 = (Float32(0.45) + rand01(asset_gen.rand_gen) * Float32(0.4))
    left_top = rectangle[2]
    width = rectangle[3].x - left_top.x
    height = rectangle[1].y - left_top.y
    w = width * k1 * k1
    h = height * k2 * k2
    pct = rand01(asset_gen.rand_gen)

    if !is_horizontal
        crect = rect(Point(0, (height - h) * pct), width, h, vertices = true)
    else
        crect = rect(Point((height - w) * pct, 0), w, height, vertices = true)
    end

    return crect
end

function paint_shape_resource(asset_gen::AssetGen, rectangle)

    cgen = ColorGen(asset_gen.rand_gen)
    roll(cgen)

    horizontal_first = randbool(asset_gen.rand_gen)
    nbar1 = div(randn(asset_gen.rand_gen, 3), 2) + 1
    nbar2 = div(randn(asset_gen.rand_gen, 3), 2) + 1

    setcolor(0, 0, 0, 0)
    rectangle_large = ENLARGEMENT * rectangle
    w = rectangle_large[3].x - rectangle_large[2].x
    h = rectangle_large[1].y - rectangle_large[2].y
    rect(rectangle_large[2], w, h, :fill)

    for i in 0:(nbar1 - 1)
        c1 = create_bar(asset_gen, rectangle, horizontal_first)
        paint_shape(asset_gen, c1, cgen)
    end

    for i in 0:(nbar2 - 1)
        c2 = create_bar(asset_gen, rectangle, !horizontal_first)
        paint_shape(asset_gen, c2, cgen)
    end

    num_blotches = randint(asset_gen.rand_gen, 1, 5)

    for j in 0:(num_blotches - 1)
        dst = choose_sub_rect(asset_gen, rectangle, Float32(0.1), Float32(0.6))
        paint_shape(asset_gen, dst, cgen)
    end
    return nothing
end

function generate_resource(asset_gen::AssetGen, img::Image, num_recurse::Int = 1, blotch_scale::Int = 50, is_rect::Bool = true)

    rectangle = rect(Point(0, 0), img.width, img.height, vertices = true)

    if is_rect
        paint_rect_resource(asset_gen, rectangle, num_recurse, blotch_scale)
    else
        paint_shape_resource(asset_gen, rectangle)
    end
    return nothing
end


text:
"""
    ResNetHP

Hyperparameters for the convolutional resnet architecture.

| Parameter                 | Type                | Default   |
|:--------------------------|:--------------------|:----------|
| `num_blocks`              | `Int`               |  -        |
| `num_filters`             | `Int`               |  -        |
| `conv_kernel_size`        | `Tuple{Int, Int}`   |  -        |
| `num_policy_head_filters` | `Int`               | `2`       |
| `num_value_head_filters`  | `Int`               | `1`       |
| `batch_norm_momentum`     | `Float32`           | `0.6f0`   |

The trunk of the two-head network consists of `num_blocks` consecutive blocks.
Each block features two convolutional layers with `num_filters` filters and
with kernel size `conv_kernel_size`. Note that both kernel dimensions must be
odd.

During training, the network is evaluated in training mode on the whole
dataset to compute the loss before it is switched to test model, using
big batches. Therefore, it makes sense to use a high batch norm momentum
(put a lot of weight on the latest measurement).

# AlphaGo Zero Parameters

The network in the original paper from Deepmind features 20 blocks with 256
filters per convolutional layer.
"""
@kwdef struct ResNetHP
  num_blocks :: Int
  num_filters :: Int
  conv_kernel_size :: Tuple{Int, Int}
  num_policy_head_filters :: Int = 2
  num_value_head_filters :: Int = 1
  batch_norm_momentum :: Float32 = 0.6f0
end

Util.generate_update_constructor(ResNetHP) |> eval

"""
    ResNet{Game} <: TwoHeadNetwork{Game}

The convolutional residual network architecture that is used
in the original AlphaGo Zero paper.
"""
mutable struct ResNet{Game} <: TwoHeadNetwork{Game}
  hyper
  common
  vhead
  phead
end

function ResNetBlock(size, n, bnmom)
  pad = size .÷ 2
  layers = Chain(
    Conv(size, n=>n, pad=pad),
    BatchNorm(n, relu, momentum=bnmom),
    Conv(size, n=>n, pad=pad),
    BatchNorm(n, momentum=bnmom))
  return Chain(
    SkipConnection(layers, +),
    x -> relu.(x))
end

function ResNet{G}(hyper::ResNetHP) where G
  bsize = GameInterface.state_dim(G)
  outdim = GameInterface.num_actions(G)
  ksize = hyper.conv_kernel_size
  @assert all(ksize .% 2 .== 1)
  pad = ksize .÷ 2
  nf = hyper.num_filters
  npf = hyper.num_policy_head_filters
  nvf = hyper.num_value_head_filters
  bnmom = hyper.batch_norm_momentum
  common = Chain(
    Conv(ksize, bsize[3]=>nf, pad=pad),
    BatchNorm(nf, relu, momentum=bnmom),
    [ResNetBlock(ksize, nf, bnmom) for i in 1:hyper.num_blocks]...)
  phead = Chain(
    Conv((1, 1), nf=>npf),
    BatchNorm(npf, relu, momentum=bnmom),
    flatten,
    Dense(bsize[1] * bsize[2] * npf, outdim),
    softmax)
  vhead = Chain(
    Conv((1, 1), nf=>nvf),
    BatchNorm(nvf, relu, momentum=bnmom),
    flatten,
    Dense(bsize[1] * bsize[2] * nvf, nf, relu),
    Dense(nf, 1))
  ResNet{G}(hyper, common, vhead, phead)
end

Network.HyperParams(::Type{<:ResNet}) = ResNetHP

max_stars_repo_name: btheodorou/Bridge-NN-Research

max_issues_repo_name: btheodorou/Bridge-NN-Research

max_forks_repo_name: btheodorou/Bridge-NN-Research


text:
# Note that this script can accept some limited command-line arguments, run
# `julia build_tarballs.jl --help` to see a usage message.
using BinaryBuilder

name = "Gnuastro"
version = v"0.11"

# Collection of sources required to build gnuastro
sources = [
    ArchiveSource("http://ftp.gnu.org/gnu/gnuastro/gnuastro-$(version.major).$(version.minor).tar.gz",
                  "f51a5fe6c2ac7218442aa87be883dbd98d130b48d5e2dff3abb2730113c76c2f"),
    DirectorySource("./bundled"),
]

# Bash recipe for building across all platforms
script = raw"""
cd $WORKSPACE/srcdir/gnuastro-*/

if [[ "${target}" == i686-linux-musl ]]; then
    # Small hack: swear that we're cross-compiling.  Our `i686-linux-musl` is
    # bugged and it can run only a few programs, with the result that the
    # configure test to check whether we're cross-compiling returns that we're
    # doing a native build, but then it fails to run a bunch of programs during
    # other tests.
    sed -i 's/cross_compiling=no/cross_compiling=yes/' configure
fi

if [[ "${target}" == *-mingw* ]]; then
    # Windows, here we go.  First off, need to patch configure to link
    # libcfitsio in the right order: first libcfitsio, then its dependencies.
    atomic_patch -p1 "${WORKSPACE}/srcdir/patches/configure_libcfitsio_libs.patch"

    # Second, WCSLIB defines a function called `wcsset`, just like a Windows
    # function defined in <string.h>.  The following patch guards all inclusions
    # of <string.h>
    atomic_patch -p1 "${WORKSPACE}/srcdir/patches/wcsset.patch"

    # Also, CFITSIO aptly defines a macro called `TBYTE`, which is the same
    # name as a MinGW macro, so we are going to rename it here as we did for
    # CFITSIO.
    export CFLAGS="-DTBYTE=_TBYTE"
fi

export CPPFLAGS="-I${prefix}/include"
./configure --prefix=${prefix} --build=${MACHTYPE} --host=${target}
make -j${nproc}
make install
"""

# These are the platforms we will build for by default, unless further
# platforms are passed in on the command line.  We are manually disabling
# many platforms that do not seem to work.
platforms = filter!(!Sys.iswindows, supported_platforms())

# The products that we will ensure are always built
products = [
    LibraryProduct("libgnuastro", :libgnuastro),
    ExecutableProduct("astarithmetic", :astarithmetic),
    ExecutableProduct("astconvertt", :astconvertt),
    ExecutableProduct("astconvolve", :astconvolve),
    ExecutableProduct("astcosmiccal", :astcosmiccal),
    ExecutableProduct("astcrop", :astcrop),
    ExecutableProduct("astfits", :astfits),
    ExecutableProduct("astmatch", :astmatch),
    ExecutableProduct("astmkcatalog", :astmkcatalog),
    ExecutableProduct("astmknoise", :astmknoise),
    ExecutableProduct("astmkprof", :astmkprof),
    ExecutableProduct("astnoisechisel", :astnoisechisel),
    ExecutableProduct("astscript-sort-by-night", :astscript_sort_by_night),
    ExecutableProduct("astsegment", :astsegment),
    ExecutableProduct("aststatistics", :aststatistics),
    ExecutableProduct("asttable", :asttable),
    ExecutableProduct("astwarp", :astwarp),
]

# Dependencies that must be installed before this package can be built
dependencies = [
    Dependency("CFITSIO_jll"),
    Dependency("GSL_jll"),
    Dependency("JpegTurbo_jll"),
    Dependency("Libtiff_jll"),
    Dependency("LibGit2_jll"),
    Dependency("WCS_jll"),
]

# Build the tarballs, and possibly a `build.jl` as well.
build_tarballs(ARGS, name, version, sources, script, platforms, products, dependencies)

max_stars_repo_name: mortenpi/Yggdrasil

max_issues_repo_name: mortenpi/Yggdrasil

max_forks_repo_name: mortenpi/Yggdrasil


text:
include(joinpath(dirname(@__DIR__), "src", "SpelledOut.jl"))
using Documenter, .SpelledOut

Documenter.makedocs(
    clean = true,
    doctest = true,
    modules = Module[SpelledOut],
    repo = "",
    highlightsig = true,
    sitename = "SpelledOut Documentation",
    expandfirst = [],
    pages = [
        "Home" => "index.md",
        "Supported Languages" => "supported_languages.md",
        "Usage" => "usage.md"
    ]
)

deploydocs(;
    repo  =  "github.com/jakewilliami/SpelledOut.jl.git",
)


text:
include("common.jl")

function f(x, y)
    0.0001*(10/(1+x^2) + x * y + 10*y^2)
end

Δt = 0.01
mmesh = Mesh(30, 30, 1/30)
bdnode = bcnode(mmesh)
bdnode = [bdnode; bdnode .+ mmesh.ndof]

nu = constant(eval_f_on_gauss_pts(f, mmesh))

nodes = fem_nodes(mmesh)
u = @. sin(2π * nodes[:,1])
v = @. sin(2π * nodes[:,2])
u0 = [u;v]
u0[bdnode] .= 0.0
us = solve_burgers(u0, 10, nu)

sess = Session(); init(sess)
U = run(sess, us)

matwrite("fenics/fwd2.mat", Dict("U"=>U))
close("all")
figure(figsize=(10,3))
subplot(121)
title("u displacement")
visualize_scalar_on_fem_points(U[end,1:mmesh.nnode], mmesh)
subplot(122)
title("v displacement")
visualize_scalar_on_fem_points(U[end,mmesh.ndof + 1:mmesh.ndof + mmesh.nnode], mmesh)
savefig("fenics/fwd2.png")

close("all")
visualize_vector_on_fem_points(U[end,1:mmesh.nnode], U[end,mmesh.ndof + 1:mmesh.ndof + mmesh.nnode], mmesh)
savefig("fenics/fwd2_quiver.png")

close("all")
visualize_scalar_on_gauss_points(run(sess, nu), mmesh)
savefig("fenics/nu.png")


text:
"""
Authors:  Yaroslav Salii, 2021
          Kara Ignatenko, 2021

Contains VegaLite spec-generating functions to be used in visualizations.

vega-specs.jl
2021-09-22 v.0.1: First modular version
2021-09-28 v.0.2: Add more specs for network visualization
2021-10-09 v.0.3: Add specs for the average infected rate line plot
2021-10-13 v.0.4: Drop the leading 0's of FIPS codes to resolve the inconsistency
                  between how FIPS codes are represented in Oboe vs. VegaDatasets
2021-10-24 v.0.5: Add a spec for control effort choropleth
"""
module VegaSpecs

using VegaLite, VegaDatasets, DataFrames

us10m = dataset("us-10m")

"""Utility function to drop the leading zero of a FIPS code."""
function dropLeadingZero(str::String)
    if startswith(str, "0")
        str[2:length(str)]
    else
        str
    end
end

normalize(arr::AbstractArray) = map(dropLeadingZero, arr)

"""
Plot side-by-side chloropleths comparing the Z and Z0 values in the solution `sol`
for a given day `day`, with `median` as the centre of the colour scale.
"""
function pltZOptVsNullByCty(sol::DataFrame, day::Int, median::Float64)
    # helper functions to get the per names of the Z and Z0 columns for a given day
    day2col(day::Int)  = "Z" * string(day)
    day2col0(day::Int) = day2col(day) * "_NULL"

    @vlplot(
	repeat={column=[day2col(day), day2col(day)*"_NULL"]},
    ) +
    @vlplot(
        :geoshape,
        data={
            values=us10m,
            format={
                type=:topojson,
                feature=:counties
            }
        },
        transform=[{
            lookup=:id,
            from={
                data=select(sol, ["id", day2col(day), day2col0(day)]), #INSERT DF HERE
                key=:id,
                fields=[day2col(day), day2col0(day)]
            }
        }],
        projection={
            type=:albersUsa
        },
        encoding={
            color={
                field={repeat=:column},
                type=:quantitative,
                scale={
                    domainMid= median, #median no. infected
                    scheme=:reds
                }
            }
        }
    )
end

"""
Plot a control effort by-county choropleth map for the given `day`
The control effort u has a blue-to-purple scheme and [0,1] scale
"""
function pltCtrlByCty(sol::DataFrame, day::Int)
    day2col_u(day::Int) = "u" * string(day) #picking the control column name for the day
    u_today = day2col_u(day) #compute the requisite column name
    @vlplot(
        :geoshape,
        data={
            values=us10m,
            format={
                type=:topojson,
                feature=:counties
            }
        },
        transform=[{
            lookup=:id,
            from={
                data=select(sol, ["id", u_today]), #INSERT DF HERE
                key=:id,
                fields=[u_today]
            }
        }],
        projection={
            type=:albersUsa
        },
        encoding={
            color={
                field= u_today,
                type=:quantitative,
                scale={
                    domainMin = 0,
                    domainMax = 1, #median no. infected
                    scheme=:bluepurple
                }
            }
        }
    )
end

# """
# ISSUES: botches the color scale properties
# Plot 3 side-by-side chloropleths comparing the u, Z, and Z_Null values in the solution `sol`
# for a given day `day`.
# For Z and Z_Null, the `median` as the centre of the Z and Z_Null colour scale.
# The control effort u is displayed to the left, with green scheme and [0,1] scale
# """
# function pltCtrl_ZOpt_ZNull_ByCty(sol::DataFrame, day::Int, median::Float64)
#     @vlplot() + [pltCtrlByCty(sol,day), pltZOptVsNullByCty(sol,day,median)]
# end

"""
Plot the average infection rate Z (for both the optimal case
and the null case) and the control effort U as functions
of time.
`long_avgc` must have `[:z_avg, :zNull_avg, :u_avg]`
"""
pltAvgInfdCtrl(long_avgc::DataFrame) = @vlplot(
    data = long_avgc,
    :line,
    x=:day,
    y=:value,
    color={
        :symbol,
        scale={
            domain=["zNull_avg","z_avg","u_avg"],
            range = ["#E31A1C","#FB9A99","#33A02C"] #red, pink, green
            #scheme=:paired
        },
        #legend = nothing
        legend = {
            orient = "top-right",
            #values=["lorem","ipsum","sit"]
            title = "variable",
        }
    },
)

pltCanvasSte(fips::Vector{String}) = @vlplot(
    mark={
        :geoshape,
        fill=:lightgray,
        stroke=:white,
        strokeWidth=1
    },
    data={
        values=us10m,
        format={
            type=:topojson,
            feature=:states
        }
    },
    transform=[{
            filter={field =:id,oneOf = normalize(fips)}
            }],
    projection={type=:albersUsa},
)

pltCanvasCty(ctys::DataFrame) = @vlplot(
    mark={
        :geoshape,
        fill=:lightgray,
        stroke=:white
    },
    data={
        values=us10m,
        format={
            type=:topojson,
            feature=:counties
        }
    },
    transform=[{
            filter={field =:id,oneOf = ctys.id}
            }],
    projection={type=:albersUsa},
)

pltBoundarySte(fips::Vector{String}) = @vlplot(
    mark={
        :geoshape,
        stroke=:white,
        filled = false,
        strokeWidth=3,
        strokeOpacity=0.2
    },
    data={
        values=us10m,
        format={
            type=:topojson,
            feature=:states
        }
    },
    transform=[{
            filter={field =:id,oneOf = normalize(fips)}
            }],
    projection={type=:albersUsa},
)

pltDotsTracts(ns::DataFrame) = @vlplot(
    :circle,
    data=ns,
    projection={type=:albersUsa},
    longitude="LNG:q",
    latitude="LAT:q",
    tooltip="Name:n",
    size={value=2},
    color={value=:black})

pltDotsDsgAPs(dsgAPs::DataFrame) = @vlplot(
    :circle,
    data=dsgAPs,
    projection={type=:albersUsa},
    longitude="LNG:q",
    latitude="LAT:q",
    tooltip="IATA_Code:n",
    size={value=60},
    color={value=:steelblue}
)

function pltTractsAndAPsBySte(ns::DataFrame, dsgAPs::DataFrame, fips::Vector{String})
    @vlplot() + pltCanvasSte(fips) + pltDotsTracts(ns) + pltDotsDsgAPs(dsgAPs)
end

function pltTractsAndAPsByCty(ns::DataFrame, dsgAPs::DataFrame, fips::Vector{String}, ctys::DataFrame; borders=true::Bool)
    @vlplot() + pltCanvasCty(ctys) +  pltDotsTracts(ns) + pltDotsDsgAPs(dsgAPs) + pltBoundarySte(fips)
end

pltPopCty(ctys::DataFrame) = @vlplot(
    :geoshape,
   # width=500, height=300,
    data={
        values=us10m,
        format={
            type=:topojson,
            feature=:counties
        }
    },
    transform=[{
        lookup=:id,
        from={
            data=ctys, #INSERT DF HERE
            key=:id,
            fields=["Pop"]
        }
    }],
    projection={
        type=:albersUsa
    },
    encoding={
        color={
            field="Pop",
            type=:quantitative,
            # type=:log,
            scale={
                domainMid= 44479, #median county pop
                scheme=:blues
            }
        }
    }
)

function pltPopCtyWithBorders(ctys::DataFrame, fips::Vector{String})
     @vlplot() + pltPopCty(ctys) + pltBoundarySte(fips)
end

end


text:
# Implements the APIs required by an application master to communicate with the resource manager and the node managers.
# The underlying methods are implementations of the following protobuf services:
# - applicationmaster_protocol.proto
# - containermanagement_protocol.proto

# In managed mode, the AMRMToken available in file CONTAINER_TOKEN_FILE_ENV_NAME is in Java serialized format
#   - Example: https://github.com/apache/hadoop/blob/ab32762f4381449540e1580eeda1cd5198e1e5fa/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/launcher/ContainerLaunch.java#L348-L351
#   - Some related debate about this here: https://issues.apache.org/jira/browse/HADOOP-6685
# Since that is unusable in anything other than Java, we are forced to operate only in unmanaged mode, where we get it from the application report.

"""
YarnAppMaster is a skeleton application master. It provides the generic scafolding methods which can be used to create specific
application masters for different purposes.

When initializing a YarnAppMaster instance as a managed app master, the scheduler address is picked up from the environment variable `JULIA_YARN_RESOURCEMANAGER_SCHEDULER_ADDRESS`.
Tokens set by Yarn in the file pointed to by `HADOOP_TOKEN_FILE_LOCATION` are also read in automatically.

When run as a managed app master, if a function is provided to be executed, then the application master is registered, the function is executed and then the application master is deregistered.
This provides a convenient way to run simple Julia applications in a Yarn cluster. E.g.:

```
using Elly

YarnAppMaster() do
    ...
    # execute Julia code
end
```
"""
mutable struct YarnAppMaster
    amrm_conn::YarnAMRMProtocol

    host::AbstractString
    port::Integer
    tracking_url::AbstractString

    max_mem::Int32
    max_cores::Int32
    available_mem::Int32
    available_cores::Int32
    nodes::YarnNodes
    containers::YarnContainers
    queue::AbstractString
    response_id::Int32      # initial value must be 0, update with response_id sent from server on every response
    registration::Union{Nothing,RegisterApplicationMasterResponseProto}
    am_rm_task::Union{Nothing,Task}
    lck::ReentrantLock

    function YarnAppMaster(rmhost::AbstractString, rmport::Integer, ugi::UserGroupInformation=UserGroupInformation(),
                amhost::AbstractString="", amport::Integer=0, amurl::AbstractString="")
        amrm_conn = YarnAMRMProtocol(rmhost, rmport, ugi)

        new(amrm_conn, amhost, amport, amurl,
            Int32(0), Int32(0), Int32(0), Int32(0),
            YarnNodes(ugi), YarnContainers(),
            "", 0,
            nothing, nothing, ReentrantLock())
    end

    function YarnAppMaster(ugi::UserGroupInformation=UserGroupInformation())
        rmschedaddress = ENV["JULIA_YARN_RESOURCEMANAGER_SCHEDULER_ADDRESS"]
        @debug("got rm address", rmschedaddress)
        parts = split(rmschedaddress, ":")
        host = parts[1]
        schedport = parse(Int, parts[2])
        am = YarnAppMaster(host, schedport, ugi)
        for token in find_tokens(ugi; kind="YARN_AM_RM_TOKEN")
            add_token!(ugi, token_alias(am.amrm_conn.channel), token)
        end
        am
    end
end

function YarnAppMaster(fn::Function, ugi::UserGroupInformation=UserGroupInformation())
    yam = YarnAppMaster(ugi)
    register(yam)
    try
        fn()
    finally
        unregister(yam, true)
    end
end

function show(io::IO, yam::YarnAppMaster)
    show(io, yam.amrm_conn)
    if yam.registration !== nothing
        println(io, "    Memory: available:$(yam.available_mem), max:$(yam.max_mem), can schecule:$(can_schedule_mem(yam))")
        println(io, "    Cores: available:$(yam.available_cores), max:$(yam.max_cores), can schedule:$(can_schedule_cores(yam))")
        println(io, "    Queue: $(yam.queue)")
        show(io, yam.nodes)
        show(io, yam.containers)
    end
end

callback(yam::YarnAppMaster, on_container_alloc::Union{Nothing,Function}, on_container_finish::Union{Nothing,Function}) =
    callback(yam.containers, on_container_alloc, on_container_finish)

function submit(client::YarnClient, unmanagedappmaster::YarnAppMaster)
    @debug("submitting unmanaged application")
    clc = launchcontext()
    app = submit(client, clc; unmanaged=true)

    # keep the am_rm token
    tok = am_rm_token(app)
    channel = unmanagedappmaster.amrm_conn.channel
    @debug("adding token", alias=token_alias(channel))
    add_token!(channel.ugi, token_alias(channel), tok)

    # register the unmanaged appmaster
    register(unmanagedappmaster)
    wait_for_attempt_state(app, Int32(1), YarnApplicationAttemptStateProto.APP_ATTEMPT_RUNNING) || throw(YarnException("Application attempt could not be launched"))

    # initialize complete node list for appmaster
    nodes(client; nodelist=unmanagedappmaster.nodes)

    app
end

function register(yam::YarnAppMaster)
    inp = RegisterApplicationMasterRequestProto()
    if !isempty(yam.host) && (yam.port > 0)
        setproperty!(inp, :host, yam.host)
        setproperty!(inp, :port, convert(Int32,yam.port))
    end
    !isempty(yam.tracking_url) && setproperty!(inp, :tracking_url, yam.tracking_url)

    resp = lock(yam.lck) do
        registerApplicationMaster(yam.amrm_conn, inp)
    end
    yam.registration = resp

    if hasproperty(resp, :maximumCapability)
        yam.max_mem = resp.maximumCapability.memory
        yam.max_cores = resp.maximumCapability.virtual_cores
    end
    @debug("max capability", mem=yam.max_mem, cores=yam.max_cores)
    if hasproperty(resp, :queue)
        yam.queue = resp.queue
    end

    # start the am_rm processing task on registration if it is a managed application master
    yam.am_rm_task = @async process_am_rm(yam)

    nothing
end

can_schedule_mem(yam::YarnAppMaster) = can_schedule(yam, SchedulerResourceTypes.MEMORY)
can_schedule_cores(yam::YarnAppMaster) = can_schedule(yam, SchedulerResourceTypes.CPU)
function can_schedule(yam::YarnAppMaster, restype::Int32)
    reg = yam.registration
    !hasproperty(reg, :scheduler_resource_types) && (return false)
    restype in reg.scheduler_resource_types
end

function _unregister(yam::YarnAppMaster, finalstatus::Int32, diagnostics::AbstractString)
    inp = FinishApplicationMasterRequestProto(final_application_status=finalstatus)
    !isempty(yam.tracking_url) && setproperty!(inp, :tracking_url, yam.tracking_url)
    !isempty(diagnostics) && setproperty!(inp, :diagnostics, diagnostics)

    resp = lock(yam.lck) do
        finishApplicationMaster(yam.amrm_conn, inp)
    end
    resp.isUnregistered && (yam.registration = nothing)
    resp.isUnregistered
end

unregister(yam::YarnAppMaster, success::Bool, diagnostics::AbstractString="") = _unregister(yam, success ? FinalApplicationStatusProto.APP_SUCCEEDED : FinalApplicationStatusProto.APP_FAILED, diagnostics)
kill(yam::YarnAppMaster, diagnostics::AbstractString="") = _unregister(yam, FinalApplicationStatusProto.APP_KILLED, diagnostics)

container_allocate(yam::YarnAppMaster, numcontainers::Int; opts...) = request_alloc(yam.containers, numcontainers; opts...)
container_release(yam::YarnAppMaster, cids::ContainerIdProto...) = request_release(yam.containers, cids...)

container_start(yam::YarnAppMaster, cid::ContainerIdProto, container_spec::ContainerLaunchContextProto) = container_start(yam, container_id_string(cid), container_spec)
container_start(yam::YarnAppMaster, cidstr::String, container_spec::ContainerLaunchContextProto) = container_start(yam, yam.containers.containers[cidstr], container_spec)
function container_start(yam::YarnAppMaster, container::ContainerProto, container_spec::ContainerLaunchContextProto)
    @debug("starting", container)
    req = StartContainerRequestProto(container_launch_context=container_spec, container_token=container.container_token)
    inp = StartContainersRequestProto(start_container_request=[req])

    nodeid = container.nodeId
    nm_conn = get_connection(yam.nodes, nodeid)
    success = false
    resp = StartContainersResponseProto()
    try
        resp = startContainers(nm_conn, inp)
        success = true
    catch ex
        rethrow(ex)
    finally
        release_connection(yam.nodes, nodeid, nm_conn, success)
    end
    success || throw(YarnException("Error starting container"))
    hasproperty(resp, :succeeded_requests) || throw(YarnException(hasproperty(resp,:failed_requests) ? resp.failed_requests[1] : "Error starting container"))
    cid = resp.succeeded_requests[1]
    (cid == container.id) || throw(YarnException("Unexpected container id mismatch"))
    set_busy(yam.containers, cid)
    cid
end

container_stop(yam::YarnAppMaster, cid::ContainerIdProto) = container_stop(yam, container_id_string(cid))
container_stop(yam::YarnAppMaster, cidstr::String) = container_stop(yam, yam.containers.containers[cidstr])
function container_stop(yam::YarnAppMaster, container::ContainerProto)
    @debug("stopping", container)

    inp = StopContainersRequestProto(container_id=[container.id])
    nodeid = container.nodeId
    nm_conn = get_connection(yam.nodes, nodeid)
    success = false
    resp = StopContainersResponseProto()
    try
        resp = stopContainers(nm_conn, inp)
        success = true
    catch ex
        rethrow(ex)
    finally
        release_connection(yam.nodes, nodeid, nm_conn, success)
    end
    success || throw(YarnException("Error stopping container"))
    hasproperty(resp, :succeeded_requests) || throw(YarnException(hasproperty(resp,:failed_requests) ? resp.failed_requests[1] : "Error stopping container"))
    cid = resp.succeeded_requests[1]
    (cid == container.id) || throw(YarnException("Unexpected container id mismatch"))
    set_free(yam.containers, cid)
    cid
end

function _update_rm(yam::YarnAppMaster)
    @debug("started processing am-rm messages")
    inp = AllocateRequestProto()

    # allocation and release requests
    (alloc_pending,release_pending) = torequest(yam.containers)
    @debug("pending", alloc_pending, release_pending)
    !isempty(alloc_pending) && setproperty!(inp, :ask, alloc_pending)
    !isempty(release_pending) && setproperty!(inp, :release, release_pending)

    # send last received response id as response_id in this request
    setproperty!(inp, :response_id, yam.response_id)

    #@debug(inp)
    resp = lock(yam.lck) do
        allocate_resp = allocate(yam.amrm_conn, inp)
        yam.response_id = allocate_resp.response_id # next response id must match this
        allocate_resp
    end
    #@debug(resp)

    # store/update tokens
    channel = yam.amrm_conn.channel
    ugi = channel.ugi
    hasproperty(resp, :am_rm_token) && add_token!(ugi, token_alias(channel), resp.am_rm_token)
    if hasproperty(resp, :nm_tokens)
        for nmtok in resp.nm_tokens
            add_token!(ugi, token_alias(nmtok.nodeId), nmtok.token)
        end
    end

    # update available headroom
    if hasproperty(resp, :limit)
        yam.available_mem = resp.limit.memory
        yam.available_cores = resp.limit.virtual_cores
    end

    # update node and container status
    update(yam.nodes, resp)
    update(yam.containers, resp)
    @debug("finished processing am-rm messages")
    #@debug(yam)
    nothing
end

haverequests(yam::YarnAppMaster) = haverequests(yam.containers)

function process_am_rm(yam::YarnAppMaster)
    @debug("started am-rm processor task")
    stopped = ()->(yam.registration === nothing)
    stopwaiting = ()->(haverequests(yam) || (yam.registration === nothing))
    waittime = 10.
    while !stopped()
        t1 = time()
        _update_rm(yam)
        t2 = time()
        interval = t1 + 60 - t2
        if interval > 0
            timedwait(stopwaiting, interval; pollint=5.0)
            t3 = time()
            waittime = (waittime*5 + (t3 - t2))/6
            (waittime < 10) && sleep(10-waittime)
        end
    end
    @debug("stopped am-rm processor task")
    nothing
end


text:
using DelimitedFiles, ProgressMeter, PyPlot

include("./util.jl")
include("./parsers.jl")
include("./Algorithms/TEAVAR.jl")
include("./simulation.jl")

function probabilityNoise(topologies,
                          demand_downscales,
                          num_demands,
                          iterations,
                          cutoff,
                          noise; paths="SMORE",
                          weibull_scale=.0001,
                          add_noise="SCENARIOS",
                          plot=true,
                          dirname="./data/raw/probability_noise")
    env = Gurobi.Env()

    error_vals = [[] for i in 1:length(noise)]

    dir = nextRun(dirname)
    for j in 1:length(noise)
        writedlm("$(dir)/noise_$(noise[j])_error", [["val_optimal", "val", "error_val"]])
    end

    progress = ProgressMeter.Progress(length(topologies)*num_demands*iterations*length(noise), .1, "Computing Probability Noise Error...", 50)
    noise_error = zeros(length(noise))
    for t in 1:length(topologies)
        links, capacity, link_probs, nodes = readTopology(topologies[t])
        for d in 1:num_demands
            demand, flows = readDemand("$(topologies[t])/demand", length(nodes), d, downscale=demand_downscales[t])
            # T, Tf, k = parsePaths("$(topologies[t])/paths/$(paths)", links, flows)
            k = 10
            T, Tf, g = getTunnels(nodes, links, capacity, flows, k)

            for i in 1:iterations
                weibull_probs = weibullProbs(length(link_probs), shape=.8, scale=weibull_scale)
                scenarios, scenario_probs = subScenarios(weibull_probs, cutoff, first=true, last=false)
                # scenarios_w_noise, scenario_probs_w_noise = subScenarios(weibull_probs_noise, cutoff, first=true, last=false)
                var, cvar, a, max_u = TEAVAR(env, links, capacity, flows, demand, 0, k, T, Tf, scenarios, scenario_probs)
                losses = calculateLossReallocation(links, capacity, demand, flows, T, Tf, k, a, scenarios, scenario_probs)
                val_optimal = sum(losses .* scenario_probs)
                # val_optimal = 1-cvar
                # val_optimal = sum((1 .- max_u) .* scenario_probs)
                for j in 1:length(noise)
                    scenario_probs_noise = []
                    if add_noise == "EVENTS"
                        weibull_probs_noise = map(p -> p + (p * noise[j] * rand(Uniform(-1, 1))), weibull_probs)
                        scenario_probs_noise = getProbabilities(scenarios, weibull_probs_noise)
                        scenario_probs_noise = scenario_probs_noise ./ sum(scenario_probs_noise)
                    else
                        scenario_probs_noise = map(p -> p + (p * noise[j] * rand(Uniform(-1, 1))), scenario_probs)
                        scenario_probs_noise = scenario_probs_noise ./ sum(scenario_probs_noise)
                    end
                    println(scenario_probs_noise)
                    # var, cvar, a, max_u = TEAVAR(env, links, capacity, flows, demand, 0, k, T, Tf, scenarios, scenario_probs_noise)
                    losses = calculateLossReallocation(links, capacity, demand, flows, T, Tf, k, a, scenarios, scenario_probs_noise)
                    val = sum(losses .* scenario_probs_noise)
                    # val = 1-cvar
                    # val = sum((1 .- max_u) .* scenario_probs_noise)
                    err = abs((val_optimal - val)/val_optimal)
                    noise_error[j] += err
                    open("$(dir)/noise_$(noise[j])_error", "a") do io
                        writedlm(io, transpose([val_optimal, val, err]))
                    end
                    ProgressMeter.next!(progress, showvalues = [(:topology,topologies[t]), (:demand,"$(d)/$(num_demands)"), (:iterations,"$(i)/$(iterations)"), (:noise, noise[j]), (:error, err)])
                end
            end
        end
    end
    y_vals = noise_error ./ (num_demands * iterations * length(topologies))

    # LOG RESULTS
    writedlm("$(dir)/noises", noise)
    writedlm("$(dir)/y_vals", y_vals)
    writedlm("$(dir)/params", [["topologies", "demand_downscales", "num_demands", "iterations", "cutoff", "noise", "paths", "weibull_scale"], [topologies, demand_downscales, num_demands, iterations, cutoff, noise, paths, weibull_scale]])

    # PLOT
    if plot
        PyPlot.clf()
        nbars = length(noise)
        barWidth = 1/(nbars)
        for i in 1:length(y_vals)
            PyPlot.bar(barWidth .* i, y_vals[i], alpha=0.8, width=barWidth)
        end
        PyPlot.ylabel("Percent Error", fontweight="bold")
        PyPlot.legend(noise, loc="upper right")
        PyPlot.savefig("$(dir)/plot.png")
        PyPlot.show()
    end
end


text:
using SeisDownload
using Test

using SeisIO, Dates  #Please load SeisIO here to correctly define type of structure "SeisData"

@testset "SeisDownload.jl" begin
    # Write your own tests here.
    #==================================================#
    # Input Parameters
    MAX_MEM_PER_CPU = 1.0 # [GB] maximum allocated memory for one cpu
    DownloadType = "Noise" # Choise of "Noise" or "Earthquake"

    #station =[""]
    # Time info for Noise case
    starttime   = DateTime(2004,8,20,12,0,0)
    endtime     = DateTime(2004,8,20,14,0,0)

    #locationbox   = [35.1811, 36.4323, -118.5294, -116.6171]
    IsLocationBox = false

    datasource = "NCEDC" # currently, only one src can be specified.
    #station = ["CCRB","EADB","FROB","GHIB","JCNB","JCSB","LCCB","MMNB", "RMNB", "SCYB","SMNB","VARB","VCAB"]

    DL_time_unit = 3600 * 1 #3600 * 24 # Download time unit [s] more than one day is better to avoid artifacts of response removal
    download_margin = 60 * 5 #Int, [s] margin of both edges while downloading data to avoid the edge effect due to instrument response removal.

    savesamplefreq = 20.0 #[1/s] when saving the data, downsample at this freq

    IsResponseRemove = true #whether instrumental response is removed or not
    #pre_filt    = (0.001, 0.002, 10.0, 20.0) #prefilter tuple used obspy remove_response: taper between f1 and f2, f3 and f4 with obspy

    fodir       = "./dataset"
    foname      = "testdata" # data is saved at ./dataset/$foname.jld2
    outputformat = "JLD2"   # output format can be JLD2, (under implementing; ASDF, SAC, ...)
    Istmpfilepreserved = false # if true, do not delete intermediate tmp files
    #==================================================#

    # store metadata in Dictionary
    # This can be customized by users

    stationlist      = String[]
    stationmethod    = String[]
    stationsrc       = String[]

    #for CI
    network     = ["BP"]
    station = ["*"]
    location    = [""]
    channel     = ["BP1"]
    datasource = "NCEDC" # currently, only one src can be specified.

    for i=1:length(network)
        for j=1:length(station)
            for k=1:length(location)
                for l=1:length(channel)
                    stationname = join([network[i], station[j], location[k], channel[l]], ".")
                    push!(stationlist, stationname)

                    #Here should be improved for multiple seismic network; we have to make
                    #proper conbination of request station and data server.
                    push!(stationmethod, "FDSN")
                    push!(stationsrc, datasource)
                end
            end
        end
    end

    stationinfo = Dict(["stationlist" => stationlist, "stationmethod" => stationmethod, "stationsrc" => stationsrc])

    mkpath(fodir)
    fopath=joinpath(fodir, foname*".jld2")

    #if lat-log box or not
    IsLocationBox ? reg=locationbox : reg=[]

    InputDictionary = Dict([
        "MAX_MEM_PER_CPU" => MAX_MEM_PER_CPU,
        "DownloadType"=> DownloadType,
        "stationinfo" => stationinfo,
        "starttime"   => starttime,
        "endtime"     => endtime,
        "DL_time_unit"     => DL_time_unit,
        "IsLocationBox"    => IsLocationBox,
        "reg"              => reg,
        "IsResponseRemove" => IsResponseRemove,
        "download_margin"  => download_margin,
        "fopath"           => fopath,
        "savesamplefreq"   => savesamplefreq,
        "outputformat"     => outputformat,
        "Istmpfilepreserved" => Istmpfilepreserved,
        "IsXMLfileRemoved" =>true
    ])

    # mass request with input Dictionary
    @test 0 == SeisDownload.seisdownload(InputDictionary)

end


text:
@testset "eachobs" begin
    for (i,x) in enumerate(eachobs(X))
        @test x == X[:,i]
    end

    for (i,x) in enumerate(eachobs(X, buffer=true))
        @test x == X[:,i]
    end

    b = zeros(size(X, 1))
    for (i,x) in enumerate(eachobs(X, buffer=b))
        @test x == X[:,i]
    end
    @test_broken b == X[:,end]

    @testset "batched" begin
        for (i, x) in enumerate(eachobs(X, batchsize=2, partial=true))
            if i != 8
                @test size(x) == (4,2)
                @test x == X[:,2i-1:2i]
            else
                @test size(x) == (4,1)
                @test x == X[:,2i-1:2i-1]
            end
        end

        for (i, x) in enumerate(eachobs(X, batchsize=2, buffer=true, partial=false))
            @test size(x) == (4,2)
            @test x == X[:,2i-1:2i]
        end

        b = zeros(4, 2)
        for (i, x) in enumerate(eachobs(X, batchsize=2, buffer=b, partial=false))
            @test size(x) == (4,2)
            @test x == X[:,2i-1:2i]
        end
    end

    @testset "shuffled" begin
        # does not reshuffle on iteration
        shuffled = eachobs(shuffleobs(1:50))
        @test collect(shuffled) == collect(shuffled)

        # does reshuffle
        reshuffled = eachobs(1:50, shuffle = true)
        @test collect(reshuffled) != collect(reshuffled)

        reshuffled = eachobs(1:50, shuffle = true, buffer = true)
        @test collect(reshuffled) != collect(reshuffled)

        reshuffled = eachobs(1:50, shuffle = true, parallel = true)
        @test collect(reshuffled) != collect(reshuffled)

        reshuffled = eachobs(1:50, shuffle = true, buffer = true, parallel = true)
        @test collect(reshuffled) != collect(reshuffled)
    end
    @testset "Argument combinations" begin
        for batchsize ∈ (-1, 2), buffer ∈ (true, false), collate ∈ (nothing, true, false),
                parallel ∈ (true, false), shuffle ∈ (true, false), partial ∈ (true, false)
            if !(buffer isa Bool) && batchsize > 0
                buffer = getobs(BatchView(X; batchsize), 1)
            end
            iter = eachobs(X; batchsize, shuffle, buffer, parallel, partial)
            @test_nowarn for _ in iter end
        end
    end
end

max_stars_repo_name: JuliaML/MLBase

max_issues_repo_name: JuliaML/MLBase

max_forks_repo_name: JuliaML/MLBase


text:
include("queue.jl")
include("buffered_input.jl")

# Position within the document being parsed
struct Mark
    index::UInt64
    line::UInt64
    column::UInt64
end

function show(io::IO, mark::Mark)
    @printf(io, "line %d, column %d", mark.line, mark.column)
end

# Where in the stream a particular token lies.
struct Span
    start_mark::Mark
    end_mark::Mark
end

struct SimpleKey
    token_number::UInt64
    required::Bool
    mark::Mark
end

# Errors thrown by the scanner.
struct ScannerError <: Exception
    context::Union{String, Nothing}
    context_mark::Union{Mark, Nothing}
    problem::String
    problem_mark::Mark
end

function show(io::IO, error::ScannerError)
    if error.context !== nothing
        print(io, error.context, " at ", error.context_mark, ": ")
    end
    print(io, error.problem, " at ", error.problem_mark)
end

include("tokens.jl")

# A stream type for the scanner, which is just a IO stream with scanner state.
mutable struct TokenStream
    input::BufferedInput

    # All tokens read.
    done::Bool

    # Tokens queued to be read.
    token_queue::Queue{Token}

    # Index of the start of the head of the stream. (0-based)
    index::UInt64

    # Index of the current column. (0-based)
    column::UInt64

    # Current line numebr. (0-based)
    line::UInt64

    # Number of tokens read, not including those still in token_queue.
    tokens_taken::UInt64

    # The number of unclosed '{' and '['. `flow_level == 0` means block
    # context.
    flow_level::UInt64

    # Current indentation level.
    indent::Int

    # Past indentation levels.
    indents::Vector{Int}

    # Can a simple key start at the current position? A simple key may
    # start:
    # - at the beginning of the line, not counting indentation spaces
    #       (in block context),
    # - after '{', '[', ',' (in the flow context),
    # - after '?', ':', '-' (in the block context).
    # In the block context, this flag also signifies if a block collection
    # may start at the current position.
    allow_simple_key::Bool

    # Keep track of possible simple keys. This is a dictionary. The key
    # is `flow_level`; there can be no more that one possible simple key
    # for each level. The value is a SimpleKey record:
    #   (token_number, required, index, line, column, mark)
    # A simple key may start with ALIAS, ANCHOR, TAG, SCALAR(flow),
    # '[', or '{' tokens.
    possible_simple_keys::Dict{UInt64,SimpleKey}

    function TokenStream(stream::IO)
        tokstream = new(BufferedInput(stream), false, Queue{Token}(),
                        1, 0, 1, 0, 0, -1,
                        Vector{Int}(undef, 0), true, Dict())
        fetch_stream_start(tokstream)
        tokstream
    end
end

function reset!(stream::TokenStream)
    stream.done = false
    fetch_stream_start(stream)
end

function get_mark(stream::TokenStream)
    Mark(stream.index, stream.line, stream.column)
end

# Advance the stream by k characters.
function forwardchars!(stream::TokenStream, k::Integer)
    for _ in 1:k
        c = peek(stream.input)
        forward!(stream.input)
        stream.index += 1
        if in(c, "\n\u0085\u2028\u2029") ||
            (c == '\r' && peek(stream.input) == '\n')
            stream.column = 0
            stream.line += 1
        else
            stream.column += 1
        end
    end
    stream.index += k
end

forwardchars!(stream::TokenStream) = forwardchars!(stream, 1)

function need_more_tokens(stream::TokenStream)
    if stream.done
        return false
    elseif isempty(stream.token_queue)
        return true
    end

    stale_possible_simple_keys(stream)
    next_possible_simple_key(stream) == stream.tokens_taken
end

function peek(stream::TokenStream)
    while need_more_tokens(stream)
        fetch_more_tokens(stream)
    end

    if !isempty(stream.token_queue)
        peek(stream.token_queue)
    else
        nothing
    end
end

function forward!(stream::TokenStream)
    while need_more_tokens(stream)
        fetch_more_tokens(stream)
    end

    if !isempty(stream.token_queue)
        stream.tokens_taken += 1
        dequeue!(stream.token_queue)
    else
        nothing
    end
end

# Read one or more tokens from the input stream.
function fetch_more_tokens(stream::TokenStream)
    # Eat whitespace.
    scan_to_next_token(stream::TokenStream)

    # Remove obsolete possible simple keys.
    stale_possible_simple_keys(stream)

    # Compare the current indentation and column. It may add some tokens
    # and decrease the current indentation level.
    unwind_indent(stream, stream.column)

    c = peek(stream.input)
    if c == '\0' || c === nothing
        fetch_stream_end(stream)
    elseif c == '%' && check_directive(stream)
        fetch_directive(stream)
    elseif c == '-' && check_document_start(stream)
        fetch_document_start(stream)
    elseif c == '.' && check_document_end(stream)
        fetch_document_end(stream)
        stream.done = true
    elseif c == '['
        fetch_flow_sequence_start(stream)
    elseif c == '{'
        fetch_flow_mapping_start(stream)
    elseif c == ']'
        fetch_flow_sequence_end(stream)
    elseif c == '}'
        fetch_flow_mapping_end(stream)
    elseif c == ','
        fetch_flow_entry(stream)
    elseif c == '-' && check_block_entry(stream)
        fetch_block_entry(stream)
    elseif c == '?' && check_key(stream)
        fetch_key(stream)
    elseif c == ':' && check_value(stream)
        fetch_value(stream)
    elseif c == '*'
        fetch_alias(stream)
    elseif c == '&'
        fetch_anchor(stream)
    elseif c == '!'
        fetch_tag(stream)
    elseif c == '|' && stream.flow_level == 0
        fetch_literal(stream)
    elseif c == '>' && stream.flow_level == 0
        fetch_folded(stream)
    elseif c == '\''
        fetch_single(stream)
    elseif c == '\"'
        fetch_double(stream)
    elseif check_plain(stream)
        fetch_plain(stream)
    else
        # TODO: Throw a meaningful exception.
        throw(c)
    end
end

# Simple keys
# -----------

# Return the number of the nearest possible simple key.
function next_possible_simple_key(stream::TokenStream)
    min_token_number = nothing
    for (level, key) in stream.possible_simple_keys
        key = stream.possible_simple_keys[level]
        if min_token_number === nothing || key.token_number < min_token_number
            min_token_number = key.token_number
        end
    end
    min_token_number
end

# Remove entries that are no longer possible simple keys. According to
# the YAML specification, simple keys
# - should be limited to a single line,
# - should be no longer than 1024 characters.
# Disabling this procedure will allow simple keys of any length and
# height (may cause problems if indentation is broken though).
function stale_possible_simple_keys(stream::TokenStream)
    for (level, key) in stream.possible_simple_keys
        if key.mark.line != stream.line || stream.index - key.mark.index > 1024
            if key.required
                throw(ScannerError("while scanning a simple key", key.mark,
                      "could not find expected ':'", get_mark(stream)))
            end
            delete!(stream.possible_simple_keys, level)
        end
    end
end

function save_possible_simple_key(stream::TokenStream)
    # Simple key required at the current position.
    required = stream.flow_level == 0 && stream.indent == stream.column
    @assert stream.allow_simple_key || !required

    if stream.allow_simple_key
        remove_possible_simple_key(stream)
        token_number = stream.tokens_taken + length(stream.token_queue)
        key = SimpleKey(token_number, required, get_mark(stream))
        stream.possible_simple_keys[stream.flow_level] = key
    end
end

function remove_possible_simple_key(stream::TokenStream)
    # Remove the saved possible key position at the current flow level.
    if haskey(stream.possible_simple_keys, stream.flow_level)
        key = stream.possible_simple_keys[stream.flow_level]
        if key.required
            throw(ScannerError("while scanning a simple key", key.mark,
                               "could not find expected ':'", get_mark(stream)))
        end
        delete!(stream.possible_simple_keys, stream.flow_level)
    end
end

function unwind_indent(stream::TokenStream, column)
    # In the flow context, indentation is ignored. We make the scanner less
    # restrictive than specification requires.
    if stream.flow_level != 0
        return
    end

    # In block context, we may need to issue the BLOCK-END tokens.
    while stream.indent > column
        mark = get_mark(stream)
        stream.indent = pop!(stream.indents)
        enqueue!(stream.token_queue, BlockEndToken(Span(mark, mark)))
    end
end

function add_indent(stream::TokenStream, column)
    if stream.indent < column
        push!(stream.indents, stream.indent)
        stream.indent = column
        true
    else
        false
    end
end

# Checkers
# --------

const whitespace = "\0 \t\r\n\u0085\u2028\u2029"

function check_directive(stream::TokenStream)
    stream.column == 0
end

function check_document_start(stream::TokenStream)
    stream.column == 0 &&
    prefix(stream.input, 3) == "---" &&
    in(peek(stream.input, 3), whitespace)
end

 function check_document_end(stream::TokenStream)
     stream.column == 0 &&
     prefix(stream.input, 3) == "..." &&
    (in(peek(stream.input, 3), whitespace) || peek(stream.input, 3) === nothing)
 end

function check_block_entry(stream::TokenStream)
    in(peek(stream.input, 1), whitespace)
end

function check_key(stream::TokenStream)
    stream.flow_level > 0 || in(peek(stream.input, 1), whitespace)
end

function check_value(stream::TokenStream)
    cnext = peek(stream.input, 1)
    stream.flow_level > 0 || in(cnext, whitespace) || cnext === nothing
end

function check_plain(stream::TokenStream)
    !in(peek(stream.input), "\0 \t\r\n\u0085\u2028\u2029-?:,[]{}#&*!|>\'\"%@`") ||
    (!in(peek(stream.input, 1), whitespace) &&
     (peek(stream.input) == '-' || (stream.flow_level == 0 &&
                              in(peek(stream.input), "?:"))))
end

# Fetchers
# --------

function fetch_stream_start(stream::TokenStream)
    mark = get_mark(stream)
    # TODO: support other other encodings.
    enqueue!(stream.token_queue,
             StreamStartToken(Span(mark, mark), "utf-8"))
end

function fetch_stream_end(stream::TokenStream)
    # Set the current intendation to -1.
    unwind_indent(stream, -1)

    # Reset simple keys.
    remove_possible_simple_key(stream)
    stream.allow_simple_key = false
    empty!(stream.possible_simple_keys)

    mark = get_mark(stream)
    enqueue!(stream.token_queue, StreamEndToken(Span(mark, mark)))
    stream.done = true
end

function fetch_directive(stream::TokenStream)
    # Set the current intendation to -1.
    unwind_indent(stream, -1)

    # Reset simple keys.
    remove_possible_simple_key(stream)
    stream.allow_simple_key = false

    enqueue!(stream.token_queue, scan_directive(stream))
end

function fetch_document_start(stream::TokenStream)
    fetch_document_indicator(stream, DocumentStartToken)
end

function fetch_document_end(stream::TokenStream)
    fetch_document_indicator(stream, DocumentEndToken)
end

function fetch_document_indicator(stream::TokenStream, tokentype)
    # Set the current intendation to -1.
    unwind_indent(stream, -1)

    # Reset simple keys. Note that there could not be a block collection
    # after '---'.
    remove_possible_simple_key(stream)
    stream.allow_simple_key = false

    # Add DOCUMENT-START or DOCUMENT-END.
    start_mark = get_mark(stream)
    forwardchars!(stream, 3)
    end_mark = get_mark(stream)
    enqueue!(stream.token_queue, tokentype(Span(start_mark, end_mark)))
end

function fetch_flow_sequence_start(stream::TokenStream)
    fetch_flow_collection_start(stream, FlowSequenceStartToken)
end

function fetch_flow_mapping_start(stream::TokenStream)
    fetch_flow_collection_start(stream, FlowMappingStartToken)
end

function fetch_flow_collection_start(stream::TokenStream, tokentype)
    # '[' and '{' may start a simple key.
    save_possible_simple_key(stream)

    # Increase the flow level.
    stream.flow_level += 1

    # Simple keys are allowed after '[' and '{'.
    stream.allow_simple_key = true

    # Add FLOW-SEQUENCE-START or FLOW-MAPPING-START.
    start_mark = get_mark(stream)
    forwardchars!(stream)
    end_mark = get_mark(stream)
    enqueue!(stream.token_queue, tokentype(Span(start_mark, end_mark)))
end

function fetch_flow_sequence_end(stream::TokenStream)
    fetch_flow_collection_end(stream, FlowSequenceEndToken)
end

function fetch_flow_mapping_end(stream::TokenStream)
    fetch_flow_collection_end(stream, FlowMappingEndToken)
end

function fetch_flow_collection_end(stream::TokenStream, tokentype)
    # Reset possible simple key on the current level.
    remove_possible_simple_key(stream)

    # Decrease the flow level.
    stream.flow_level -= 1

    # No simple keys after ']' or '}'.
    stream.allow_simple_key = false

    # Add FLOW-SEQUENCE-END or FLOW-MAPPING-END.
    start_mark = get_mark(stream)
    forwardchars!(stream)
    end_mark = get_mark(stream)
    enqueue!(stream.token_queue, tokentype(Span(start_mark, end_mark)))
end

function fetch_flow_entry(stream::TokenStream)
    # Simple keys are allowed after ','.
    stream.allow_simple_key = true

    # Reset possible simple key on the current level.
    remove_possible_simple_key(stream)

    # Add FLOW-ENTRY.
    start_mark = get_mark(stream)
    forwardchars!(stream)
    end_mark = get_mark(stream)
    enqueue!(stream.token_queue, FlowEntryToken(Span(start_mark, end_mark)))
end

function fetch_block_entry(stream::TokenStream)
    # Block context needs additional checks.
    if stream.flow_level == 0
        # Are we allowed to start a new entry?
        if !stream.allow_simple_key
            throw(ScannerError(nothing, nothing,
                               "sequence entries not allowed here",
                               get_mark(stream)))
        end

        if add_indent(stream, stream.column)
            mark = get_mark(stream)
            enqueue!(stream.token_queue,
                     BlockSequenceStartToken(Span(mark, mark)))
        end

    # It's an error for the block entry to occur in the flow context,
    # but we let the parser detect this.
    else
        return
    end

    # Simple keys are allowed after '-'.
    stream.allow_simple_key = true

    # Reset possible simple key on the current level.
    remove_possible_simple_key(stream)

    # Add BLOCK-ENTRY.
    start_mark = get_mark(stream)
    forwardchars!(stream)
    end_mark = get_mark(stream)
    enqueue!(stream.token_queue,
             BlockEntryToken(Span(start_mark, end_mark)))
end

function fetch_key(stream::TokenStream)
    if stream.flow_level == 0
        # Are we allowed to start a key (not nessesary a simple)?
        if !stream.allow_simple_key
            throw(ScannerError(nothing, nothing,
                               "mapping keys are not allowed here",
                               get_mark(stream)))
        end

        # We may need to add BLOCK-MAPPING-START.
        if add_indent(stream, stream.column)
            mark = get_mark(stream)
            enqueue!(stream.token_queue,
                     BlockMappingStartToken(Span(mark, mark)))
        end
    end

    # Simple keys are allowed after '?' in the block context.
    stream.allow_simple_key = stream.flow_level == 0

    # Reset possible simple key on the current level.
    remove_possible_simple_key(stream)

    # Add KEY.
    start_mark = get_mark(stream)
    forwardchars!(stream)
    end_mark = get_mark(stream)
    enqueue!(stream.token_queue, KeyToken(Span(start_mark, end_mark)))
end

function fetch_value(stream::TokenStream)
    # Simple key
    if haskey(stream.possible_simple_keys, stream.flow_level)
        # Add KEY.
        key = stream.possible_simple_keys[stream.flow_level]
        delete!(stream.possible_simple_keys, stream.flow_level)

        enqueue!(stream.token_queue, KeyToken(Span(key.mark, key.mark)),
                 key.token_number - stream.tokens_taken)

        # If this key starts a new block mapping, we need to add
        # BLOCK-MAPPING-START.
        if stream.flow_level == 0 && add_indent(stream, key.mark.column)
            enqueue!(stream.token_queue,
                     BlockMappingStartToken(Span(key.mark, key.mark)),
                     key.token_number - stream.tokens_taken)
        end

        stream.allow_simple_key = false

    # Complex key
    else
        # Block context needs additional checks.
        # (Do we really need them? They will be caught by the parser
        # anyway.)
        if stream.flow_level == 0
            # We are allowed to start a complex value if and only if
            # we can start a simple key.
            if !stream.allow_simple_key
                throw(ScannerError(nothing, nothing,
                                   "mapping values are not allowed here",
                                   get_mark(stream)))
            end
        end

        # If this value starts a new block mapping, we need to add
        # BLOCK-MAPPING-START.  It will be detected as an error later by
        # the parser.
        if stream.flow_level == 0 && add_indent(stream, stream.column)
            mark = get_mark(stream)
            enqueue!(stream.token_queue,
                     BlockMappingStartToken(Span(mark, mark)))
        end

        # Simple keys are allowed after ':' in the block context.
        stream.allow_simple_key = stream.flow_level == 0

        # Reset possible simple key on the current level.
        remove_possible_simple_key(stream)
    end

    # Add VALUE.
    start_mark = get_mark(stream)
    forwardchars!(stream)
    end_mark = get_mark(stream)
    enqueue!(stream.token_queue, ValueToken(Span(start_mark, end_mark)))
end

function fetch_alias(stream::TokenStream)
    # ALIAS could be a simple key.
    save_possible_simple_key(stream)

    # No simple keys after ALIAS.
    stream.allow_simple_key = false

    # Scan and add ALIAS.
    enqueue!(stream.token_queue, scan_anchor(stream, AliasToken))
end

function fetch_anchor(stream::TokenStream)
    # ANCHOR could start a simple key.
    save_possible_simple_key(stream)

    # No simple keys after ANCHOR.
    stream.allow_simple_key = false

    # Scan and add ANCHOR.
    enqueue!(stream.token_queue, scan_anchor(stream, AnchorToken))
end

function fetch_tag(stream::TokenStream)
    # TAG could start a simple key.
    save_possible_simple_key(stream)

    # No simple keys after TAG.
    stream.allow_simple_key = false

    # Scan and add TAG.
    enqueue!(stream.token_queue, scan_tag(stream))
end

function fetch_literal(stream::TokenStream)
    fetch_block_scalar(stream, '|')
end

function fetch_folded(stream::TokenStream)
    fetch_block_scalar(stream, '>')
end

function fetch_block_scalar(stream::TokenStream, style::Char)
    # A simple key may follow a block scalar.
    stream.allow_simple_key = true

    # Reset possible simple key on the current level.
    remove_possible_simple_key(stream)

    # Scan and add SCALAR.
    enqueue!(stream.token_queue, scan_block_scalar(stream, style))
end

function fetch_single(stream::TokenStream)
    fetch_flow_scalar(stream, '\'')
end

function fetch_double(stream::TokenStream)
    fetch_flow_scalar(stream, '"')
end

function fetch_flow_scalar(stream::TokenStream, style::Char)
    # A flow scalar could be a simple key.
    save_possible_simple_key(stream)

    # No simple keys after flow scalars.
    stream.allow_simple_key = false

    # Scan and add SCALAR.
    enqueue!(stream.token_queue, scan_flow_scalar(stream, style))
end

function fetch_plain(stream::TokenStream)
    save_possible_simple_key(stream)
    stream.allow_simple_key = false
    enqueue!(stream.token_queue, scan_plain(stream))
end

# Scanners
# --------

# If the stream is at a line break, advance past it.
#
# Returns:
#   '\r\n'      :   '\n'
#   '\r'        :   '\n'
#   '\n'        :   '\n'
#   '\x85'      :   '\n'
#   '\u2028'    :   '\u2028'
#   '\u2029     :   '\u2029'
#   default     :   ''
#
function scan_line_break(stream::TokenStream)
    if in(peek(stream.input), "\r\n\u0085")
        if prefix(stream.input, 2) == "\r\n"
            forwardchars!(stream, 2)
        else
            forwardchars!(stream)
        end
        return "\n"
    elseif in(peek(stream.input), "\u2028\u2029")
        ch = peek(stream.input)
        forwardchars!(stream)
        return ch
    end
    return ""
end

# Scan past whitespace to the next token.
function scan_to_next_token(stream::TokenStream)
    if stream.index == 0 && peek(stream.input) == '\uFEFF'
        forwardchars!(stream)
    end

    found = false
    while !found
        while peek(stream.input) == ' '
            forwardchars!(stream)
        end

        if peek(stream.input) == '#'
            forwardchars!(stream)
            while !in(peek(stream.input), "\0\r\n\u0085\u2028\u2029")
                forwardchars!(stream)
            end
        end

        if scan_line_break(stream) != ""
            if stream.flow_level == 0
                stream.allow_simple_key = true
            end
        else
            found = true
        end
    end
end

function scan_directive(stream::TokenStream)
    start_mark = get_mark(stream)
    forwardchars!(stream)
    name = scan_directive_name(stream, start_mark)

    value = nothing
    if name == "YAML"
        value = scan_yaml_directive_value(stream, start_mark)
        end_mark = get_mark(stream)
    elseif name == "TAG"
        tag_handle = scan_tag_directive_handle(stream, start_mark)
        tag_prefix = scan_tag_directive_prefix(stream, start_mark)
        value = (tag_handle, tag_prefix)
        end_mark = get_mark(stream)
    else
        end_mark = get_mark(stream)
        while !in(peek(stream.input), "\0\r\n\u0085\u2028\u2029")
            forwardchars!(stream)
        end
    end

    scan_directive_ignored_line(stream, start_mark)
    DirectiveToken(Span(start_mark, end_mark), name, value)
end

function scan_directive_name(stream::TokenStream, start_mark::Mark)
    length = 0
    c = peek(stream.input)
    while isletter(c) || isnumeric(c) || c == '-' || c == '_'
        length += 1
        c = peek(stream.input, length)
    end

    if length == 0
        throw(ScannerError("while scanning a directive", start_mark,
                           "expected alphanumeric character, but found '$(c)'",
                           get_mark(stream)))
    end

    value = prefix(stream.input, length)
    forwardchars!(stream, length)

    c = peek(stream.input)
    if !in(c, ":\0 \r\n\u0085\u2028\u2029")
        throw(ScannerError("while scanning a directive", start_mark,
                           "expected alphanumeric character, but found '$(c)'",
                           get_mark(stream)))
    end

    value
end

function scan_yaml_directive_value(stream::TokenStream, start_mark::Mark)
    while peek(stream.input) == ' ' || peek(stream.input) == ':'
        forwardchars!(stream)
    end

    major = scan_yaml_directive_number(stream, start_mark)
    if peek(stream.input) != '.'
        throw(ScannerError("while scanning a directive", start_mark,
                           "expected '.' but found '$(peek(stream.input))'",
                           get_mark(stream)))
    end
    forwardchars!(stream)
    minor = scan_yaml_directive_number(stream, start_mark)
    if !in(peek(stream.input), "\0 \r\n\u0085\u2028\u2029")
        throw(ScannerError("while scanning a directive", start_mark,
                           "expected ' ' or a line break, but found '$(peek(stream.input))'",
                           get_mark(stream)))
    end
    return (major, minor)
end

function scan_yaml_directive_number(stream::TokenStream, start_mark::Mark)
    if !isdigit(peek(stream.input))
        throw(ScannerError("while scanning a directive", start_mark,
                           "expected a digit, but found '$(peek(stream.input))'",
                           get_mark(stream)))
    end
    length = 0
    while isdigit(peek(stream.input, length))
        length += 1
    end
    value = parse(Int, prefix(stream.input, length))
    forwardchars!(stream, length)
    value
end

function scan_tag_directive_handle(stream::TokenStream, start_mark::Mark)
    while peek(stream.input) == ' '
        forwardchars!(stream)
    end

    value = scan_tag_handle(stream, "directive", start_mark)
    if peek(stream.input) != ' '
        throw(ScannerError("while scanning a directive", start_mark,
                           "expected ' ', but found '$(peek(stream.input))'",
                           get_mark(stream)))
    end
    value
end

function scan_tag_directive_prefix(stream::TokenStream, start_mark::Mark)
    while peek(stream.input) == ' '
        forwardchars!(stream)
    end

    value = scan_tag_uri(stream, "directive", start_mark)
    if !in(peek(stream.input), "\0 \r\n\u0085\u2028\u2029")
        throw(ScannerError("while scanning a directive", start_mark,
                           "expected ' ', but found $(peek(stream.input))",
                           get_mark(stream)))
    end
    value
end

function scan_directive_ignored_line(stream::TokenStream, start_mark::Mark)
    while peek(stream.input) == ' '
        forwardchars!(stream)
    end
    if peek(stream.input) == '#'
        forwardchars!(stream)
        while !in(peek(stream.input), "\0\r\n\u0085\u2028\u2029")
            forwardchars!(stream)
        end
    end
    if !in(peek(stream.input), "\0\r\n\u0085\u2028\u2029")
        throw(ScannerError("while scanning a directive", start_mark,
                           "expected a comment or a line break, but found '$(peek(stream.input))'",
                           get_mark(stream)))
    end
    scan_line_break(stream)
end

function scan_anchor(stream::TokenStream, tokentype)
    start_mark = get_mark(stream)
    indicator = peek(stream.input)
    if indicator == '*'
        name = "alias"
    else
        name = "anchor"
    end
    forwardchars!(stream)
    length = 0
    c = peek(stream.input)
    while isletter(c) || isnumeric(c) || c == '-' || c == '_'
        length += 1
        c = peek(stream.input, length)
    end

    if length == 0
        throw(ScannerError("while scanning an $(name)", start_mark,
                           "expected an alphanumeric character, but found '$(peek(stream.input))'",
                           get_mark(stream)))
    end
    value = prefix(stream.input, length)
    forwardchars!(stream, length)
    if !in(peek(stream.input), "\0 \t\r\n\u0085\u2028\u2029?:,]}%@`")
        throw(ScannerError("while scanning an $(name)", start_mark,
                           "expected an alphanumeric character, but found '$(peek(stream.input))'",
                           get_mark(stream)))
    end
    end_mark = get_mark(stream)
    tokentype(Span(start_mark, end_mark), value)
end

function scan_tag(stream::TokenStream)
    start_mark = get_mark(stream)
    c = peek(stream.input, 1)
    if c == '<'
        handle = nothing
        forwardchars!(stream, 2)
        suffix = scan_tag_uri(stream, "tag", start_mark)
        if peek(stream.input) != '>'
            throw(ScannerError("while parsing a tag", start_mark,
                               "expected '>', but found '$(peek(stream.input))'",
                               get_mark(stream)))
        end
        forwardchars!(stream)
    elseif in(c, "\0 \t\r\n\u0085\u2028\u2029")
        handle = nothing
        suffix = '!'
        forwardchars!(stream)
    else
        length = 1
        use_handle = false
        while !in(c, "\0 \r\n\u0085\u2028\u2029")
            if c == '!'
                use_handle = true
                break
            end
            length += 1
            c = peek(stream.input, length)
        end
        if use_handle
            handle = scan_tag_handle(stream, "tag", start_mark)
        else
            handle = "!"
            forwardchars!(stream)
        end
        suffix = scan_tag_uri(stream, "tag", start_mark)
    end

    c = peek(stream.input)
    if !in(c, "\0 \r\n\u0085\u2028\u2029")
        throw(ScannerError("while scanning a tag", start_mark,
                           "expected ' ' or a line break, but found '$(c)'",
                           get_mark(stream)))
    end

    value = (handle, suffix)
    end_mark = get_mark(stream)
    TagToken(Span(start_mark, end_mark), value)
end

function scan_block_scalar(stream::TokenStream, style::Char)
    folded = style == '>'

    chunks = Any[]
    start_mark = get_mark(stream)

    # Scan the header.
    forwardchars!(stream)
    chomping, increment = scan_block_scalar_indicators(stream, start_mark)
    scan_block_scalar_ignored_line(stream, start_mark)

    # Determine the indentation level and go to the first non-empty line.
    min_indent = max(1, stream.indent + 1)
    if increment === nothing
        breaks, max_indent, end_mark = scan_block_scalar_indentation(stream)
        indent = max(min_indent, max_indent)
    else
        indent = min_indent + increment - 1
        breaks, end_mark = scan_block_scalar_breaks(stream, indent)
    end
    line_break = ""

    # Scan the inner part of the block scalar.
    while stream.column == indent && peek(stream.input) != '\0'
        append!(chunks, breaks)
        leading_non_space = peek(stream.input) != ' ' && peek(stream.input) != '\t'
        length = 0
        while !in(peek(stream.input, length), "\0\r\n\u0085\u2028\u2029")
            length += 1
        end
        push!(chunks, prefix(stream.input, length))
        forwardchars!(stream, length)
        line_break = scan_line_break(stream)
        breaks, end_mark = scan_block_scalar_breaks(stream, indent)
        if stream.column == indent && peek(stream.input) != '\0'
            if folded && line_break == "\n" &&
               leading_non_space && !in(peek(stream.input), " \t")
                if isempty(breaks)
                    push!(chunks, ' ')
                end
            else
                push!(chunks, line_break)
            end
        else
            break
        end
    end

    # Chomp the tail.
    if chomping != false
        push!(chunks, line_break)
    end
    if chomping == true
        append!(chunks, breaks)
    end

    ScalarToken(Span(start_mark, end_mark), string(chunks...), false, style)
end

function scan_block_scalar_ignored_line(stream::TokenStream, start_mark::Mark)
    while peek(stream.input) == ' '
        forwardchars!(stream)
    end

    if peek(stream.input) == '#'
        while !in(peek(stream.input), "\0\r\n\u0085\u2028\u2029")
            forwardchars!(stream)
        end
    end

    if !in(peek(stream.input), "\0\r\n\u0085\u2028\u2029")
        throw(ScannerError("while scanning a block scalal", start_mark,
                           "expected a comment or a line break, but found '$(peek(stream.input))'",
                           get_mark(stream)))
    end

    scan_line_break(stream)
end

function scan_block_scalar_indicators(stream::TokenStream, start_mark::Mark)
    chomping = nothing
    increment = nothing
    c = peek(stream.input)
    if c == '+' || c == '-'
        chomping = c == '+'
        forwardchars!(stream)
        c = peek(stream.input)
        if in(c, "0123456789")
            increment = parse(Int, string(c))
            if increment == 0
                throw(ScannerError("while scanning a block scalar", start_mark,
                    "expected indentation indicator in the range 1-9, but found 0",
                    get_mark(stream)))
            end
        end
    elseif in(c, "0123456789")
        increment = parse(Int, string(c))
        if increment == 0
            throw(ScannerError("while scanning a block scalar", start_mark,
                "expected indentation indicator in the range 1-9, but found 0",
                get_mark(stream)))
        end
        forwardchars!(stream)

        c = peek(stream.input)
        if c == '+' || c == '-'
            comping = c == '+'
            forwardchars!(stream)
        end
    end

    c = peek(stream.input)
    if !in(c, "\0 \r\n\u0085\u2028\u2029")
        throw(ScannerError("while scanning a block scalar", start_mark,
            "expected chomping or indentation indicators, but found '$(c)'",
            get_mark(stream)))
    end

    chomping, increment
end

function scan_block_scalar_indentation(stream::TokenStream)
    chunks = Any[]
    max_indent = 0
    end_mark = get_mark(stream)
    while in(peek(stream.input), " \r\n\u0085\u2028\u2029")
        if peek(stream.input) != ' '
            push!(chunks, scan_line_break(stream))
            end_mark = get_mark(stream)
        else
            forwardchars!(stream)
            if stream.column > max_indent
                max_indent = stream.column
            end
        end
    end

    chunks, max_indent, end_mark
end

function scan_block_scalar_breaks(stream::TokenStream, indent)
    chunks = Any[]
    end_mark = get_mark(stream)
    while stream.column < indent && peek(stream.input) == ' '
        forwardchars!(stream)
    end

    while in(peek(stream.input), "\r\n\u0085\u2028\u2029")
        push!(chunks, scan_line_break(stream))
        end_mark = get_mark(stream)
        while stream.column < indent && peek(stream.input) == ' '
            forwardchars!(stream)
        end
    end

    chunks, end_mark
end

function scan_flow_scalar(stream::TokenStream, style::Char)
    double = style == '"'
    chunks = Any[]
    start_mark = get_mark(stream)
    q = peek(stream.input) # quote
    forwardchars!(stream)
    while peek(stream.input) != q
        append!(chunks, scan_flow_scalar_spaces(stream, double, start_mark))
        append!(chunks, scan_flow_scalar_non_spaces(stream, double, start_mark))
    end
    forwardchars!(stream)
    end_mark = get_mark(stream)
    ScalarToken(Span(start_mark, end_mark), string(chunks...), false, style)
end

const ESCAPE_REPLACEMENTS = Dict{Char,Char}(
    '0'  => '\0',
    'a'  => '\u0007',
    'b'  => '\u0008',
    't'  => '\u0009',
    '\t' => '\u0009',
    'n'  => '\u000a',
    'v'  => '\u000b',
    'f'  => '\u000c',
    'r'  => '\u000d',
    'e'  => '\u001b',
    ' '  => '\u0020',
    '"'  => '"',
    '\\' => '\\',
    'N'  => '\u0085',
    '_' => '\u00A0',
    'L'  => '\u2028',
    'P'  => '\u2029'
)

const ESCAPE_CODES = Dict{Char, Int}(
    'x' => 2,
    'u' => 4,
    'U' => 8
)

function scan_flow_scalar_non_spaces(stream::TokenStream, double::Bool,
                                     start_mark::Mark)
    chunks = Any[]
    while true
        length = 0
        while !in(peek(stream.input, length), "\'\"\\\0 \t\r\n\u0085\u2028\u2029")
            length += 1
        end
        if length > 0
            push!(chunks, prefix(stream.input, length))
            forwardchars!(stream, length)
        end

        c = peek(stream.input)
        if !double && c == '\'' && peek(stream.input, 1) == '\''
            push!(chunks, '\'')
            forwardchars!(stream, 2)
        elseif (double && c == '\'') || (!double && in(c, "\"\\"))
            push!(chunks, c)
            forward!(stream.input)
        elseif double && c == '\\'
            forward!(stream.input)
            c = peek(stream.input)
            if haskey(ESCAPE_REPLACEMENTS, c)
                push!(chunks, ESCAPE_REPLACEMENTS[c])
                forward!(stream.input)
            elseif haskey(ESCAPE_CODES, c)
                length = ESCAPE_CODES[c]
                forward!(stream.input)
                for k in 0:(length-1)
                    c = peek(stream.input, k)
                    if !in(peek(stream.input, k), "0123456789ABCDEFabcdef")
                        throw(ScannerError("while scanning a double-quoted scalar",
                                           start_mark,
                                           string("expected escape sequence of",
                                                  " $(length) hexadecimal",
                                                  "digits, but found '$(c)'"),
                                           get_mark(stream)))
                    end
                end
                push!(chunks, Char(parse(Int, prefix(stream.input, length), base = 16)))
                forwardchars!(stream, length)
            elseif in(c, "\r\n\u0085\u2028\u2029")
                scan_line_break(stream)
                append!(chunks, scan_flow_scalar_breaks(stream, double, start_mark))
            else
                throw(ScannerError("while scanning a double-quoted scalar",
                                   start_mark,
                                   "found unknown escape character '$(c)'",
                                   get_mark(stream)))
            end
        else
            return chunks
        end
    end
end

function scan_flow_scalar_spaces(stream::TokenStream, double::Bool,
                                 start_mark::Mark)
    chunks = Any[]
    length = 0
    while in(peek(stream.input, length), " \t")
        length += 1
    end
    whitespaces = prefix(stream.input, length)
    forwardchars!(stream, length)

    c = peek(stream.input)
    if c == '\0'
        throw(ScannerError("while scanning a quoted scalar", start_mark,
                           "found unexpected end of stream", get_mark(stream)))
    elseif in(c, "\r\n\u0085\u2028\u2029")
        line_break = scan_line_break(stream)
        breaks = scan_flow_scalar_breaks(stream, double, start_mark)
        if line_break != '\n'
            push!(chunks, line_break)
        else isempty(breaks)
            push!(chunks, ' ')
        end
        append!(chunks, breaks)
    else
        push!(chunks, whitespaces)
    end

    chunks
end

function scan_flow_scalar_breaks(stream::TokenStream, double::Bool,
                                 start_mark::Mark)
    chunks = Any[]
    while true
        pref = prefix(stream.input, 3)
        if pref == "---" || pref == "..." &&
           in(peek(stream.input, 3), "\0 \t\r\n\u0085\u2028\u2029")
            throw(ScannerError("while scanning a quoted scalar", start_mark,
                               "found unexpected document seperator",
                               get_mark(stream)))
        end

        while in(peek(stream.input), " \t")
            forward!(stream.input)
        end

        if in(peek(stream.input), "\r\n\u0085\u2028\u2029")
            push!(chunks, scan_line_break(stream))
        else
            return chunks
        end
    end
end

function scan_plain(stream::TokenStream)
    # See the specification for details.
    # We add an additional restriction for the flow context:
    #   plain scalars in the flow context cannot contain ',', ':' and '?'.
    # We also keep track of the `allow_simple_key` flag here.
    # Indentation rules are loosed for the flow context.
    chunks = Any[]
    start_mark = get_mark(stream)
    end_mark = start_mark
    indent = stream.indent + 1

    # We allow zero indentation for scalars, but then we need to check for
    # document separators at the beginning of the line.
    #if indent == 0:
    #    indent = 1
    spaces = Any[]
    while true
        length = 0
        if peek(stream.input) == '#'
            break
        end

        while true
            c = peek(stream.input, length)
            cnext = peek(stream.input, length + 1)
            if in(c, whitespace) ||
                c === nothing ||
                (stream.flow_level == 0 && c == ':' &&
                    (cnext === nothing || in(cnext, whitespace))) ||
                (stream.flow_level != 0 && in(c, ",:?[]{}"))
                break
            end
            length += 1
        end

        # It's not clear what we should do with ':' in the flow context.
        c = peek(stream.input)
        if stream.flow_level != 0 && c == ':' &&
            !in(peek(stream.input, length + 1), "\0 \t\r\n\0u0085\u2028\u2029,[]{}")
            forwardchars!(stream, length)
            throw(ScannerError("while scanning a plain scalar", start_mark,
                               "found unexpected ':'", get_mark(stream)))
        end

        if length == 0
            break
        end

        stream.allow_simple_key = true
        append!(chunks, spaces)
        push!(chunks, prefix(stream.input, length))
        forwardchars!(stream, length)
        end_mark = get_mark(stream)
        spaces = scan_plain_spaces(stream, indent, start_mark)
        if isempty(spaces) || peek(stream.input) == '#' ||
            (stream.flow_level == 0 && stream.column < indent)
            break
        end
    end

    ScalarToken(Span(start_mark, end_mark), string(chunks...), true, nothing)
end

function scan_plain_spaces(stream::TokenStream, indent::Integer,
                           start_mark::Mark)
    chunks = Any[]
    length = 0
    while peek(stream.input, length) == ' '
        length += 1
    end

    whitespaces = prefix(stream.input, length)
    forwardchars!(stream, length)
    c = peek(stream.input)
    if in(c, "\r\n\u0085\u2028\u2029")
        line_break = scan_line_break(stream)
        stream.allow_simple_key = true
        pref = prefix(stream.input, 3)
        if pref == "---" || pref == "..." &&
            in(peek(stream.input, 3), "\0 \t\r\n\u0085\u2028\u2029")
            return Any[]
        end

        breaks = Any[]
        while in(peek(stream.input), " \r\n\u0085\u2028\u2029")
            if peek(stream.input) == ' '
                forwardchars!(stream)
            else
                push!(breaks, scan_line_break(stream))
                pref = prefix(stream.input, 3)
                if pref == "---" || pref == "..." &&
                    in(peek(stream.input, 3), "\0 \t\r\n\u0085\u2028\u2029")
                    return Any[]
                end
            end
        end

        if line_break != '\n'
            push!(chunks, line_break)
        elseif isempty(breaks)
            push!(chunks, ' ')
        end
    elseif !isempty(whitespaces)
        push!(chunks, whitespaces)
    end

    chunks
end

function scan_tag_handle(stream::TokenStream, name::String, start_mark::Mark)
    c = peek(stream.input)
    if c != '!'
        throw(ScannerError("while scanning a $(name)", start_mark,
                           "expected '!', but found '$(c)'", get_mark(stream)))
    end
    length = 1
    c = peek(stream.input, length)
    if c != ' '
        while isletter(c) || isnumeric(c) || c == '-' || c == '_'
            length += 1
            c = peek(stream.input, length)
        end

        if c != '!'
            forwardchars!(stream, length)
            throw(ScannerError("while scanning a $(name)", start_mark,
                               "expected '!', but found '$(c)'",
                               get_mark(stream)))
        end
        length += 1
    end

    value = prefix(stream.input, length)
    forwardchars!(stream, length)
    value
end

function scan_tag_uri(stream::TokenStream, name::String, start_mark::Mark)
    chunks = Any[]
    length = 0
    c = peek(stream.input, length)
    while isletter(c) || isnumeric(c) || in(c, "-;/?:@&=+\$,_.!~*\'()[]%")
        if c == '%'
            push!(chunks, prefix(stream.input, length))
            forwardchars!(stream, length)
            length = 0
            push!(chunks, scan_uri_escapes(stream, name, start_mark))
        else
            length += 1
        end
        c = peek(stream.input, length)
    end

    if length > 0
        push!(chunks, prefix(stream.input, length))
        forwardchars!(stream, length)
        length = 0
    end

    if isempty(chunks)
        throw(ScannerError("while parsing a $(name)", start_mark,
                           "expected URI, but found '$(c)'",
                           get_mark(stream)))
    end

    string(chunks...)
end

function scan_uri_escapes(stream::TokenStream, name::String, start_mark::Mark)
    bytes = Any[]
    mark = get_mark(stream)
    while peek(stream.input) == '%'
        forward!(stream.input)
        for k in 0:1
            if !in(peek(stream.input, k), "0123456789ABCDEFabcdef")
                throw(ScannerError("while scanning a $(name)", start_mark,
                                   string("expected URI escape sequence of",
                                          " 2 hexadecimal digits, but found",
                                          " '$(peek(stream.input, k))'"),
                                   get_mark(stream)))
            end
        end
        push!(bytes, char(parse_hex(prefix(stream.input, 2))))
        forwardchars!(stream, 2)
    end

    string(bytes...)
end


text:
push!(LOAD_PATH, joinpath(@__DIR__, "../.."))

using BandwidthBenchmark
using UnicodePlots

Threads.@threads :static for i in 1:Threads.nthreads()
    println("Thread $i running on core $(BandwidthBenchmark.get_core_id())")
end
println()

title = length(ARGS) > 0 ? join(ARGS, " ") : nothing

data = BandwidthBenchmark.flopscaling()
p = lineplot(data[:,1], data[:,2], title = title, xlabel = "# cores", ylabel = "MFlops/s", border = :ascii, canvas = AsciiCanvas)
print(stdout, p)

max_stars_repo_name: carstenbauer/BandwidthBenchmark

max_issues_repo_name: carstenbauer/BandwidthBenchmark

max_forks_repo_name: carstenbauer/BandwidthBenchmark


text:
module EquationsOfStateOfSolids

using Unitful: AbstractQuantity, NoUnits, ħ, me

const FERMI_GAS_CONSTANT = (3π^2)^(2 / 3) * ħ^2 / 5 / me

# See https://discourse.julialang.org/t/is-there-a-way-to-include-in-function-name/45378/3
abstract type Power end
struct TwoThirds <: Power end
struct OneThird <: Power end
struct FiveHalves <: Power end
struct ThreeHalves <: Power end

const _⅔ = TwoThirds()
const _⅓ = OneThird()
const _2½ = FiveHalves()
const _1½ = ThreeHalves()

Base.:(^)(x, ::TwoThirds) = x^(2 // 3)
Base.:(^)(x::Union{Complex,AbstractQuantity{<:Complex}}, ::TwoThirds) = x^(2 / 3)
Base.:(^)(x::Union{Real,AbstractQuantity{<:Real}}, ::TwoThirds) =
    _isnegative(x) ? complex(x)^(2 / 3) : x^(2 / 3)
Base.:(^)(x, ::OneThird) = x^(1 // 3)
Base.:(^)(x::Union{Complex,AbstractQuantity{<:Complex}}, ::OneThird) = x^(1 / 3)
Base.:(^)(x::Union{Real,AbstractQuantity{<:Real}}, ::OneThird) =
    _isnegative(x) ? complex(x)^(1 / 3) : x^(1 / 3)
Base.:(^)(x, ::FiveHalves) = x^(5 // 2)
Base.:(^)(x::Union{Complex,AbstractQuantity{<:Complex}}, ::FiveHalves) = sqrt(x^5)
Base.:(^)(x::Union{Real,AbstractQuantity{<:Real}}, ::FiveHalves) =
    _isnegative(x) ? sqrt(complex(x^5)) : sqrt(x^5)
Base.:(^)(x, ::ThreeHalves) = x^(3 // 2)
Base.:(^)(x::Union{Complex,AbstractQuantity{<:Complex}}, ::ThreeHalves) = sqrt(x^3)
Base.:(^)(x::Union{Real,AbstractQuantity{<:Real}}, ::ThreeHalves) =
    _isnegative(x) ? sqrt(complex(x^3)) : sqrt(x^3)

_isnegative(x) = x < zero(x)  # Do not export!

include("FiniteStrains.jl")
include("collections/collections.jl")
include("vsolve.jl")
include("Fitting.jl")

end


text:
# Begin by importing RTS-96 data as with previous project.

using MAT

type powerSystemData
    Sb
    f
    t
    r
    x
    b
    Y
    bustype
    Gp
    Gq
    Dp
    Dq
    Rp
    Rq
    Pmax
    Pmin
    Qmax
    Qmin
    Plim
    Vg
    Vceiling
    Vfloor
    busIdx
    N
    Nr
    Ng
    k
end

function createY(f,t,r,x,b,s)
    # Create an admittance matrix from three vectors: from, to, and adm. value
    # Note: 'f' and 't' must be integer vectors.
    # DC if s == true

    if s == true
        y = 1./x
        return sparse([f; t; t; f],[t; f; t; f],[-y; -y; y; y])
    else
        G = 1./r
        G[G.==Inf] = 0
        B = 1./x
        y = complex(G,B)
        return sparse([f; t; t; f],[t; f; t; f],[-y; -y; y + b./2; y + b./2])
    end
end

function unpack_psDL(psDL)
# code used to unpack psDL type instance:
return (psDL.Sb,
    psDL.f,
    psDL.t,
    psDL.r,
    psDL.x,
    psDL.b,
    psDL.Y,
    psDL.bustype,
    psDL.Gp,
    psDL.Gq,
    psDL.Dp,
    psDL.Dq,
    psDL.Rp,
    psDL.Rq,
    psDL.Pmax,
    psDL.Pmin,
    psDL.Qmax,
    psDL.Qmin,
    psDL.Plim,
    psDL.Vg,
    psDL.Vceiling,
    psDL.Vfloor,
    psDL.busIdx,
    psDL.N,
    psDL.Nr,
    psDL.Ng,
    psDL.k)
end

include("readRTS96Data.jl")
# psData = psDataLoad()