text:
function layoutable(::Type{IntervalSlider}, fig_or_scene; bbox = nothing, kwargs...)

    topscene = get_topscene(fig_or_scene)

    default_attrs = default_attributes(IntervalSlider, topscene).attributes
    theme_attrs = subtheme(topscene, :IntervalSlider)
    attrs = merge!(merge!(Attributes(kwargs), theme_attrs), default_attrs)

    decorations = Dict{Symbol, Any}()

    @extract attrs (
        halign, valign, horizontal, linewidth, snap,
        startvalues, interval, color_active, color_active_dimmed, color_inactive
    )

    sliderrange = attrs.range

    protrusions = Node(GridLayoutBase.RectSides{Float32}(0, 0, 0, 0))
    layoutobservables = LayoutObservables{IntervalSlider}(attrs.width, attrs.height, attrs.tellwidth, attrs.tellheight,
        halign, valign, attrs.alignmode; suggestedbbox = bbox, protrusions = protrusions)

    onany(linewidth, horizontal) do lw, horizontal
        if horizontal
            layoutobservables.autosize[] = (nothing, Float32(lw))
        else
            layoutobservables.autosize[] = (Float32(lw), nothing)
        end
    end

    sliderbox = lift(identity, layoutobservables.computedbbox)

    endpoints = lift(sliderbox, horizontal) do bb, horizontal

        h = height(bb)
        w = width(bb)

        if horizontal
            y = bottom(bb) + h / 2
            [Point2f(left(bb) + h/2, y),
             Point2f(right(bb) - h/2, y)]
        else
            x = left(bb) + w / 2
            [Point2f(x, bottom(bb) + w/2),
             Point2f(x, top(bb) - w/2)]
        end
    end

    # this is the index of the selected value in the slider's range
    # selected_index = Node(1)
    # add the selected index to the attributes so it can be manipulated later
    attrs.selected_indices = (1, 1)
    selected_indices = attrs.selected_indices

    # the fraction on the slider corresponding to the selected_indices
    # this is only used after dragging
    sliderfractions = lift(selected_indices, sliderrange) do is, r
        map(is) do i
            (i - 1) / (length(r) - 1)
        end
    end

    dragging = Node(false)

    # what the slider actually displays currently (also during dragging when
    # the slider position is in an "invalid" position given the slider's range)
    displayed_sliderfractions = Node((0.0, 0.0))

    on(sliderfractions) do fracs
        # only update displayed fraction through sliderfraction if not dragging
        # dragging overrides the value so there is clear mouse interaction
        if !dragging[]
            displayed_sliderfractions[] = fracs
        end
    end

    # when the range is changed, switch to closest interval
    on(sliderrange) do rng
        selected_indices[] = closest_index.(Ref(rng), interval[])
    end

    on(selected_indices) do is
        interval[] = getindex.(Ref(sliderrange[]), is)
    end

    # initialize slider value with closest from range
    selected_indices[] = if startvalues[] === Makie.automatic
        (1, lastindex(sliderrange[]))
    else
        closest_index.(Ref(sliderrange[]), startvalues[])
    end

    middlepoints = lift(endpoints, displayed_sliderfractions) do ep, sfs
        [Point2f(ep[1] .+ sf .* (ep[2] .- ep[1])) for sf in sfs]
    end

    linepoints = lift(endpoints, middlepoints) do eps, middles
        [eps[1], middles[1], middles[1], middles[2], middles[2], eps[2]]
    end

    linecolors = lift(color_active_dimmed, color_inactive) do ca, ci
        [ci, ca, ci]
    end

    endbuttoncolors = lift(color_active_dimmed, color_inactive) do ca, ci
        [ci, ci]
    end

    endbuttons = scatter!(topscene, endpoints, color = endbuttoncolors,
        markersize = linewidth, strokewidth = 0, raw = true, inspectable = false)
    decorations[:endbuttons] = endbuttons

    linesegs = linesegments!(topscene, linepoints, color = linecolors,
        linewidth = linewidth, raw = true, inspectable = false)
    decorations[:linesegments] = linesegs

    state = Node(:none)
    button_magnifications = lift(state) do state
        if state == :none
            [1.0, 1.0]
        elseif state == :min
            [1.25, 1.0]
        elseif state == :both
            [1.25, 1.25]
        else
            [1.0, 1.25]
        end
    end
    buttonsizes = @lift($linewidth .* $button_magnifications)
    buttons = scatter!(topscene, middlepoints, color = color_active, strokewidth = 0,
        markersize = buttonsizes, raw = true, inspectable = false)
    decorations[:buttons] = buttons

    mouseevents = addmouseevents!(topscene, layoutobservables.computedbbox)

    # we need to record where a drag started for the case where the center of the
    # range is shifted, because the difference in indices always needs to stay the same
    # and the slider is moved relative to this start position
    startfraction = Ref(0.0)
    start_disp_fractions = Ref((0.0, 0.0))
    startindices = Ref((1, 1))

    onmouseleftdrag(mouseevents) do event

        dragging[] = true
        fraction = if horizontal[]
            (event.px[1] - endpoints[][1][1]) / (endpoints[][2][1] - endpoints[][1][1])
        else
            (event.px[2] - endpoints[][1][2]) / (endpoints[][2][2] - endpoints[][1][2])
        end
        fraction = clamp(fraction, 0, 1)

        if state[] in (:min, :max)
            if snap[]
                snapindex = closest_fractionindex(sliderrange[], fraction)
                fraction = (snapindex - 1) / (length(sliderrange[]) - 1)
            end
            if state[] == :min
                # if the mouse crosses over the current max, reverse
                if fraction > displayed_sliderfractions[][2]
                    state[] = :max
                    displayed_sliderfractions[] = (displayed_sliderfractions[][2], fraction)
                else
                    displayed_sliderfractions[] = (fraction, displayed_sliderfractions[][2])
                end
            else
                # if the mouse crosses over the current min, reverse
                if fraction < displayed_sliderfractions[][1]
                    state[] = :min
                    displayed_sliderfractions[] = (fraction, displayed_sliderfractions[][1])
                else
                    displayed_sliderfractions[] = (displayed_sliderfractions[][1], fraction)
                end
            end
            newindices = closest_fractionindex.(Ref(sliderrange[]), displayed_sliderfractions[])

            if selected_indices[] != newindices
                selected_indices[] = newindices
            end
        elseif state[] == :both
            fracdif = fraction - startfraction[]

            clamped_fracdif = clamp(fracdif, -start_disp_fractions[][1], 1 - start_disp_fractions[][2])

            ntarget = round(Int, length(sliderrange[]) * clamped_fracdif)

            nlow = -startindices[][1] + 1
            nhigh = length(sliderrange[]) - startindices[][2]
            nchange = clamp(ntarget, nlow, nhigh)

            newindices = startindices[] .+ nchange

            displayed_sliderfractions[] = if snap[]
                (newindices .- 1) ./ (length(sliderrange[]) - 1)
            else
                start_disp_fractions[] .+ clamped_fracdif
            end

            if selected_indices[] != newindices
                selected_indices[] = newindices
            end
        end

        return Consume(true)
    end

    onmouseleftdragstop(mouseevents) do event
        dragging[] = false
        # adjust slider to closest legal value
        sliderfractions[] = sliderfractions[]
        return Consume(true)
    end

    onmouseleftdown(mouseevents) do event

        pos = event.px

        dim = horizontal[] ? 1 : 2
        frac = clamp(
            (pos[dim] - endpoints[][1][dim]) / (endpoints[][2][dim] - endpoints[][1][dim]),
            0, 1
        )

        startfraction[] = frac
        startindices[] = selected_indices[]
        start_disp_fractions[] = displayed_sliderfractions[]

        if state[] in (:both, :none)
            return Consume(true)
        end

        newindex = closest_fractionindex(sliderrange[], frac)
        if abs(newindex - selected_indices[][1]) < abs(newindex - selected_indices[][2])
            selected_indices[] = (newindex, selected_indices[][2])
        else
            selected_indices[] = (selected_indices[][1], newindex)
        end
        # linecolors[] = [color_active[], color_inactive[]]

        return Consume(true)
    end

    onmouseleftdoubleclick(mouseevents) do event
        selected_indices[] = selected_indices[] = if startvalues[] === Makie.automatic
            (1, lastindex(sliderrange[]))
        else
            closest_index.(Ref(sliderrange[]), startvalues[])
        end

        return Consume(true)
    end

    onmouseover(mouseevents) do event
        fraction = if horizontal[]
            (event.px[1] - endpoints[][1][1]) / (endpoints[][2][1] - endpoints[][1][1])
        else
            (event.px[2] - endpoints[][1][2]) / (endpoints[][2][2] - endpoints[][1][2])
        end
        fraction = clamp(fraction, 0, 1)

        buttondistance = displayed_sliderfractions[][2] - displayed_sliderfractions[][1]

        state[] = if fraction < displayed_sliderfractions[][1] + 0.25 * buttondistance
            :min
        elseif fraction < displayed_sliderfractions[][1] + 0.75 * buttondistance
            :both
        else
            :max
        end

        return Consume(false)
    end

    onmouseout(mouseevents) do event
        state[] = :none
        return Consume(false)
    end

    # trigger autosize through linewidth for first layout
    linewidth[] = linewidth[]

    IntervalSlider(fig_or_scene, layoutobservables, attrs, decorations)
end

"""
Set the `slider` to the values in the slider's range that are closest to `v1` and `v2`, and return those values ordered min, max.
"""
function set_close_to!(intervalslider::IntervalSlider, v1, v2)
    mima = minmax(v1, v2)
    indices = closest_index.(Ref(intervalslider.range[]), mima)
    intervalslider.selected_indices[] = indices
    getindex.(Ref(intervalslider.range[]), indices)
end


text:
# Exercise 14-1
include("./wc.jl")
using .LineCount
a = linecount("./src/exercises/wc.jl")
# println(a)

# If in REPL mode, run the following:
# include("./src/exercises/wc.jl")
# using .LineCount
# linecount("./src/exercises/wc.jl")

# Exercise 14-2
function sed(str, rpl, file1, file2)
    try
        io1 = open(file1, "r")
        io2 = open(file2, "w")
        while !eof(io1)
            line = read(io1, String)
            newline = replace(line, str => rpl)
            write(io2, newline)
        end
        close(io1)
        close(io2)
    catch exc
        println("Oh no! : $exc")
    end
end

file1 = "./src/exercises/str.txt"
file2 = "./src/exercises/rpl.txt"
file3 = "not a file"
# sed("ab", "(new)", file1, file2)
# sed("ab", "(new)", file3, file2)

# Exercise 14-4
function printallfiles(dir, ext)
    n = length(ext)
    for (root, dirs, files) in walkdir(dir)
        #=
        println("Directories in $root")
        for dir in dirs
            println(joinpath(root, dir)) # path to directories
        end
        println("Files in $root")
        =#
        for file in files
            if file[end-n+1:end] == ext
                println(joinpath(root, file)) # path to files
            end
        end
    end
end

# printallfiles(".", ".txt")

ext: jl


text:
# This file is autogenerated by HDF5.jl's `gen/gen_wrappers.jl` and should not be editted.
#
# To add new bindings, define the binding in `gen/api_defs.jl`, re-run
# `gen/gen_wrappers.jl`, and commit the updated `src/api.jl`.

function h5_close()
    var"#status#" = ccall((:H5close, libhdf5), herr_t, ())
    var"#status#" < 0 && error("Error closing the HDF5 resources")
    return nothing
end

function h5_dont_atexit()
    var"#status#" = ccall((:H5dont_atexit, libhdf5), herr_t, ())
    var"#status#" < 0 && error("Error calling dont_atexit")
    return nothing
end

function h5_free_memory(buf)
    var"#status#" = ccall((:H5free_memory, libhdf5), herr_t, (Ptr{Cvoid},), buf)
    var"#status#" < 0 && error("Error freeing memory")
    return nothing
end

function h5_garbage_collect()
    var"#status#" = ccall((:H5garbage_collect, libhdf5), herr_t, ())
    var"#status#" < 0 && error("Error on garbage collect")
    return nothing
end

function h5_get_libversion(majnum, minnum, relnum)
    var"#status#" = ccall((:H5get_libversion, libhdf5), herr_t, (Ref{Cuint}, Ref{Cuint}, Ref{Cuint}), majnum, minnum, relnum)
    var"#status#" < 0 && error("Error getting HDF5 library version")
    return nothing
end

function h5_is_library_threadsafe(is_ts)
    var"#status#" = ccall((:H5is_library_threadsafe, libhdf5), herr_t, (Ref{Cuint},), is_ts)
    var"#status#" < 0 && error("Error determining thread safety")
    return nothing
end

function h5_open()
    var"#status#" = ccall((:H5open, libhdf5), herr_t, ())
    var"#status#" < 0 && error("Error initializing the HDF5 library")
    return nothing
end

function h5_set_free_list_limits(reg_global_lim, reg_list_lim, arr_global_lim, arr_list_lim, blk_global_lim, blk_list_lim)
    var"#status#" = ccall((:H5set_free_list_limits, libhdf5), herr_t, (Cint, Cint, Cint, Cint, Cint, Cint), reg_global_lim, reg_list_lim, arr_global_lim, arr_list_lim, blk_global_lim, blk_list_lim)
    var"#status#" < 0 && error("Error setting limits on free lists")
    return nothing
end

function h5a_close(id)
    var"#status#" = ccall((:H5Aclose, libhdf5), herr_t, (hid_t,), id)
    var"#status#" < 0 && error("Error closing attribute")
    return nothing
end

function h5a_create(loc_id, pathname, type_id, space_id, acpl_id, aapl_id)
    var"#status#" = ccall((:H5Acreate2, libhdf5), hid_t, (hid_t, Ptr{UInt8}, hid_t, hid_t, hid_t, hid_t), loc_id, pathname, type_id, space_id, acpl_id, aapl_id)
    var"#status#" < 0 && error("Error creating attribute ", h5a_get_name(loc_id), "/", pathname)
    return var"#status#"
end

function h5a_create_by_name(loc_id, obj_name, attr_name, type_id, space_id, acpl_id, aapl_id, lapl_id)
    var"#status#" = ccall((:H5Acreate_by_name, libhdf5), hid_t, (hid_t, Ptr{UInt8}, Ptr{UInt8}, hid_t, hid_t, hid_t, hid_t, hid_t), loc_id, obj_name, attr_name, type_id, space_id, acpl_id, aapl_id, lapl_id)
    var"#status#" < 0 && error("Error creating attribute ", attr_name, " for object ", obj_name)
    return var"#status#"
end

function h5a_delete(loc_id, attr_name)
    var"#status#" = ccall((:H5Adelete, libhdf5), herr_t, (hid_t, Ptr{UInt8}), loc_id, attr_name)
    var"#status#" < 0 && error("Error deleting attribute ", attr_name)
    return nothing
end

function h5a_delete_by_idx(loc_id, obj_name, idx_type, order, n, lapl_id)
    var"#status#" = ccall((:H5Adelete_by_idx, libhdf5), herr_t, (hid_t, Ptr{UInt8}, Cint, Cint, hsize_t, hid_t), loc_id, obj_name, idx_type, order, n, lapl_id)
    var"#status#" < 0 && error("Error deleting attribute ", n, " from object ", obj_name)
    return nothing
end

function h5a_delete_by_name(loc_id, obj_name, attr_name, lapl_id)
    var"#status#" = ccall((:H5Adelete_by_name, libhdf5), herr_t, (hid_t, Ptr{UInt8}, Ptr{UInt8}, hid_t), loc_id, obj_name, attr_name, lapl_id)
    var"#status#" < 0 && error("Error removing attribute ", attr_name, " from object ", obj_name)
    return nothing
end

function h5a_exists(obj_id, attr_name)
    var"#status#" = ccall((:H5Aexists, libhdf5), htri_t, (hid_t, Ptr{UInt8}), obj_id, attr_name)
    var"#status#" < 0 && error("Error checking whether attribute ", attr_name, " exists")
    return var"#status#" > 0
end

function h5a_exists_by_name(loc_id, obj_name, attr_name, lapl_id)
    var"#status#" = ccall((:H5Aexists_by_name, libhdf5), htri_t, (hid_t, Ptr{UInt8}, Ptr{UInt8}, hid_t), loc_id, obj_name, attr_name, lapl_id)
    var"#status#" < 0 && error("Error checking whether object ", obj_name, " has attribute ", attr_name)
    return var"#status#" > 0
end

function h5a_get_create_plist(attr_id)
    var"#status#" = ccall((:H5Aget_create_plist, libhdf5), hid_t, (hid_t,), attr_id)
    var"#status#" < 0 && error("Cannot get creation property list")
    return var"#status#"
end

function h5a_get_name(attr_id, buf_size, buf)
    var"#status#" = ccall((:H5Aget_name, libhdf5), Cssize_t, (hid_t, Csize_t, Ptr{UInt8}), attr_id, buf_size, buf)
    var"#status#" < 0 && error("Error getting attribute name")
    return var"#status#"
end

function h5a_get_name_by_idx(loc_id, obj_name, index_type, order, idx, name, size, lapl_id)
    var"#status#" = ccall((:H5Aget_name_by_idx, libhdf5), Cssize_t, (hid_t, Cstring, Cint, Cint, hsize_t, Ptr{UInt8}, Csize_t, hid_t), loc_id, obj_name, index_type, order, idx, name, size, lapl_id)
    var"#status#" < 0 && error("Error getting attribute name")
    return var"#status#"
end

function h5a_get_space(attr_id)
    var"#status#" = ccall((:H5Aget_space, libhdf5), hid_t, (hid_t,), attr_id)
    var"#status#" < 0 && error("Error getting attribute dataspace")
    return var"#status#"
end

function h5a_get_type(attr_id)
    var"#status#" = ccall((:H5Aget_type, libhdf5), hid_t, (hid_t,), attr_id)
    var"#status#" < 0 && error("Error getting attribute type")
    return var"#status#"
end

function h5a_open(obj_id, pathname, aapl_id)
    var"#status#" = ccall((:H5Aopen, libhdf5), hid_t, (hid_t, Ptr{UInt8}, hid_t), obj_id, pathname, aapl_id)
    var"#status#" < 0 && error("Error opening attribute ", h5i_get_name(obj_id), "/", pathname)
    return var"#status#"
end

function h5a_read(attr_id, mem_type_id, buf)
    var"#status#" = ccall((:H5Aread, libhdf5), herr_t, (hid_t, hid_t, Ptr{Cvoid}), attr_id, mem_type_id, buf)
    var"#status#" < 0 && error("Error reading attribute ", h5a_get_name(attr_id))
    return nothing
end

function h5a_write(attr_hid, mem_type_id, buf)
    var"#status#" = ccall((:H5Awrite, libhdf5), herr_t, (hid_t, hid_t, Ptr{Cvoid}), attr_hid, mem_type_id, buf)
    var"#status#" < 0 && error("Error writing attribute data")
    return nothing
end

function h5d_close(dataset_id)
    var"#status#" = ccall((:H5Dclose, libhdf5), herr_t, (hid_t,), dataset_id)
    var"#status#" < 0 && error("Error closing dataset")
    return nothing
end

function h5d_create(loc_id, pathname, dtype_id, space_id, lcpl_id, dcpl_id, dapl_id)
    var"#status#" = ccall((:H5Dcreate2, libhdf5), hid_t, (hid_t, Ptr{UInt8}, hid_t, hid_t, hid_t, hid_t, hid_t), loc_id, pathname, dtype_id, space_id, lcpl_id, dcpl_id, dapl_id)
    var"#status#" < 0 && error("Error creating dataset ", h5i_get_name(loc_id), "/", pathname)
    return var"#status#"
end

function h5d_flush(dataset_id)
    var"#status#" = ccall((:H5Dflush, libhdf5), herr_t, (hid_t,), dataset_id)
    var"#status#" < 0 && error("Error flushing dataset")
    return nothing
end

function h5d_get_access_plist(dataset_id)
    var"#status#" = ccall((:H5Dget_access_plist, libhdf5), hid_t, (hid_t,), dataset_id)
    var"#status#" < 0 && error("Error getting dataset access property list")
    return var"#status#"
end

function h5d_get_create_plist(dataset_id)
    var"#status#" = ccall((:H5Dget_create_plist, libhdf5), hid_t, (hid_t,), dataset_id)
    var"#status#" < 0 && error("Error getting dataset create property list")
    return var"#status#"
end

function h5d_get_offset(dataset_id)
    var"#status#" = ccall((:H5Dget_offset, libhdf5), haddr_t, (hid_t,), dataset_id)
    var"#status#" == -1 % haddr_t && error("Error getting offset")
    return var"#status#"
end

function h5d_get_space(dataset_id)
    var"#status#" = ccall((:H5Dget_space, libhdf5), hid_t, (hid_t,), dataset_id)
    var"#status#" < 0 && error("Error getting dataspace")
    return var"#status#"
end

function h5d_get_type(dataset_id)
    var"#status#" = ccall((:H5Dget_type, libhdf5), hid_t, (hid_t,), dataset_id)
    var"#status#" < 0 && error("Error getting dataspace type")
    return var"#status#"
end

function h5d_open(loc_id, pathname, dapl_id)
    var"#status#" = ccall((:H5Dopen2, libhdf5), hid_t, (hid_t, Ptr{UInt8}, hid_t), loc_id, pathname, dapl_id)
    var"#status#" < 0 && error("Error opening dataset ", h5i_get_name(loc_id), "/", pathname)
    return var"#status#"
end

function h5d_read(dataset_id, mem_type_id, mem_space_id, file_space_id, xfer_plist_id, buf)
    var"#status#" = ccall((:H5Dread, libhdf5), herr_t, (hid_t, hid_t, hid_t, hid_t, hid_t, Ptr{Cvoid}), dataset_id, mem_type_id, mem_space_id, file_space_id, xfer_plist_id, buf)
    var"#status#" < 0 && error("Error reading dataset ", h5i_get_name(dataset_id))
    return nothing
end

function h5d_refresh(dataset_id)
    var"#status#" = ccall((:H5Drefresh, libhdf5), herr_t, (hid_t,), dataset_id)
    var"#status#" < 0 && error("Error refreshing dataset")
    return nothing
end

function h5d_set_extent(dataset_id, new_dims)
    var"#status#" = ccall((:H5Dset_extent, libhdf5), herr_t, (hid_t, Ptr{hsize_t}), dataset_id, new_dims)
    var"#status#" < 0 && error("Error extending dataset dimensions")
    return nothing
end

function h5d_vlen_get_buf_size(dset_id, type_id, space_id, buf)
    var"#status#" = ccall((:H5Dvlen_get_buf_size, libhdf5), herr_t, (hid_t, hid_t, hid_t, Ptr{hsize_t}), dset_id, type_id, space_id, buf)
    var"#status#" < 0 && error("Error getting vlen buffer size")
    return nothing
end

function h5d_vlen_reclaim(type_id, space_id, plist_id, buf)
    var"#status#" = ccall((:H5Dvlen_reclaim, libhdf5), herr_t, (hid_t, hid_t, hid_t, Ptr{Cvoid}), type_id, space_id, plist_id, buf)
    var"#status#" < 0 && error("Error reclaiming vlen buffer")
    return nothing
end

function h5d_write(dataset_id, mem_type_id, mem_space_id, file_space_id, xfer_plist_id, buf)
    var"#status#" = ccall((:H5Dwrite, libhdf5), herr_t, (hid_t, hid_t, hid_t, hid_t, hid_t, Ptr{Cvoid}), dataset_id, mem_type_id, mem_space_id, file_space_id, xfer_plist_id, buf)
    var"#status#" < 0 && error("Error writing dataset")
    return nothing
end

function h5e_get_auto(estack_id, func, client_data)
    var"#status#" = ccall((:H5Eget_auto2, libhdf5), herr_t, (hid_t, Ref{Ptr{Cvoid}}, Ref{Ptr{Cvoid}}), estack_id, func, client_data)
    var"#status#" < 0 && error("Error getting error reporting behavior")
    return nothing
end

function h5e_set_auto(estack_id, func, client_data)
    var"#status#" = ccall((:H5Eset_auto2, libhdf5), herr_t, (hid_t, Ptr{Cvoid}, Ptr{Cvoid}), estack_id, func, client_data)
    var"#status#" < 0 && error("Error setting error reporting behavior")
    return nothing
end

function h5f_close(file_id)
    var"#status#" = ccall((:H5Fclose, libhdf5), herr_t, (hid_t,), file_id)
    var"#status#" < 0 && error("Error closing file")
    return nothing
end

function h5f_create(pathname, flags, fcpl_id, fapl_id)
    var"#status#" = ccall((:H5Fcreate, libhdf5), hid_t, (Ptr{UInt8}, Cuint, hid_t, hid_t), pathname, flags, fcpl_id, fapl_id)
    var"#status#" < 0 && error("Error creating file ", pathname)
    return var"#status#"
end

function h5f_flush(object_id, scope)
    var"#status#" = ccall((:H5Fflush, libhdf5), herr_t, (hid_t, Cint), object_id, scope)
    var"#status#" < 0 && error("Error flushing object to file")
    return nothing
end

function h5f_get_access_plist(file_id)
    var"#status#" = ccall((:H5Fget_access_plist, libhdf5), hid_t, (hid_t,), file_id)
    var"#status#" < 0 && error("Error getting file access property list")
    return var"#status#"
end

function h5f_get_create_plist(file_id)
    var"#status#" = ccall((:H5Fget_create_plist, libhdf5), hid_t, (hid_t,), file_id)
    var"#status#" < 0 && error("Error getting file create property list")
    return var"#status#"
end

function h5f_get_intent(file_id, intent)
    var"#status#" = ccall((:H5Fget_intent, libhdf5), herr_t, (hid_t, Ptr{Cuint}), file_id, intent)
    var"#status#" < 0 && error("Error getting file intent")
    return nothing
end

function h5f_get_name(obj_id, buf, buf_size)
    var"#status#" = ccall((:H5Fget_name, libhdf5), Cssize_t, (hid_t, Ptr{UInt8}, Csize_t), obj_id, buf, buf_size)
    var"#status#" < 0 && error("Error getting file name")
    return var"#status#"
end

function h5f_get_obj_count(file_id, types)
    var"#status#" = ccall((:H5Fget_obj_count, libhdf5), Cssize_t, (hid_t, Cuint), file_id, types)
    var"#status#" < 0 && error("Error getting object count")
    return var"#status#"
end

function h5f_get_obj_ids(file_id, types, max_objs, obj_id_list)
    var"#status#" = ccall((:H5Fget_obj_ids, libhdf5), Cssize_t, (hid_t, Cuint, Csize_t, Ptr{hid_t}), file_id, types, max_objs, obj_id_list)
    var"#status#" < 0 && error("Error getting objects")
    return var"#status#"
end

function h5f_get_vfd_handle(file_id, fapl_id, file_handle)
    var"#status#" = ccall((:H5Fget_vfd_handle, libhdf5), herr_t, (hid_t, hid_t, Ref{Ptr{Cvoid}}), file_id, fapl_id, file_handle)
    var"#status#" < 0 && error("Error getting VFD handle")
    return nothing
end

function h5f_is_hdf5(pathname)
    var"#status#" = ccall((:H5Fis_hdf5, libhdf5), htri_t, (Cstring,), pathname)
    var"#status#" < 0 && error("Cannot access file ", pathname)
    return var"#status#" > 0
end

function h5f_open(pathname, flags, fapl_id)
    var"#status#" = ccall((:H5Fopen, libhdf5), hid_t, (Cstring, Cuint, hid_t), pathname, flags, fapl_id)
    var"#status#" < 0 && error("Error opening file ", pathname)
    return var"#status#"
end

function h5f_start_swmr_write(id)
    var"#status#" = ccall((:H5Fstart_swmr_write, libhdf5), herr_t, (hid_t,), id)
    var"#status#" < 0 && error("Error starting SWMR write")
    return nothing
end

function h5g_close(group_id)
    var"#status#" = ccall((:H5Gclose, libhdf5), herr_t, (hid_t,), group_id)
    var"#status#" < 0 && error("Error closing group")
    return nothing
end

function h5g_create(loc_id, pathname, lcpl_id, gcpl_id, gapl_id)
    var"#status#" = ccall((:H5Gcreate2, libhdf5), hid_t, (hid_t, Ptr{UInt8}, hid_t, hid_t, hid_t), loc_id, pathname, lcpl_id, gcpl_id, gapl_id)
    var"#status#" < 0 && error("Error creating group ", h5i_get_name(loc_id), "/", pathname)
    return var"#status#"
end

function h5g_get_create_plist(group_id)
    var"#status#" = ccall((:H5Gget_create_plist, libhdf5), hid_t, (hid_t,), group_id)
    var"#status#" < 0 && error("Error getting group create property list")
    return var"#status#"
end

function h5g_get_info(group_id, buf)
    var"#status#" = ccall((:H5Gget_info, libhdf5), herr_t, (hid_t, Ptr{H5G_info_t}), group_id, buf)
    var"#status#" < 0 && error("Error getting group info")
    return nothing
end

function h5g_get_num_objs(loc_id, num_obj)
    var"#status#" = ccall((:H5Gget_num_objs, libhdf5), hid_t, (hid_t, Ptr{hsize_t}), loc_id, num_obj)
    var"#status#" < 0 && error("Error getting group length")
    return var"#status#"
end

function h5g_get_objname_by_idx(loc_id, idx, pathname, size)
    var"#status#" = ccall((:H5Gget_objname_by_idx, libhdf5), Cssize_t, (hid_t, hsize_t, Ptr{UInt8}, Csize_t), loc_id, idx, pathname, size)
    var"#status#" < 0 && error("Error getting group object name ", h5i_get_name(loc_id), "/", pathname)
    return var"#status#"
end

function h5g_open(loc_id, pathname, gapl_id)
    var"#status#" = ccall((:H5Gopen2, libhdf5), hid_t, (hid_t, Ptr{UInt8}, hid_t), loc_id, pathname, gapl_id)
    var"#status#" < 0 && error("Error opening group ", h5i_get_name(loc_id), "/", pathname)
    return var"#status#"
end

function h5i_dec_ref(obj_id)
    var"#status#" = ccall((:H5Idec_ref, libhdf5), Cint, (hid_t,), obj_id)
    var"#status#" < 0 && error("Error decementing reference")
    return var"#status#"
end

function h5i_get_file_id(obj_id)
    var"#status#" = ccall((:H5Iget_file_id, libhdf5), hid_t, (hid_t,), obj_id)
    var"#status#" < 0 && error("Error getting file identifier")
    return var"#status#"
end

function h5i_get_name(obj_id, buf, buf_size)
    var"#status#" = ccall((:H5Iget_name, libhdf5), Cssize_t, (hid_t, Ptr{UInt8}, Csize_t), obj_id, buf, buf_size)
    var"#status#" < 0 && error("Error getting object name")
    return var"#status#"
end

function h5i_get_ref(obj_id)
    var"#status#" = ccall((:H5Iget_ref, libhdf5), Cint, (hid_t,), obj_id)
    var"#status#" < 0 && error("Error getting reference count")
    return var"#status#"
end

function h5i_get_type(obj_id)
    var"#status#" = ccall((:H5Iget_type, libhdf5), Cint, (hid_t,), obj_id)
    var"#status#" < 0 && error("Error getting type")
    return var"#status#"
end

function h5i_inc_ref(obj_id)
    var"#status#" = ccall((:H5Iinc_ref, libhdf5), Cint, (hid_t,), obj_id)
    var"#status#" < 0 && error("Error incrementing identifier refcount")
    return var"#status#"
end

function h5i_is_valid(obj_id)
    var"#status#" = ccall((:H5Iis_valid, libhdf5), htri_t, (hid_t,), obj_id)
    var"#status#" < 0 && error("Cannot determine whether object is valid")
    return var"#status#" > 0
end

function h5l_create_external(target_file_name, target_obj_name, link_loc_id, link_name, lcpl_id, lapl_id)
    var"#status#" = ccall((:H5Lcreate_external, libhdf5), herr_t, (Ptr{UInt8}, Ptr{UInt8}, hid_t, Ptr{UInt8}, hid_t, hid_t), target_file_name, target_obj_name, link_loc_id, link_name, lcpl_id, lapl_id)
    var"#status#" < 0 && error("Error creating external link ", link_name, " pointing to ", target_obj_name, " in file ", target_file_name)
    return nothing
end

function h5l_create_hard(obj_loc_id, obj_name, link_loc_id, link_name, lcpl_id, lapl_id)
    var"#status#" = ccall((:H5Lcreate_hard, libhdf5), herr_t, (hid_t, Ptr{UInt8}, hid_t, Ptr{UInt8}, hid_t, hid_t), obj_loc_id, obj_name, link_loc_id, link_name, lcpl_id, lapl_id)
    var"#status#" < 0 && error("Error creating hard link ", link_name, " pointing to ", obj_name)
    return nothing
end

function h5l_create_soft(target_path, link_loc_id, link_name, lcpl_id, lapl_id)
    var"#status#" = ccall((:H5Lcreate_soft, libhdf5), herr_t, (Ptr{UInt8}, hid_t, Ptr{UInt8}, hid_t, hid_t), target_path, link_loc_id, link_name, lcpl_id, lapl_id)
    var"#status#" < 0 && error("Error creating soft link ", link_name, " pointing to ", target_path)
    return nothing
end

function h5l_delete(obj_id, pathname, lapl_id)
    var"#status#" = ccall((:H5Ldelete, libhdf5), herr_t, (hid_t, Ptr{UInt8}, hid_t), obj_id, pathname, lapl_id)
    var"#status#" < 0 && error("Error deleting ", h5i_get_name(obj_id), "/", pathname)
    return nothing
end

function h5l_exists(loc_id, pathname, lapl_id)
    var"#status#" = ccall((:H5Lexists, libhdf5), htri_t, (hid_t, Ptr{UInt8}, hid_t), loc_id, pathname, lapl_id)
    var"#status#" < 0 && error("Cannot determine whether ", pathname, " exists")
    return var"#status#" > 0
end

function h5l_get_info(link_loc_id, link_name, link_buf, lapl_id)
    var"#status#" = ccall((:H5Lget_info, libhdf5), herr_t, (hid_t, Ptr{UInt8}, Ptr{H5L_info_t}, hid_t), link_loc_id, link_name, link_buf, lapl_id)
    var"#status#" < 0 && error("Error getting info for link ", link_name)
    return nothing
end

function h5l_get_name_by_idx(loc_id, group_name, index_field, order, n, name, size, lapl_id)
    var"#status#" = ccall((:H5Lget_name_by_idx, libhdf5), Cssize_t, (hid_t, Ptr{UInt8}, Cint, Cint, hsize_t, Ptr{UInt8}, Csize_t, hid_t), loc_id, group_name, index_field, order, n, name, size, lapl_id)
    var"#status#" < 0 && error("Error getting object name")
    return var"#status#"
end

function h5o_close(object_id)
    var"#status#" = ccall((:H5Oclose, libhdf5), herr_t, (hid_t,), object_id)
    var"#status#" < 0 && error("Error closing object")
    return nothing
end

function h5o_copy(src_loc_id, src_name, dst_loc_id, dst_name, ocpypl_id, lcpl_id)
    var"#status#" = ccall((:H5Ocopy, libhdf5), herr_t, (hid_t, Ptr{UInt8}, hid_t, Ptr{UInt8}, hid_t, hid_t), src_loc_id, src_name, dst_loc_id, dst_name, ocpypl_id, lcpl_id)
    var"#status#" < 0 && error("Error copying object ", h5i_get_name(src_loc_id), "/", src_name, " to ", h5i_get_name(dst_loc_id), "/", dst_name)
    return nothing
end

function h5o_get_info(object_id, buf)
    var"#status#" = ccall((:H5Oget_info1, libhdf5), herr_t, (hid_t, Ptr{H5O_info_t}), object_id, buf)
    var"#status#" < 0 && error("Error getting object info")
    return nothing
end

function h5o_open(loc_id, pathname, lapl_id)
    var"#status#" = ccall((:H5Oopen, libhdf5), hid_t, (hid_t, Ptr{UInt8}, hid_t), loc_id, pathname, lapl_id)
    var"#status#" < 0 && error("Error opening object ", h5i_get_name(loc_id), "/", pathname)
    return var"#status#"
end

function h5o_open_by_addr(loc_id, addr)
    var"#status#" = ccall((:H5Oopen_by_addr, libhdf5), hid_t, (hid_t, haddr_t), loc_id, addr)
    var"#status#" < 0 && error("Error opening object by address")
    return var"#status#"
end

function h5o_open_by_idx(loc_id, group_name, index_type, order, n, lapl_id)
    var"#status#" = ccall((:H5Oopen_by_idx, libhdf5), hid_t, (hid_t, Ptr{UInt8}, Cint, Cint, hsize_t, hid_t), loc_id, group_name, index_type, order, n, lapl_id)
    var"#status#" < 0 && error("Error opening object of index ", n)
    return var"#status#"
end

function h5p_close(id)
    var"#status#" = ccall((:H5Pclose, libhdf5), herr_t, (hid_t,), id)
    var"#status#" < 0 && error("Error closing property list")
    return nothing
end

function h5p_create(cls_id)
    var"#status#" = ccall((:H5Pcreate, libhdf5), hid_t, (hid_t,), cls_id)
    var"#status#" < 0 && error("Error creating property list")
    return var"#status#"
end

function h5p_get_alignment(fapl_id, threshold, alignment)
    var"#status#" = ccall((:H5Pget_alignment, libhdf5), herr_t, (hid_t, Ref{hsize_t}, Ref{hsize_t}), fapl_id, threshold, alignment)
    var"#status#" < 0 && error("Error getting alignment")
    return nothing
end

function h5p_get_alloc_time(plist_id, alloc_time)
    var"#status#" = ccall((:H5Pget_alloc_time, libhdf5), herr_t, (hid_t, Ptr{Cint}), plist_id, alloc_time)
    var"#status#" < 0 && error("Error getting allocation timing")
    return nothing
end

function h5p_get_char_encoding(plist_id, encoding)
    var"#status#" = ccall((:H5Pget_char_encoding, libhdf5), herr_t, (hid_t, Ref{Cint}), plist_id, encoding)
    var"#status#" < 0 && error("Error getting char encoding")
    return nothing
end

function h5p_get_chunk(plist_id, n_dims, dims)
    var"#status#" = ccall((:H5Pget_chunk, libhdf5), Cint, (hid_t, Cint, Ptr{hsize_t}), plist_id, n_dims, dims)
    var"#status#" < 0 && error("Error getting chunk size")
    return var"#status#"
end

function h5p_get_create_intermediate_group(lcpl_id, crt_intermed_group)
    var"#status#" = ccall((:H5Pget_create_intermediate_group, libhdf5), herr_t, (hid_t, Ref{Cuint}), lcpl_id, crt_intermed_group)
    var"#status#" < 0 && error("Error getting create intermediate group property")
    return nothing
end

function h5p_get_driver(plist_id)
    var"#status#" = ccall((:H5Pget_driver, libhdf5), hid_t, (hid_t,), plist_id)
    var"#status#" < 0 && error("Error getting driver identifier")
    return var"#status#"
end

function h5p_get_driver_info(plist_id)
    var"#status#" = ccall((:H5Pget_driver_info, libhdf5), Ptr{Cvoid}, (hid_t,), plist_id)
    return var"#status#"
end

function h5p_get_dxpl_mpio(dxpl_id, xfer_mode)
    var"#status#" = ccall((:H5Pget_dxpl_mpio, libhdf5), herr_t, (hid_t, Ptr{Cint}), dxpl_id, xfer_mode)
    var"#status#" < 0 && error("Error getting MPIO transfer mode")
    return nothing
end

function h5p_get_fapl_mpio32(fapl_id, comm, info)
    var"#status#" = ccall((:H5Pget_fapl_mpio, libhdf5), herr_t, (hid_t, Ptr{Hmpih32}, Ptr{Hmpih32}), fapl_id, comm, info)
    var"#status#" < 0 && error("Error getting MPIO properties")
    return nothing
end

function h5p_get_fapl_mpio64(fapl_id, comm, info)
    var"#status#" = ccall((:H5Pget_fapl_mpio, libhdf5), herr_t, (hid_t, Ptr{Hmpih64}, Ptr{Hmpih64}), fapl_id, comm, info)
    var"#status#" < 0 && error("Error getting MPIO properties")
    return nothing
end

function h5p_get_fclose_degree(fapl_id, fc_degree)
    var"#status#" = ccall((:H5Pget_fclose_degree, libhdf5), herr_t, (hid_t, Ref{Cint}), fapl_id, fc_degree)
    var"#status#" < 0 && error("Error getting close degree")
    return nothing
end

function h5p_get_filter_by_id(plist_id, filter_id, flags, cd_nelmts, cd_values, namelen, name, filter_config)
    var"#status#" = ccall((:H5Pget_filter_by_id2, libhdf5), herr_t, (hid_t, H5Z_filter_t, Ref{Cuint}, Ref{Csize_t}, Ptr{Cuint}, Csize_t, Ptr{UInt8}, Ptr{Cuint}), plist_id, filter_id, flags, cd_nelmts, cd_values, namelen, name, filter_config)
    var"#status#" < 0 && error("Error getting filter ID")
    return nothing
end

function h5p_get_layout(plist_id)
    var"#status#" = ccall((:H5Pget_layout, libhdf5), Cint, (hid_t,), plist_id)
    var"#status#" < 0 && error("Error getting layout")
    return var"#status#"
end

function h5p_get_libver_bounds(fapl_id, low, high)
    var"#status#" = ccall((:H5Pget_libver_bounds, libhdf5), herr_t, (hid_t, Ref{Cint}, Ref{Cint}), fapl_id, low, high)
    var"#status#" < 0 && error("Error getting library version bounds")
    return nothing
end

function h5p_get_local_heap_size_hint(plist_id, size_hint)
    var"#status#" = ccall((:H5Pget_local_heap_size_hint, libhdf5), herr_t, (hid_t, Ref{Csize_t}), plist_id, size_hint)
    var"#status#" < 0 && error("Error getting local heap size hint")
    return nothing
end

function h5p_get_obj_track_times(plist_id, track_times)
    var"#status#" = ccall((:H5Pget_obj_track_times, libhdf5), herr_t, (hid_t, Ref{UInt8}), plist_id, track_times)
    var"#status#" < 0 && error("Error setting object time tracking")
    return nothing
end

function h5p_get_userblock(plist_id, len)
    var"#status#" = ccall((:H5Pget_userblock, libhdf5), herr_t, (hid_t, Ptr{hsize_t}), plist_id, len)
    var"#status#" < 0 && error("Error getting userblock")
    return nothing
end

function h5p_modify_filter(plist_id, filter_id, flags, cd_nelmts, cd_values)
    var"#status#" = ccall((:H5Pmodify_filter, libhdf5), herr_t, (hid_t, H5Z_filter_t, Cuint, Csize_t, Ptr{Cuint}), plist_id, filter_id, flags, cd_nelmts, cd_values)
    var"#status#" < 0 && error("Error modifying filter")
    return nothing
end

function h5p_set_alignment(plist_id, threshold, alignment)
    var"#status#" = ccall((:H5Pset_alignment, libhdf5), herr_t, (hid_t, hsize_t, hsize_t), plist_id, threshold, alignment)
    var"#status#" < 0 && error("Error setting alignment")
    return nothing
end

function h5p_set_alloc_time(plist_id, alloc_time)
    var"#status#" = ccall((:H5Pset_alloc_time, libhdf5), herr_t, (hid_t, Cint), plist_id, alloc_time)
    var"#status#" < 0 && error("Error setting allocation timing")
    return nothing
end

function h5p_set_char_encoding(plist_id, encoding)
    var"#status#" = ccall((:H5Pset_char_encoding, libhdf5), herr_t, (hid_t, Cint), plist_id, encoding)
    var"#status#" < 0 && error("Error setting char encoding")
    return nothing
end

function h5p_set_chunk(plist_id, ndims, dims)
    var"#status#" = ccall((:H5Pset_chunk, libhdf5), herr_t, (hid_t, Cint, Ptr{hsize_t}), plist_id, ndims, dims)
    var"#status#" < 0 && error("Error setting chunk size")
    return nothing
end

function h5p_set_chunk_cache(dapl_id, rdcc_nslots, rdcc_nbytes, rdcc_w0)
    var"#status#" = ccall((:H5Pset_chunk_cache, libhdf5), herr_t, (hid_t, Csize_t, Csize_t, Cdouble), dapl_id, rdcc_nslots, rdcc_nbytes, rdcc_w0)
    var"#status#" < 0 && error("Error setting chunk cache")
    return nothing
end

function h5p_set_create_intermediate_group(plist_id, setting)
    var"#status#" = ccall((:H5Pset_create_intermediate_group, libhdf5), herr_t, (hid_t, Cuint), plist_id, setting)
    var"#status#" < 0 && error("Error setting create intermediate group")
    return nothing
end

function h5p_set_deflate(plist_id, setting)
    var"#status#" = ccall((:H5Pset_deflate, libhdf5), herr_t, (hid_t, Cuint), plist_id, setting)
    var"#status#" < 0 && error("Error setting compression method and level (deflate)")
    return nothing
end

function h5p_set_dxpl_mpio(dxpl_id, xfer_mode)
    var"#status#" = ccall((:H5Pset_dxpl_mpio, libhdf5), herr_t, (hid_t, Cint), dxpl_id, xfer_mode)
    var"#status#" < 0 && error("Error setting MPIO transfer mode")
    return nothing
end

function h5p_set_external(plist_id, name, offset, size)
    var"#status#" = ccall((:H5Pset_external, libhdf5), herr_t, (hid_t, Ptr{UInt8}, Int, Csize_t), plist_id, name, offset, size)
    var"#status#" < 0 && error("Error setting external property")
    return nothing
end

function h5p_set_fapl_mpio32(fapl_id, comm, info)
    var"#status#" = ccall((:H5Pset_fapl_mpio, libhdf5), herr_t, (hid_t, Hmpih32, Hmpih32), fapl_id, comm, info)
    var"#status#" < 0 && error("Error setting MPIO properties")
    return nothing
end

function h5p_set_fapl_mpio64(fapl_id, comm, info)
    var"#status#" = ccall((:H5Pset_fapl_mpio, libhdf5), herr_t, (hid_t, Hmpih64, Hmpih64), fapl_id, comm, info)
    var"#status#" < 0 && error("Error setting MPIO properties")
    return nothing
end

function h5p_set_fclose_degree(plist_id, fc_degree)
    var"#status#" = ccall((:H5Pset_fclose_degree, libhdf5), herr_t, (hid_t, Cint), plist_id, fc_degree)
    var"#status#" < 0 && error("Error setting close degree")
    return nothing
end

function h5p_set_filter(plist_id, filter_id, flags, cd_nelmts, cd_values)
    var"#status#" = ccall((:H5Pset_filter, libhdf5), herr_t, (hid_t, H5Z_filter_t, Cuint, Csize_t, Ptr{Cuint}), plist_id, filter_id, flags, cd_nelmts, cd_values)
    var"#status#" < 0 && error("Error setting filter")
    return nothing
end

function h5p_set_layout(plist_id, setting)
    var"#status#" = ccall((:H5Pset_layout, libhdf5), herr_t, (hid_t, Cint), plist_id, setting)
    var"#status#" < 0 && error("Error setting layout")
    return nothing
end

function h5p_set_libver_bounds(fapl_id, low, high)
    var"#status#" = ccall((:H5Pset_libver_bounds, libhdf5), herr_t, (hid_t, Cint, Cint), fapl_id, low, high)
    var"#status#" < 0 && error("Error setting library version bounds")
    return nothing
end

function h5p_set_local_heap_size_hint(plist_id, size_hint)
    var"#status#" = ccall((:H5Pset_local_heap_size_hint, libhdf5), herr_t, (hid_t, Csize_t), plist_id, size_hint)
    var"#status#" < 0 && error("Error setting local heap size hint")
    return nothing
end

function h5p_set_obj_track_times(plist_id, track_times)
    var"#status#" = ccall((:H5Pset_obj_track_times, libhdf5), herr_t, (hid_t, UInt8), plist_id, track_times)
    var"#status#" < 0 && error("Error setting object time tracking")
    return nothing
end

function h5p_set_shuffle(plist_id)
    var"#status#" = ccall((:H5Pset_shuffle, libhdf5), herr_t, (hid_t,), plist_id)
    var"#status#" < 0 && error("Error enabling shuffle filter")
    return nothing
end

function h5p_set_userblock(plist_id, len)
    var"#status#" = ccall((:H5Pset_userblock, libhdf5), herr_t, (hid_t, hsize_t), plist_id, len)
    var"#status#" < 0 && error("Error setting userblock")
    return nothing
end

function h5p_set_virtual(dcpl_id, vspace_id, src_file_name, src_dset_name, src_space_id)
    var"#status#" = ccall((:H5Pset_virtual, libhdf5), herr_t, (hid_t, hid_t, Ptr{UInt8}, Ptr{UInt8}, hid_t), dcpl_id, vspace_id, src_file_name, src_dset_name, src_space_id)
    var"#status#" < 0 && error("Error setting virtual")
    return nothing
end

function h5r_create(ref, loc_id, pathname, ref_type, space_id)
    var"#status#" = ccall((:H5Rcreate, libhdf5), herr_t, (Ptr{Cvoid}, hid_t, Ptr{UInt8}, Cint, hid_t), ref, loc_id, pathname, ref_type, space_id)
    var"#status#" < 0 && error("Error creating reference to object ", h5i_get_name(loc_id), "/", pathname)
    return nothing
end

function h5r_dereference(obj_id, oapl_id, ref_type, ref)
    var"#status#" = ccall((:H5Rdereference2, libhdf5), hid_t, (hid_t, hid_t, Cint, Ptr{Cvoid}), obj_id, oapl_id, ref_type, ref)
    var"#status#" < 0 && error("Error dereferencing object")
    return var"#status#"
end

function h5r_get_obj_type(loc_id, ref_type, ref, obj_type)
    var"#status#" = ccall((:H5Rget_obj_type2, libhdf5), herr_t, (hid_t, Cint, Ptr{Cvoid}, Ptr{Cint}), loc_id, ref_type, ref, obj_type)
    var"#status#" < 0 && error("Error getting object type")
    return nothing
end

function h5r_get_region(loc_id, ref_type, ref)
    var"#status#" = ccall((:H5Rget_region, libhdf5), hid_t, (hid_t, Cint, Ptr{Cvoid}), loc_id, ref_type, ref)
    var"#status#" < 0 && error("Error getting region from reference")
    return var"#status#"
end

function h5s_close(space_id)
    var"#status#" = ccall((:H5Sclose, libhdf5), herr_t, (hid_t,), space_id)
    var"#status#" < 0 && error("Error closing dataspace")
    return nothing
end

function h5s_copy(space_id)
    var"#status#" = ccall((:H5Scopy, libhdf5), hid_t, (hid_t,), space_id)
    var"#status#" < 0 && error("Error copying dataspace")
    return var"#status#"
end

function h5s_create(class)
    var"#status#" = ccall((:H5Screate, libhdf5), hid_t, (Cint,), class)
    var"#status#" < 0 && error("Error creating dataspace")
    return var"#status#"
end

function h5s_create_simple(rank, current_dims, maximum_dims)
    var"#status#" = ccall((:H5Screate_simple, libhdf5), hid_t, (Cint, Ptr{hsize_t}, Ptr{hsize_t}), rank, current_dims, maximum_dims)
    var"#status#" < 0 && error("Error creating simple dataspace")
    return var"#status#"
end

function h5s_get_simple_extent_dims(space_id, dims, maxdims)
    var"#status#" = ccall((:H5Sget_simple_extent_dims, libhdf5), Cint, (hid_t, Ptr{hsize_t}, Ptr{hsize_t}), space_id, dims, maxdims)
    var"#status#" < 0 && error("Error getting the dimensions for a dataspace")
    return var"#status#"
end

function h5s_get_simple_extent_ndims(space_id)
    var"#status#" = ccall((:H5Sget_simple_extent_ndims, libhdf5), Cint, (hid_t,), space_id)
    var"#status#" < 0 && error("Error getting the number of dimensions for a dataspace")
    return var"#status#"
end

function h5s_get_simple_extent_type(space_id)
    var"#status#" = ccall((:H5Sget_simple_extent_type, libhdf5), Cint, (hid_t,), space_id)
    var"#status#" < 0 && error("Error getting the dataspace type")
    return var"#status#"
end

function h5s_is_simple(space_id)
    var"#status#" = ccall((:H5Sis_simple, libhdf5), htri_t, (hid_t,), space_id)
    var"#status#" < 0 && error("Error determining whether dataspace is simple")
    return var"#status#" > 0
end

function h5s_select_hyperslab(dspace_id, seloper, start, stride, count, block)
    var"#status#" = ccall((:H5Sselect_hyperslab, libhdf5), herr_t, (hid_t, Cint, Ptr{hsize_t}, Ptr{hsize_t}, Ptr{hsize_t}, Ptr{hsize_t}), dspace_id, seloper, start, stride, count, block)
    var"#status#" < 0 && error("Error selecting hyperslab")
    return nothing
end

function h5t_array_create(basetype_id, ndims, sz)
    var"#status#" = ccall((:H5Tarray_create2, libhdf5), hid_t, (hid_t, Cuint, Ptr{hsize_t}), basetype_id, ndims, sz)
    var"#status#" < 0 && error("Error creating H5T_ARRAY of id ", basetype_id, " and size ", sz)
    return var"#status#"
end

function h5t_close(dtype_id)
    var"#status#" = ccall((:H5Tclose, libhdf5), herr_t, (hid_t,), dtype_id)
    var"#status#" < 0 && error("Error closing datatype")
    return nothing
end

function h5t_committed(dtype_id)
    var"#status#" = ccall((:H5Tcommitted, libhdf5), htri_t, (hid_t,), dtype_id)
    var"#status#" < 0 && error("Error determining whether datatype is committed")
    return var"#status#" > 0
end

function h5t_commit(loc_id, name, dtype_id, lcpl_id, tcpl_id, tapl_id)
    var"#status#" = ccall((:H5Tcommit2, libhdf5), herr_t, (hid_t, Ptr{UInt8}, hid_t, hid_t, hid_t, hid_t), loc_id, name, dtype_id, lcpl_id, tcpl_id, tapl_id)
    var"#status#" < 0 && error("Error committing type")
    return nothing
end

function h5t_copy(dtype_id)
    var"#status#" = ccall((:H5Tcopy, libhdf5), hid_t, (hid_t,), dtype_id)
    var"#status#" < 0 && error("Error copying datatype")
    return var"#status#"
end

function h5t_create(class_id, sz)
    var"#status#" = ccall((:H5Tcreate, libhdf5), hid_t, (Cint, Csize_t), class_id, sz)
    var"#status#" < 0 && error("Error creating datatype of id ", class_id)
    return var"#status#"
end

function h5t_equal(dtype_id1, dtype_id2)
    var"#status#" = ccall((:H5Tequal, libhdf5), hid_t, (hid_t, hid_t), dtype_id1, dtype_id2)
    var"#status#" < 0 && error("Error checking datatype equality")
    return var"#status#"
end

function h5t_get_array_dims(dtype_id, dims)
    var"#status#" = ccall((:H5Tget_array_dims2, libhdf5), Cint, (hid_t, Ptr{hsize_t}), dtype_id, dims)
    var"#status#" < 0 && error("Error getting dimensions of array")
    return var"#status#"
end

function h5t_get_array_ndims(dtype_id)
    var"#status#" = ccall((:H5Tget_array_ndims, libhdf5), Cint, (hid_t,), dtype_id)
    var"#status#" < 0 && error("Error getting ndims of array")
    return var"#status#"
end

function h5t_get_class(dtype_id)
    var"#status#" = ccall((:H5Tget_class, libhdf5), Cint, (hid_t,), dtype_id)
    var"#status#" < 0 && error("Error getting class")
    return var"#status#"
end

function h5t_get_cset(dtype_id)
    var"#status#" = ccall((:H5Tget_cset, libhdf5), Cint, (hid_t,), dtype_id)
    var"#status#" < 0 && error("Error getting character set encoding")
    return var"#status#"
end

function h5t_get_ebias(dtype_id)
    var"#status#" = ccall((:H5Tget_ebias, libhdf5), Csize_t, (hid_t,), dtype_id)
    var"#status#" < 0 && error("Error getting datatype floating point exponent bias")
    return var"#status#"
end

function h5t_get_fields(dtype_id, spos, epos, esize, mpos, msize)
    var"#status#" = ccall((:H5Tget_fields, libhdf5), herr_t, (hid_t, Ref{Csize_t}, Ref{Csize_t}, Ref{Csize_t}, Ref{Csize_t}, Ref{Csize_t}), dtype_id, spos, epos, esize, mpos, msize)
    var"#status#" < 0 && error("Error getting datatype floating point bit positions")
    return nothing
end

function h5t_get_member_class(dtype_id, index)
    var"#status#" = ccall((:H5Tget_member_class, libhdf5), Cint, (hid_t, Cuint), dtype_id, index)
    var"#status#" < 0 && error("Error getting class of compound datatype member #", index)
    return var"#status#"
end

function h5t_get_member_index(dtype_id, membername)
    var"#status#" = ccall((:H5Tget_member_index, libhdf5), Cint, (hid_t, Ptr{UInt8}), dtype_id, membername)
    var"#status#" < 0 && error("Error getting index of compound datatype member \"", membername, "\"")
    return var"#status#"
end

function h5t_get_member_offset(dtype_id, index)
    var"#status#" = ccall((:H5Tget_member_offset, libhdf5), Csize_t, (hid_t, Cuint), dtype_id, index)
    return var"#status#"
end

function h5t_get_member_type(dtype_id, index)
    var"#status#" = ccall((:H5Tget_member_type, libhdf5), hid_t, (hid_t, Cuint), dtype_id, index)
    var"#status#" < 0 && error("Error getting type of compound datatype member #", index)
    return var"#status#"
end

function h5t_get_native_type(dtype_id, direction)
    var"#status#" = ccall((:H5Tget_native_type, libhdf5), hid_t, (hid_t, Cint), dtype_id, direction)
    var"#status#" < 0 && error("Error getting native type")
    return var"#status#"
end

function h5t_get_nmembers(dtype_id)
    var"#status#" = ccall((:H5Tget_nmembers, libhdf5), Cint, (hid_t,), dtype_id)
    var"#status#" < 0 && error("Error getting the number of members")
    return var"#status#"
end

function h5t_get_sign(dtype_id)
    var"#status#" = ccall((:H5Tget_sign, libhdf5), Cint, (hid_t,), dtype_id)
    var"#status#" < 0 && error("Error getting sign")
    return var"#status#"
end

function h5t_get_size(dtype_id)
    var"#status#" = ccall((:H5Tget_size, libhdf5), Csize_t, (hid_t,), dtype_id)
    var"#status#" < 0 && error("Error getting size")
    return var"#status#"
end

function h5t_get_strpad(dtype_id)
    var"#status#" = ccall((:H5Tget_strpad, libhdf5), Cint, (hid_t,), dtype_id)
    var"#status#" < 0 && error("Error getting string padding")
    return var"#status#"
end

function h5t_get_super(dtype_id)
    var"#status#" = ccall((:H5Tget_super, libhdf5), hid_t, (hid_t,), dtype_id)
    var"#status#" < 0 && error("Error getting super type")
    return var"#status#"
end

function h5t_insert(dtype_id, fieldname, offset, field_id)
    var"#status#" = ccall((:H5Tinsert, libhdf5), herr_t, (hid_t, Ptr{UInt8}, Csize_t, hid_t), dtype_id, fieldname, offset, field_id)
    var"#status#" < 0 && error("Error adding field ", fieldname, " to compound datatype")
    return nothing
end

function h5t_is_variable_str(type_id)
    var"#status#" = ccall((:H5Tis_variable_str, libhdf5), htri_t, (hid_t,), type_id)
    var"#status#" < 0 && error("Error determining whether string is of variable length")
    return var"#status#" > 0
end

function h5t_lock(type_id)
    var"#status#" = ccall((:H5Tlock, libhdf5), herr_t, (hid_t,), type_id)
    var"#status#" < 0 && error("Error locking type")
    return nothing
end

function h5t_open(loc_id, name, tapl_id)
    var"#status#" = ccall((:H5Topen2, libhdf5), hid_t, (hid_t, Ptr{UInt8}, hid_t), loc_id, name, tapl_id)
    var"#status#" < 0 && error("Error opening type ", h5i_get_name(loc_id), "/", name)
    return var"#status#"
end

function h5t_set_cset(dtype_id, cset)
    var"#status#" = ccall((:H5Tset_cset, libhdf5), herr_t, (hid_t, Cint), dtype_id, cset)
    var"#status#" < 0 && error("Error setting character set in datatype")
    return nothing
end

function h5t_set_ebias(dtype_id, ebias)
    var"#status#" = ccall((:H5Tset_ebias, libhdf5), herr_t, (hid_t, Csize_t), dtype_id, ebias)
    var"#status#" < 0 && error("Error setting datatype floating point exponent bias")
    return nothing
end

function h5t_set_fields(dtype_id, spos, epos, esize, mpos, msize)
    var"#status#" = ccall((:H5Tset_fields, libhdf5), herr_t, (hid_t, Csize_t, Csize_t, Csize_t, Csize_t, Csize_t), dtype_id, spos, epos, esize, mpos, msize)
    var"#status#" < 0 && error("Error setting datatype floating point bit positions")
    return nothing
end

function h5t_set_precision(dtype_id, sz)
    var"#status#" = ccall((:H5Tset_precision, libhdf5), herr_t, (hid_t, Csize_t), dtype_id, sz)
    var"#status#" < 0 && error("Error setting precision of datatype")
    return nothing
end

function h5t_set_size(dtype_id, sz)
    var"#status#" = ccall((:H5Tset_size, libhdf5), herr_t, (hid_t, Csize_t), dtype_id, sz)
    var"#status#" < 0 && error("Error setting size of datatype")
    return nothing
end

function h5t_set_strpad(dtype_id, sz)
    var"#status#" = ccall((:H5Tset_strpad, libhdf5), herr_t, (hid_t, Cint), dtype_id, sz)
    var"#status#" < 0 && error("Error setting size of datatype")
    return nothing
end

function h5t_vlen_create(base_type_id)
    var"#status#" = ccall((:H5Tvlen_create, libhdf5), hid_t, (hid_t,), base_type_id)
    var"#status#" < 0 && error("Error creating vlen type")
    return var"#status#"
end

function h5do_append(dset_id, dxpl_id, index, num_elem, memtype, buffer)
    var"#status#" = ccall((:H5DOappend, libhdf5_hl), herr_t, (hid_t, hid_t, Cuint, hsize_t, hid_t, Ptr{Cvoid}), dset_id, dxpl_id, index, num_elem, memtype, buffer)
    var"#status#" < 0 && error("error appending")
    return nothing
end

function h5do_write_chunk(dset_id, dxpl_id, filter_mask, offset, bufsize, buf)
    var"#status#" = ccall((:H5DOwrite_chunk, libhdf5_hl), herr_t, (hid_t, hid_t, Int32, Ptr{hsize_t}, Csize_t, Ptr{Cvoid}), dset_id, dxpl_id, filter_mask, offset, bufsize, buf)
    var"#status#" < 0 && error("Error writing chunk")
    return nothing
end

function h5ds_attach_scale(did, dsid, idx)
    var"#status#" = ccall((:H5DSattach_scale, libhdf5_hl), herr_t, (hid_t, hid_t, Cuint), did, dsid, idx)
    var"#status#" < 0 && error("Unable to attach scale")
    return nothing
end

function h5ds_detach_scale(did, dsid, idx)
    var"#status#" = ccall((:H5DSdetach_scale, libhdf5_hl), herr_t, (hid_t, hid_t, Cuint), did, dsid, idx)
    var"#status#" < 0 && error("Unable to detach scale")
    return nothing
end

function h5ds_get_label(did, idx, label, size)
    var"#status#" = ccall((:H5DSget_label, libhdf5_hl), herr_t, (hid_t, Cuint, Ptr{UInt8}, hsize_t), did, idx, label, size)
    var"#status#" < 0 && error("Unable to get label")
    return nothing
end

function h5ds_get_num_scales(did, idx)
    var"#status#" = ccall((:H5DSget_num_scales, libhdf5_hl), Cint, (hid_t, Cuint), did, idx)
    var"#status#" < 0 && error("Error getting number of scales")
    return var"#status#"
end

function h5ds_get_scale_name(did, name, size)
    var"#status#" = ccall((:H5DSget_scale_name, libhdf5_hl), Cssize_t, (hid_t, Ptr{UInt8}, Csize_t), did, name, size)
    var"#status#" < 0 && error("Unable to get scale name")
    return var"#status#"
end

function h5ds_is_attached(did, dsid, idx)
    var"#status#" = ccall((:H5DSis_attached, libhdf5_hl), htri_t, (hid_t, hid_t, Cuint), did, dsid, idx)
    var"#status#" < 0 && error("Unable to check if dimension is attached")
    return var"#status#" > 0
end

function h5ds_is_scale(did)
    var"#status#" = ccall((:H5DSis_scale, libhdf5_hl), htri_t, (hid_t,), did)
    var"#status#" < 0 && error("Unable to check if dataset is scale")
    return var"#status#" > 0
end

function h5ds_set_label(did, idx, label)
    var"#status#" = ccall((:H5DSset_label, libhdf5_hl), herr_t, (hid_t, Cuint, Ref{UInt8}), did, idx, label)
    var"#status#" < 0 && error("Unable to set label")
    return nothing
end

function h5ds_set_scale(dsid, dimname)
    var"#status#" = ccall((:H5DSset_scale, libhdf5_hl), herr_t, (hid_t, Ptr{UInt8}), dsid, dimname)
    var"#status#" < 0 && error("Unable to set scale")
    return nothing
end

function h5lt_dtype_to_text(datatype, str, lang_type, len)
    var"#status#" = ccall((:H5LTdtype_to_text, libhdf5_hl), herr_t, (hid_t, Ptr{UInt8}, Cint, Ref{Csize_t}), datatype, str, lang_type, len)
    var"#status#" < 0 && error("Error getting datatype text representation")
    return nothing
end

function h5tb_get_field_info(loc_id, table_name, field_names, field_sizes, field_offsets, type_size)
    var"#status#" = ccall((:H5TBget_field_info, libhdf5_hl), herr_t, (hid_t, Ptr{UInt8}, Ptr{Ptr{UInt8}}, Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}), loc_id, table_name, field_names, field_sizes, field_offsets, type_size)
    var"#status#" < 0 && error("Error getting field information")
    return nothing
end

function h5z_register(filter_class)
    var"#status#" = ccall((:H5Zregister, libhdf5), herr_t, (Ref{H5Z_class_t},), filter_class)
    var"#status#" < 0 && error("Unable to register new filter")
    return nothing
end


text:
#=
DPM_demo_Gaussian1DGaussian1D_collapsed

A demo for Dirichlet Process Mixture Model with Gaussian1DGaussian1D Bayesian
components.

08/07/2015
Adham Beyki, odinay@gmail.com
=#

using BNP

## --- synthesizing the data ---
# synthesized corpus properties
true_KK = 5           # number of components
NN = 500              # number of data points

vv = 0.02            # fixed variance
ss = 2

true_atoms = [Gaussian1D(ss*kk, vv) for kk = 1:true_KK]

# constructing the observations and labels
mix = ones(Float64, true_KK)/true_KK
xx = ones(Float64, NN)
true_zz = ones(Int64, NN)
true_nn = zeros(Int64, true_KK)

for n=1:NN
    kk = sample(mix)
    true_zz[n] = kk
    xx[n] = sample(true_atoms[kk])
    true_nn[kk] += 1
end

## ------- inference --------
# constructing the conjugate component
m0= mean(xx)
v0 = 2
q0 = Gaussian1DGaussian1D(m0, v0, vv)

# constructing the model
init_KK = 1
KK_truncation = 10
dpm_aa  = 1
dpm_aa1 = 1
dpm_aa2 = 1
dpm = DPM(q0, init_KK, dpm_aa, dpm_aa1, dpm_aa2)

# sampling
zz = zeros(Int64, length(xx))
zz = rand(1:dpm.KK, NN)

n_burnins   = 100
n_lags      = 1
n_samples   = 300
sample_hyperparam = true
n_internals = 10
store_every = 10000
results_path = ""
filename    = "demo_DPM_Gaussian1DGaussian1D_"
KK_list, KK_dict = truncated_gibbs_sampler(dpm, KK_truncation, xx, zz,
	n_burnins, n_lags, n_samples, sample_hyperparam, n_internals, store_every, results_path, filename)

KK_hist = hist(KK_list, 0.5:maximum(KK_list)+0.5)[2]
candidate_KK = indmax(KK_hist)
posterior_components, nn = posterior(dpm, xx, KK_dict[candidate_KK], candidate_KK)


text:
# TODO: KEEP
# function compareAll(Al::T1, Bl::T2; show::Bool=true, skip::Vector{Symbol}=Symbol[])::Bool where {T1 <: Union{SingleThreaded, MultiThreaded}, T2 <: Union{SingleThreaded, MultiThreaded}}
#   return T1 == T2
# end
import DistributedFactorGraphs: compare, compareAllSpecial

# These are now moved to DistributedFactorGraphs, with the exceptions of
# the functions with IIF-specific parameters.
# To extend these, import the relevant DFG compareX function and overload it.

function Base.isapprox( p1::Union{<:BallTreeDensity, <:ManifoldKernelDensity},
                        p2::Union{<:BallTreeDensity, <:ManifoldKernelDensity};
                        atol::Real=1e-6 )
  #
  mmd(p1,p2) < atol
end

function Base.isapprox( a::ProductRepr,
                        b::ProductRepr;
                        atol::Real=1e-6 )
  #
  for (i,a_) in enumerate(a.parts)
    isapprox(a_, b.parts[i]; atol=atol) || (return false)
  end
  return true
end

## FIXME, FIGURE OUT HOW TO DEPRECATE BELOW ==============================================

function compareAllSpecial( A::T1, B::T2;
                            skip=Symbol[], show::Bool=true) where {T1 <: CommonConvWrapper, T2 <: CommonConvWrapper}
  #
  if T1 != T2
    @warn "CCW types T1 and T2 not equal=>" T1 T2
    # return false
  end
  # FIXME still issues with compare, skipping :vartypes https://github.com/JuliaRobotics/DistributedFactorGraphs.jl/issues/434
  return compareAll(A, B, skip=union(skip, [:vartypes]), show=show)
end

function compare( p1::Union{<:BallTreeDensity,<:ManifoldKernelDensity},
                  p2::Union{<:BallTreeDensity,<:ManifoldKernelDensity} )
  #
  return  compareAll(p1.bt,p2.bt, skip=[:calcStatsHandle; :data]) &&
          compareAll(p1,p2, skip=[:calcStatsHandle; :bt])
end

function compare( c1::TreeClique,
                  c2::TreeClique )
  #
  TP = true
  TP = TP && c1.id == c2.id
  # data
  @warn "skipping ::TreeClique compare of data"
  # TP = TP && compare(c1.data, c2.data)

  # attributes
  @warn "only comparing keys of TreeClique attributes"
  TP = TP && collect(keys(c1.attributes)) == collect(keys(c2.attributes))

  return TP
end

#


text:
using Oceananigans.TimeSteppers: update_state!

import Oceananigans.Fields: set!

using Oceananigans.Utils: @apply_regionally, apply_regionally!

"""
    set!(model; kwargs...)

Set velocity and tracer fields of `model`. The keyword arguments
`kwargs...` take the form `name=data`, where `name` refers to one of the
fields of `model.velocities` or `model.tracers`, and the `data` may be an array,
a function with arguments `(x, y, z)`, or any data type for which a
`set!(ϕ::AbstractField, data)` function exists.

Example
=======
```julia
model = HydrostaticFreeSurfaceModel(grid=RectilinearGrid(size=(32, 32, 32), length=(1, 1, 1))

# Set u to a parabolic function of z, v to random numbers damped
# at top and bottom, and T to some silly array of half zeros,
# half random numbers.

u₀(x, y, z) = z/model.grid.Lz * (1 + z/model.grid.Lz)
v₀(x, y, z) = 1e-3 * rand() * u₀(x, y, z)

T₀ = rand(size(model.grid)...)
T₀[T₀ .< 0.5] .= 0

set!(model, u=u₀, v=v₀, T=T₀)
```
"""
function set!(model::HydrostaticFreeSurfaceModel; kwargs...)
    for (fldname, value) in kwargs
        if fldname ∈ propertynames(model.velocities)
            ϕ = getproperty(model.velocities, fldname)
        elseif fldname ∈ propertynames(model.tracers)
            ϕ = getproperty(model.tracers, fldname)
        elseif fldname ∈ propertynames(model.free_surface)
            ϕ = getproperty(model.free_surface, fldname)
        else
            throw(ArgumentError("name $fldname not found in model.velocities, model.tracers, or model.free_surface"))
        end

        @apply_regionally set!(ϕ, value)
    end

    update_state!(model)

    return nothing
end


text:
using Printf;
using Plots;
gr();
anim = Animation();

f(x) = 1/2*cos(8pi*(x-1/2)) + 1/2;
function init()
	global c = 1.0;
	global nx = 101;
	global x = range(0.0, stop=1.0, length=nx);
	global dx = 2e-3;
	global u1 = zeros(Float64, nx);
	global u2 = zeros(Float64, nx);
	for i = 1:nx
		if 3/8 <= x[i] <= 5/8
			u1[i] = f(x[i]);
			u2[i] = f(x[i]);
		else
			u1[i] = 0.0;
			u2[i] = 0.0;
		end
	end
	global t = 0.0;
	global tlim = 1.2;
	global dt = 2e-3;
end

function main()
	init();
	while t < tlim
		pre_u1 = copy(u1);
		pre_u2 = copy(u2);
		for i = 2:nx-1
			u1[i] = pre_u1[i] - c*dt/dx*(pre_u1[i] - pre_u1[i-1]);
			u2[i] = pre_u2[i] + c*dt/dx*(pre_u2[i+1] - pre_u2[i]);
		end
		u1[begin] = u1[end] = u2[begin] = u2[end] = 0.0;
		plt = plot(x, [u1 u2], xlims = (0.0, 1.0), xticks=0:0.2:1.0, ylims=(0,1.0), yticks=0:0.2:1.0, xlabel="x", ylabel="u", title="Upwind differencial method", legend=false);
		frame(anim, plt);
		@printf("t = %.4f\n", t);
		global t +=  dt;
	end
	gif(anim, "hyperbole_PDE.gif", fps=5);
end

main();


text: Dict{String, Any}("utc" => Dict{String, Any}("value" => "1987-07-05T17:45:56Z", "type" => "datetime"), "nzdt" => Dict{String, Any}("value" => "1987-07-05T17:45:56+13:00", "type" => "datetime"), "nzst" => Dict{String, Any}("value" => "1987-07-05T17:45:56+12:00", "type" => "datetime"), "pdt" => Dict{String, Any}("value" => "1987-07-05T17:45:56-05:00", "type" => "datetime"))