text:
function time_series_intraday(symbol::String, interval::String="1min"; outputsize::String="compact", datatype::String="json")
    @argcheck in(interval, ["1min", "5min", "15min", "30min", "60min"])
    @argcheck in(outputsize, ["compact", "full"])
    @argcheck in(datatype, ["json", "csv"])
    uri = "$(alphavantage_api)query?function=TIME_SERIES_INTRADAY&symbol=$symbol&interval=$interval&outputsize=$outputsize&datatype=$datatype&apikey=" * ENV["ALPHA_VANTAGE_API_KEY"]
    data = _get_request(uri)
    return _parse_response(data, datatype)
end
export time_series_intraday

for func in (:daily, :daily_adjusted, :weekly, :weekly_adjusted, :monthly, :monthly_adjusted)
    x = "time_series_$(func)"
    fname = Symbol(x)
    @eval begin
        function ($fname)(symbol::String; outputsize::String="compact", datatype::String="json")
            @argcheck in(outputsize, ["compact", "full"])
            @argcheck in(datatype, ["json", "csv"])
            uri = "$(alphavantage_api)query?function="* uppercase($x) * "&symbol=$symbol&outputsize=$outputsize&datatype=$datatype&apikey=" * ENV["ALPHA_VANTAGE_API_KEY"]
            data = _get_request(uri)
            return _parse_response(data, datatype)
        end
        export $fname
    end
end


text:
"""
Given the number of rows and columns, return an NTuple{4,Float64} containing
`(width, height, vspace, hspace)`, where `width` and `height` are the
width and height of each subplot and `vspace` and `hspace` are the vertical
and horizonal spacing between subplots, respectively.
"""
function sizes(nr::Int, nc::Int, subplot_titles::Bool=false)
    # NOTE: the logic of this function was mostly borrowed from plotly.py
    dx = 0.2 / nc
    dy = subplot_titles ? 0.55 / nr : 0.3 / nr
    width = (1. - dx * (nc - 1)) / nc
    height = (1. - dy * (nr - 1)) / nr
    vspace = nr == 1 ? 0.0 : (1 - height*nr)/(nr-1)
    hspace = nc == 1 ? 0.0 : (1 - width*nc)/(nc-1)
    width, height, vspace, hspace
end

function gen_layout(nr, nc, subplot_titles::Bool=false)
    w, h, dy, dx = sizes(nr, nc, subplot_titles)

    x = 0.0  # start from left
    y = 1.0  # start from top

    out = Layout()
    for col in 1:nc

        y = 1.0 # reset y as we start a new col
        for row in 1:nr
            subplot = sub2ind((nc, nr), col, row)

            out["xaxis$subplot"] = Dict{Any,Any}(:domain=>[x, x+w],
                                                 :anchor=> "y$subplot")
            out["yaxis$subplot"] = Dict{Any,Any}(:domain=>[y-h, y],
                                                 :anchor=> "x$subplot")

            y -= nr == 1 ? 0.0 : h + dy
         end

         x += nc == 1 ? 0.0 : w + dx
    end

    out

end

function handle_titles!(big_layout, sub_layout, ix::Int)
    # don't worry about it if the sub_layout doesn't have a title
    if !haskey(sub_layout.fields, "title") && !haskey(sub_layout.fields, :title)
        return big_layout
    end

    # check for symbol or string
    nm = haskey(sub_layout.fields, "title") ? "title" : :title

    ann = Dict{Any,Any}(:font => Dict{Any,Any}(:size => 16),
                        :showarrow => false,
                        :text => pop!(sub_layout.fields, nm),
                        :x => mean(big_layout["xaxis$(ix).domain"]),
                        :xanchor => "center",
                        :xref => "paper",
                        :y => big_layout["yaxis$(ix).domain"][2],
                        :yanchor => "bottom",
                        :yref => "paper")
    anns = get(big_layout.fields, :annotations, Dict{Any,Any}[])
    push!(anns, ann)
    big_layout[:annotations] = anns
    big_layout
end

function _cat(nr::Int, nc::Int, ps::Plot...)
    copied_plots = Plot[copy(p) for p in ps]
    subplot_titles = any(map(x -> haskey(x.layout.fields, :title) ||
                                  haskey(x.layout.fields, "title"), ps))
    layout = gen_layout(nr, nc, subplot_titles)

    for col in 1:nc, row in 1:nr
        ix = sub2ind((nc, nr), col, row)

        for trace in copied_plots[ix].data
            trace["xaxis"] = "x$ix"
            trace["yaxis"] = "y$ix"
        end

        handle_titles!(layout, copied_plots[ix].layout, ix)
        layout["xaxis$ix"] = merge(copied_plots[ix].layout["xaxis"], layout["xaxis$ix"])
        layout["yaxis$ix"] = merge(copied_plots[ix].layout["yaxis"], layout["yaxis$ix"])
    end

    Plot(vcat([p.data for p in copied_plots]...), layout)
end

Base.hcat(ps::Plot...) = _cat(1, length(ps), ps...)
Base.vcat(ps::Plot...) = _cat(length(ps), 1,  ps...)
Base.vect(ps::Plot...) = vcat(ps...)

function Base.hvcat(rows::Tuple{Vararg{Int}}, ps::Plot...)
    nr = length(rows)
    nc = rows[1]

    for (i, c) in enumerate(rows[2:end])
        c == nc || error("Saw $c columns in row $(i+1), expected $nc")
    end
    _cat(nr, nc, ps...)
end

# methods on syncplot
Base.hcat{TP<:SyncPlot}(sps::TP...) = TP(hcat([sp.plot for sp in sps]...))
Base.vcat{TP<:SyncPlot}(sps::TP...) = TP(vcat([sp.plot for sp in sps]...))
Base.vect{TP<:SyncPlot}(sps::TP...) = vcat(sps...)
Base.hvcat{TP<:SyncPlot}(rows::Tuple{Vararg{Int}}, sps::TP...) =
    TP(hvcat(rows, [sp.plot for sp in sps]...))

ext: jl


text:
# The following check is done because `MLJBase.clean!(model)` isn't called for
# `MLJBase.predict` and the user may modify the model's`K` value
# wrapped in a machine.
function err_if_given_invalid_K(K)
    K > 0 || throw(ArgumentError("Number of neighbors `K` has to be greater than 0"))
    return K
end

# internal method essentially the same as Base.replace!(y, (z .=> r)...)
# but more efficient.
# Similar to the behaviour of `Base.replace!` if `z` contain repetions of values in
# `y` then only the transformation corresponding to the first occurence is performed
# i.e `_replace!([1,5,3], [1,4], 4:5)` would return `[4,5,3]` rather than `[5,5,3]`
# (which replaces `1=>4` and then `4=>5`)
function _replace!(y::AbstractVector, z::AbstractVector, r::AbstractVector)
    length(r) == length(z) ||
     throw(DimensionMismatch("`z` and `r` has to be of the same length"))
    @inbounds for i in eachindex(y)
        for j in eachindex(z)
            isequal(z[j], y[i]) && (y[i] = r[j]; break)
        end
    end
    return y
end

### Methods for combining knn_weights and sample weights
combine_weights(idxs_matrix, knn_weights, ::Nothing) = knn_weights
combine_weights(idxs_matrix, ::Nothing, ::Nothing) = Fill(1, size(idxs_matrix))
combine_weights(idxs_matrix, ::Nothing, sample_weights) = @inbounds(@view(sample_weights[idxs_matrix]))

@inline function combine_weights(idxs_matrix, knn_weights, sample_weights)
    @inbounds(sw = @view(sample_weights[idxs_matrix]))
    weights = knn_weights .* sw
    return weights
end

### Specialized `sum` methods
_sum(x; dims=:) = sum(x, dims=dims)
_sum(x::Fill{Int, 2}; dims=:) = __sum(x, dims)

@inline function __sum(x::Fill{Int, 2}, dims::Int)
    dims  > 2 && return x
    len = size(x, dims)
    axis = dims == 1 ? (1, size(x, 2)) : (size(x, 1), 1)
    fill_value = @inbounds first(x)
    return Fill(fill_value * len, axis)
end

@inline function __sum(x::Fill{Int, 2}, dims::Colon)
    fill_value = @inbounds first(x)
    return *(size(x)...) * fill_value
end

### Normalize the rows or columns of an `AbstractMatrix` by its sum, rowsum or columnsum.
### Specialization introduced for some julia Base `<:Real` types to gain further
### performance.
function scale(A::Mat{<:Union{Base.IEEEFloat, BigFloat, Rational}}; dims=:)
    axis_sum = sum(A,dims=dims)
    A ./= axis_sum
    return A
end

function scale(A::Mat{<:Real}; dims=:)
    axis_sum = sum(A, dims=dims)
    A_scaled = A ./ axis_sum
    return A_scaled
end

### Wrap knn distances and indices which are `Vector{Vector{<:AbstractFloat}}` as
## `NeighDistsMatrix` and `NeighIndsMatrix` respectively. This among other things
## makes it easy to write kernels
struct NeighIndsMatrix{T<:Integer} <: AbstractMatrix{T}
    vecofvecs::Vector{Vector{T}}
end

struct NeighDistsMatrix{T} <: AbstractMatrix{T}
    vecofvecs::Vector{Vector{T}}
end

function Base.size(A::Union{NeighIndsMatrix, NeighDistsMatrix})
    return (length(A.vecofvecs), length(@inbounds(A.vecofvecs[1])))
end

Base.IndexStyle(m::Union{NeighIndsMatrix, NeighDistsMatrix}) = Base.IndexCartesian()

@inline function Base.getindex(A::Union{NeighIndsMatrix, NeighDistsMatrix}, i::Int, j::Int)
    @boundscheck Base.checkbounds(A, i, j)
    # Ai is the ith row of matrix `A`
    @inbounds(Ai = A.vecofvecs[i])
    # Aij is the element in the ith row and jth column of matrix `A`
    @inbounds(Aij = Ai[j])
    return Aij
end

@inline function Base.view(A::Union{NeighIndsMatrix, NeighDistsMatrix}, i::Int, j::Colon)
    #J = map(i->unalias(A,i), to_indices(A, i))
    J = Base.to_indices(A, (i, j))
    @boundscheck Base.checkbounds(A, J...)
    # Ai is the ith row of matrix `A`
    @inbounds(Ai = A.vecofvecs[i])
    return Ai
end

function Base.unaliascopy(A::Union{NeighIndsMatrix, NeighDistsMatrix})::typeof(A)
    v = A.vecofvecs
    return typeof(A)([copy(@inbounds(v[i])) for i in eachindex(v)])
end

@inline function Base.setindex!(
    A::Union{NeighIndsMatrix, NeighDistsMatrix},
    val,
    i::Int,
    j::Int
)
    @boundscheck Base.checkbounds(A, i, j)
    # Ai is the ith row of matrix `A`
    @inbounds(Ai = A.vecofvecs[i])
    @inbounds Base.setindex!(Ai, val, j)
    return val
end

### Efficient way to store and index into Matrices with
### the same rows i.e Rank One Matrices. This is perfect for our usecase
### since we don't modify weight matrix.
struct RankOneMatrix{T} <: AbstractMatrix{T}
    rowvector::Vector{T}
    nrows::Int
end

Base.IndexStyle(::RankOneMatrix) = Base.IndexCartesian()
Base.size(A::RankOneMatrix) = (A.nrows, length(A.rowvector))

@inline function Base.getindex(A::RankOneMatrix, i::Int, j::Int)
    @boundscheck Base.checkbounds(A, i, j)
    Aij = @inbounds(A.rowvector[j])
    return Aij
end

function Base.unaliascopy(A::RankOneMatrix)::typeof(A)
    row_vector = A.rowvector
    nrows = A.nrows
    return typeof(A)(copy(row_vector), nrows)
end

### Check to make sure a given `AbstractArray` isa one based indexed array.
@inline function check_onebased_indexing(argname::String, matorvec; istable=false)
    Base.has_offset_axes(matorvec) && begin
        if matorvec isa AbstractVector
            throw(ArgumentError(
                "$argname vector must be a 1-based indexed `AbstractVector`"
                )
            )
        elseif matorvec isa AbstractMatrix
            throw(
                ArgumentError(
                    "$(argname) matrix $(
                        ifelse(istable, "generated from $(argname) table", "")
                    )  must be a 1-based indexed `AbstractMatrix`"
                )
            )
        end
    end
    return nothing
end


text:
commands = readlines("day2/commands.txt")

function dive(commands)
    h, d = 0, 0
    for command in commands
        dir, x = split(command)
        x = parse(Int, x)
        if dir == "forward"
            h += x
        else
            d += dir == "down" ? x : -x
        end
    end
    h, d
end

h, d = dive(commands)
p1 = h * d

@show p1

function dive2(commands)
    h, d, a = 0, 0, 0
    for command in commands
        dir, x = split(command)
        x = parse(Int, x)
        if dir == "forward"
            h += x
            d += x * a
        else
            a += dir == "down" ? x : -x
        end
    end
    h, d, a
end

h, d, _ = dive2(commands)
p2 = h * d

@show p2


text:
using DockerSandbox
using Test

import Pkg
import TOML

include("utils.jl")

include("no_nonstdlib_deps.jl")
include("docker_is_installed.jl")

include("add_capabilities.jl")
include("environment_variables.jl")
include("errors.jl")
include("read_only_maps.jl")
include("read_write_maps.jl")
include("with_container.jl")


text:
"
    EditorTab <: GtkScrolledWindow

A single text file inside the `Editor`.
The main fields are the GtkSourceView (view) and the GtkSourceBuffer (buffer)."
mutable struct EditorTab <: GtkScrolledWindow

    handle::Ptr{Gtk.GObject}
    view::GtkSourceView
    buffer::GtkSourceBuffer
    filename::String
    texthash::UInt64
    modified::Bool
    search_context::GtkSourceSearchContext
    search_mark_start
    search_mark_end
    scroll_target::Float64
    scroll_target_line::Int
    autocomplete_words::Array{String, 1}
    label::GtkLabel
    eval_in::Module

    function EditorTab(filename::String, main_window::MainWindow)

        languageDefinitions = main_window.style_and_language_manager.languageDefinitions
        lang = haskey(languageDefinitions, extension(filename)) ?
        languageDefinitions[extension(filename)] : languageDefinitions[".jl"]

        filename = isabspath(filename) ? filename : joinpath(pwd(), filename)#FIXME pwd should be called on worker
        filename = normpath(filename)

        b = GtkSourceBuffer(lang)

        set_gtk_property!(b, :style_scheme, main_window.style_and_language_manager.main_style)
        v = GtkSourceView(b)

        highlight_matching_brackets(b, true)

        show_line_numbers!(v, opt("Editor", "show_line_numbers"))
	    auto_indent!(v, true)
        highlight_current_line!(v, true)
        set_gtk_property!(v, :wrap_mode, opt("Editor", "wrap_mode"))
        set_gtk_property!(v, :tab_width, opt("Editor", "tab_width"))
        set_gtk_property!(v, :insert_spaces_instead_of_tabs, true)

        sc = GtkScrolledWindow()
        push!(sc, v)

        search_con = GtkSourceSearchContext(b, _editor(main_window).search_window.search_settings)
        highlight(search_con, true)

        t = new(sc.handle, v, b, filename, 0, false, search_con, nothing, nothing)
        t.eval_in = Main
        Gtk.gobject_move_ref(t, sc)
    end
    EditorTab(main_window::MainWindow) = EditorTab("", main_window)
end

function set_text!(t::EditorTab, text::String)
    set_gtk_property!(t.buffer, :text, text)
end
get_text(t::EditorTab) = get_gtk_property(t.buffer, :text, String)

include("CompletionWindow.jl")
include("SearchWindow.jl")

function check_texthash(t::EditorTab, editor)
    try
        f = Base.open(t.filename, "r")
        text = read(f, String)
        if hash(text) != t.texthash
            ok = ask_dialog("File has been modified by external program, save anyway?", editor.main_window)
            !ok && return false
        end
        close(f)
    catch err
        @warn "Error while saving $(t.filename)"
        @warn err
    end
    true
end

function save(t::EditorTab)

    editor = parent(t)

    if basename(t.filename) == ""
        save_as(t)
        return
    end
    !check_texthash(t, editor) && return
    try
        f = Base.open(t.filename, "w")
        text = get_text(t)
        write(f, text)
        close(f)
        t.texthash = hash(text)
        modified(t, false)
        if extension(t.filename) == ".jl"
            t.autocomplete_words = collect_symbols(t)
        end
    catch err
        @warn "Error while saving $(t.filename)"
        @warn err
    end
end

function save_as(t::EditorTab)
    extensions = (".jl", ".md")
    selection = Gtk.save_dialog("Save as file", Gtk.toplevel(t), map(x->string("*", x), extensions))
    isempty(selection) && return nothing
    #basename, ext = splitext(selection)
    t.filename = selection
    save(t)
end

function open_in_new_tab(filename::String, editor; line=0)#FIXME type this, but Editor not defined at this point
    t = add_tab(filename, editor)
    t.scroll_target_line = max(0, line-1)
    open(t, t.filename)
    return t
end
open_in_new_tab(filename::String; line=0) =
    open_in_new_tab(filename, main_window.editor;line=line)#need this for console command

function set_font(t::EditorTab, provider::GtkStyleProvider)
    sc = Gtk.G_.style_context(t.view)
    push!(sc, provider, 600)
end

function istextfile(t::EditorTab)
    fext = extension(t.filename)
    for ext in [".md", ".txt"]
        fext == ext && return true
    end
    false
end

function get_cell(buffer::GtkTextBuffer)

    (foundb, itb_start, itb_end) = search(buffer, "##", :backward)
    (foundf, itf_start, itf_end) = search(buffer, "##", :forward)

    if foundf && !foundb
        return(true, mutable(GtkTextIter(buffer, 1)), itf_end) #start of file
    end

    return((foundf && foundb), itb_start, itf_end)
end

function highlight_cells()

    Gtk.apply_tag(
        srcbuffer, "background",
        GtkTextIter(srcbuffer, 1), GtkTextIter(srcbuffer, length(srcbuffer)+1)
    )
    (found, it_start, it_end) = get_cell(srcbuffer)

    if found
        Gtk.apply_tag(srcbuffer, "cell", it_start , it_end )
    end
end

hasselection(t::EditorTab) = hasselection(t.buffer)

function selected_text(t::EditorTab)
    (found, it_start, it_end) = selection_bounds(t.buffer)
    return found ? (it_start:it_end).text[String] : ""
end

"""
    Opens file at line or switch to it if already opened.
"""
function open_tab(file, editor; line=0)

    file = normpath(file)
    if ispath(file)
        #first look in existing tabs if the file is already open
        for i = 1:length(editor)
            n = editor[i]
            if typeof(n) == EditorTab && n.filename == file

                index(editor, i)
                if line != 0
                    it = GtkTextIter(n.buffer, line, 1)
                    scroll_to(n.view, it, 0, true, 0.0, 0.15)#FIXME use mark instead ? use Gtk's scroll_to
                    place_cursor(n.buffer, it)
                end
                grab_focus(n.view)
                return true
            end
        end
        #otherwise open it
        t = open_in_new_tab(file, editor, line=line)
    else
        #create new file
        t = open_in_new_tab(file, editor, line=line)
    end
    return true
end

function open_method(view::GtkTextView, editor)#FIXME type this, but Editor not defined at this point

    word = get_word_under_mouse_cursor(view)

    try
        ex = Meta.parse(word)

        v = Core.eval(Main, ex)
        v = typeof(v) <: Function ? methods(v) : v

        file, line = method_filename(v)
        file = string(file)
        file = ispath(file) ? file : joinpath( joinpath(splitdir(Sys.BINDIR)[1], "share/julia/base"), file)

        open_tab(file, editor; line=line)
    catch err
        @warn err
    end
    return false
end

function line_to_adj_value(buffer::GtkTextBuffer, adj::GtkAdjustment, l::Integer)
    tot = line_count(buffer)
    scaling = get_gtk_property(adj, :upper, AbstractFloat) #-
              #get_gtk_property(adj, :page_size, AbstractFloat)

    return l/tot * scaling
end

#clicks

function select_word_double_click(textview::GtkTextView, buffer::GtkTextBuffer, x::Integer, y::Integer)

    x, y  = Gtk.window_to_buffer_coords(textview, x, y)
    iter_end = Gtk.text_iter_at_position(textview, x, y)
    #iter_end = mutable( get_text_iter_at_cursor(buffer) ) #not using this because the cursor position is modified somewhere

    w, iter_start, iter_end = select_word(iter_end, buffer)
    select_range(buffer, iter_start, iter_end)
end

@guarded (INTERRUPT) function tab_button_press_cb(widgetptr::Ptr, eventptr::Ptr, user_data)

    textview = convert(GtkTextView, widgetptr)
    event = convert(Gtk.GdkEvent, eventptr)
    buffer = get_gtk_property(textview, :buffer, GtkTextBuffer)
    editor = user_data

    if event.event_type == Gtk.GdkEventType.DOUBLE_BUTTON_PRESS
        select_word_double_click(textview, buffer, round(Integer, event.x), round(Integer, event.y))
        return INTERRUPT
    end

    mod = get_default_mod_mask()

    if Int(event.button) == 1 && event.state & mod == PrimaryModifier
        open_method(textview, editor) && return INTERRUPT
    end

    return PROPAGATE
end

function replace_text(buffer::GtkTextBuffer, itstart::T, itend::T, str::String) where {T <: Gtk.TI}
    pos = offset(itstart)+1
    splice!(buffer, itstart:itend)
    insert!(buffer, GtkTextIter(buffer, pos), str)
end

# returns the position of the cursor inside a buffer such that we can position a window there
function get_cursor_absolute_position(view::GtkTextView)

    it, r1, r2 = Gtk.cursor_locations(view)
    x, y = Gtk.buffer_to_window_coords(view, r1.x, r1.y, 1)

    w = Gtk.GAccessor.window(view)
    ox, oy = Gtk.get_origin(w)

    return (x+ox, y+oy+r1.height, r1.height)
end

function run_line(console::Console, t::EditorTab)

    cmd = selected_text(t)
    if cmd == ""
        (cmd, itstart, itend) = get_current_line_text(t.buffer)
        cmd = strip(cmd)
    end
    run_command(console, cmd)
end

function run_command(c::Console, cmd)
    GtkREPL.command(c, cmd)
    GtkREPL.on_return(c, cmd)
end

@guarded (PROPAGATE) function editor_key_release_cb(widgetptr::Ptr, eventptr::Ptr, user_data)

    @warn "loading data"
    textview = convert(GtkTextView, widgetptr)
    event = convert(Gtk.GdkEvent, eventptr)
    buffer = textview.buffer[GtkTextBuffer]
    editor = user_data

    @warn "updating completion window"
    !update_completion_window_release(event, buffer, editor) && return convert(Cint, true)
    @warn "done"

    return PROPAGATE
end
##

@guarded (INTERRUPT) function editor_tab_key_press_cb(widgetptr::Ptr, eventptr::Ptr, user_data)

    textview = convert(GtkTextView, widgetptr)
    event = convert(Gtk.GdkEvent, eventptr)
    buffer = textview.buffer[GtkTextBuffer]
    t = user_data
    editor = parent(t)::Editor
    console = current_console(editor)

    doing(Actions["save"], event) && save(t)
    doing(Actions["open"], event) && openfile_dialog()

    if doing(Actions["closetab"], event)
        close_tab(editor)
        save(project)
    end
    if doing(Actions["newtab"], event)
        add_tab(editor)
        save(project)
    end
    if doing(Actions["datahint"], event)
        show_data_hint(textview, t)
    end
    if doing(Actions["search"], event)
        open(editor.search_window, t)
    end
    if event.keyval == GdkKeySyms.Tab
        if !visible(completion_window)
            return init_autocomplete(textview, t; key=:tab)
        end
    end
    if event.keyval == GdkKeySyms.F3
        if !visible(completion_window)
            return init_autocomplete(textview, t; key=:ctrl_tab)
        end
    end
    if doing(Actions["runline"], event) || doing(Actions["runline_kp"], event)
        run_line(console, t)
        return convert(Cint, true)
    end
    if doing(Actions["runcode"], event) || doing(Actions["runcode_kp"], event)
        run_code(console, t)
        return INTERRUPT
    end
    if doing(Actions["runfile"], event)
        cmd = "include(\"$(t.filename)\")"
        cmd = replace(cmd, "\\" => "/")
        run_command(console, cmd)
    end
    if event.keyval == GdkKeySyms.Escape
        set_search_text(editor.search_window.search_settings, "")
        visible(editor.search_window, false)
    end
    if doing(Actions["copy"], event)
        (found, it_start, it_end) = selection_bounds(buffer)
        if !found
            (txt, its, ite) = get_line_text(buffer, get_text_iter_at_cursor(buffer))
            select_range(buffer, its, ite)
        end
        signal_emit(textview, "copy-clipboard", Nothing)
        return INTERRUPT
    end
    if doing(Actions["paste"], event)
        signal_emit(textview, "paste-clipboard", Nothing)
        return INTERRUPT
    end
    if doing(Actions["cut"], event)
        (found, it_start, it_end) = selection_bounds(buffer)
        if !found
            (txt, its, ite) = get_line_text(buffer, get_text_iter_at_cursor(buffer))
            select_range(buffer, its, ite)
        end
        signal_emit(textview, "cut-clipboard", Nothing)

        return INTERRUPT
    end
    if doing(Actions["move_to_line_start"], event) ||
       doing(Action(GdkKeySyms.Left, PrimaryModifier), event)
        move_cursor_to_sentence_start(buffer)
        return INTERRUPT
    end
    if doing(Actions["move_to_line_end"], event) ||
       doing(Action(GdkKeySyms.Right, PrimaryModifier), event)
        move_cursor_to_sentence_end(buffer)
        return INTERRUPT
    end
    if doing(Action(GdkKeySyms.Right, PrimaryModifier+GdkModifierType.SHIFT), event)
        select_on_ctrl_shift(:end, buffer)
        return INTERRUPT
    end
    if doing(Action(GdkKeySyms.Left, PrimaryModifier+GdkModifierType.SHIFT), event)
        select_on_ctrl_shift(:start, buffer)
        return INTERRUPT
    end
    if doing(Action(GdkKeySyms.Down, PrimaryModifier), event)
        move_cursor_to_next_cell(buffer, textview, :down)
        return INTERRUPT
    end
    if doing(Action(GdkKeySyms.Up, PrimaryModifier), event)
        move_cursor_to_next_cell(buffer, textview, :up)
        return INTERRUPT
    end
    if doing(Actions["toggle_comment"], event)
        user_action(toggle_comment, buffer)#make sure undo works
    end
    if doing(Actions["undo"], event)
        canundo(buffer) && undo!(buffer)
        return INTERRUPT
    end
    if doing(Actions["redo"], event)
        canredo(buffer) && redo!(buffer)
        return INTERRUPT
    end
    if doing(Actions["delete_line"], event)
        (found, itstart, itend) = selection_bounds(buffer)
        if found
            itstart = text_iter_line_start(nonmutable(buffer, itstart))#FIXME need a mutable version
            !get_gtk_property(itend, :ends_line, Bool) && skip(itend, :forward_to_line_end)
            splice!(buffer, itstart-1:itend)
        else
            (cmd, itstart, itend) = get_current_line_text(buffer)
            splice!(buffer, itstart-1:itend)
        end
    end
    if doing(Actions["duplicate_line"], event)
        (cmd, itstart, itend) = get_current_line_text(buffer)
        insert!(buffer, itend, "\n" * cmd)
    end
    if doing(Actions["goto_line"], event)
        ok, v = input_dialog("Line number", "1", (("Cancel", 0), ("Ok", 1)), editor.main_window)
        if ok == 1
            v = Meta.parse(v)
            if typeof(v) <: Integer
                scroll_to_line(t, v)
            else
                println("Invalid line number: $v")
            end
        end
    end
    if doing(Actions["extract_method"], event)
        return user_action(editor_extract_method, buffer)
    end
    !update_completion_window(event, buffer, t) && return INTERRUPT

    return PROPAGATE
end

##

function editor_extract_method(buffer::GtkTextBuffer)
    (found, itstart, itend) = selection_bounds(buffer)
    body = found ? (itstart:itend).text[String] : ""
    body == "" && return PROPAGATE

    insert_offset = offset(itstart)

    tabw = opt("Editor", "tab_width")
    tab = " "^tabw
    met = Refactoring.extract_method(body, tab)

    replace_text(buffer, itstart, itend, met)
    it = GtkTextIter(buffer, insert_offset + sizeof("function ")+2) #FIXME probable offset issue
    place_cursor(buffer, it)

    return INTERRUPT
end

function toggle_comment(buffer::GtkTextBuffer)

    (found, it_start, it_end) = selection_bounds(buffer)
    if found
        for i in line(it_start):line(it_end)
            toggle_comment(buffer, GtkTextIter(buffer, i, 1))
        end
    else
        it = get_text_iter_at_cursor(buffer)
        toggle_comment(buffer, it)
    end
end
function toggle_comment(buffer::GtkTextBuffer, it::GtkTextIter)

    it = text_iter_line_start(it)#start of the text
    it_ls = GtkTextIter(buffer, line(it), 1)#start of the line

    if get_text_right_of_iter(it_ls) == "#"
        splice!(buffer, it_ls:it_ls+1)
    else
        if get_text_right_of_iter(it) == "#"
            splice!(buffer, it:it+1)
        else
            insert!(buffer, it_ls, "#")
        end
    end
end

function run_code(console::Console, t::EditorTab)
    cmd = selected_text(t)
    if cmd == ""
        (found, it_start, it_end) = get_cell(t.buffer)
        if found
            cmd = (it_start:it_end).text[String]
        else
            cmd = get_gtk_property(t.buffer, :text, String)
        end
    end
    run_command(console, cmd)
end

function get_word_under_mouse_cursor(textview::GtkTextView)
    x, y = Gtk.window_to_buffer_coords(textview, mousepos[1], mousepos[2])
    iter_end = Gtk.text_iter_at_position(textview, x, y)
    buffer = textview.buffer[GtkTextBuffer]
    word, itstart, itend = select_word(iter_end, buffer, false)
    return word
end

function show_data_hint(textview::GtkTextView, t::EditorTab)

    word = get_word_under_mouse_cursor(textview)

    try
        if extension(t.filename) == ".md"

        else
            ex = Meta.parse(word)
            isnothing(ex) && return

            c = current_console(parent(t))

            v = remotecall_fetch(GtkREPL.eval_symbol, worker(c), ex, c.eval_in)
            v = GtkREPL.RemoteGtkREPL.format_output(v)

            doc = remotecall_fetch(GtkREPL.RemoteGtkREPL.get_doc, worker(c), ex, c.eval_in)

            v = string(v, "\n\n")
            doc = string("\n", doc)
        end

        # sp = parent(t).main_window.style_and_language_manager.main_style
        # style = GtkSourceWidget.style(sp, "text")

        style_mng = parent(t).main_window.style_and_language_manager
        style = get_style(style_mng, "text")

        mc = MarkdownColors(
            style_mng.fontsize,
            Gtk.get_gtk_property(style, :foreground, String),
            Gtk.get_gtk_property(style, :background, String),
            Gtk.get_gtk_property(get_style(style_mng, "def:note"), :foreground, String),
            Gtk.get_gtk_property(style, :background, String),
        )

        view = MarkdownTextView(doc, v, mc)

        popup = GtkWindow("", 800, 400, true, true) |> GtkScrolledWindow(view)
        set_gtk_property!(view, :margin, 3)
        signal_connect(data_hint_window_key_press_cb, popup, "key-press-event", Cint, (Ptr{Gtk.GdkEvent}, ), false)
        signal_connect(data_hint_window_focus_out_cb, popup, "focus-out-event", Cint, (Ptr{Gtk.GdkEvent}, ), false)

        Gtk.G_.position(popup, mousepos_root[1]+10, mousepos_root[2])
        showall(popup)

    catch err
        @warn err
    end
end

@guarded (INTERRUPT) function data_hint_window_focus_out_cb(widgetptr::Ptr, eventptr::Ptr, user_data)
    w = convert(GtkWindow, widgetptr)
    destroy(w)
    return INTERRUPT
end

#    if doing(Actions["copy"], event)
#        signal_emit(textview, "copy-clipboard", Nothing)
#        return INTERRUPT
#    end

@guarded (INTERRUPT) function data_hint_window_key_press_cb(widgetptr::Ptr, eventptr::Ptr, user_data)
    w = convert(GtkWindow, widgetptr)
    event = convert(Gtk.GdkEvent, eventptr)

    if doing(Action(GdkKeySyms.Escape, NoModifier), event)
        destroy(w)
    end
    return PROPAGATE
end

value(adj::GtkAdjustment) = get_gtk_property(adj, :value, AbstractFloat)
value(adj::GtkAdjustment, v::AbstractFloat) = set_gtk_property!(adj, :value, v)

# maybe I should replace this by a task that check for the
# end of loading and then call a function
function tab_adj_changed_cb(adjptr::Ptr, user_data)

    #FIXME need to check if the scroll target is valid somehow
    adj = convert(GtkAdjustment, adjptr)
    t = user_data
    if t.scroll_target != 0 && t.scroll_target_line == 0
        if value(adj) != t.scroll_target
            value(adj, t.scroll_target)
        else
            t.scroll_target = 0
        end
    end

    if t.scroll_target_line != 0
        v = line_to_adj_value(get_buffer(t.view), adj, t.scroll_target_line)
        if value(adj) != v
            value(adj, v)
        else
            t.scroll_target_line = 0
        end
    end

    return nothing
end

function scroll_to_line(t::EditorTab, l::Integer)

    adj = get_gtk_property(t, :vadjustment, GtkAdjustment)
    v = line_to_adj_value(get_buffer(t.view), adj, l)
    v = max(0, v - get_gtk_property(adj, :step_increment, AbstractFloat))
    value(adj, v)
end

function modified(t::EditorTab, v::Bool)
    t.modified = v
    f = basename(t.filename)
    f = f == "" ? "Untitled" : f

    s = v ? f * "*" : f

    set_gtk_property!(t.label, :label, s)
end

function tab_buffer_changed_cb(widgetptr::Ptr, user_data)
    t = user_data
    modified(t, true)

    return nothing
end

@guarded (PROPAGATE) function input_dialog_key_press_cb(widgetptr::Ptr, eventptr::Ptr, user_data)

    dialog = convert(GtkMessageDialog, widgetptr)
    event = convert(Gtk.GdkEvent, eventptr)

    if doing(Action(GdkKeySyms.Return, NoModifier), event)
        response(dialog, 1)
        return INTERRUPT
    end
    if doing(Action(GdkKeySyms.Escape, NoModifier), event)
        response(dialog, 0)
        return INTERRUPT
    end

    return PROPAGATE
end

#FIXME put this into Gtk.jl ?
import Gtk.input_dialog
function input_dialog(message::String, entry_default::String, buttons = (("Cancel", 0), ("Accept", 1)), parent = GtkNullContainer())
    widget = GtkMessageDialog(message, buttons, Gtk.GtkDialogFlags.DESTROY_WITH_PARENT, Gtk.GtkMessageType.INFO, parent)

    box = Gtk.content_area(widget)
    entry = GtkEntry(; text = entry_default)
    push!(box, entry)

    signal_connect(input_dialog_key_press_cb, widget, "key-press-event",
    Cint, (Ptr{Gtk.GdkEvent}, ), false)

    showall(widget)
    resp = run(widget)
    entry_text = get_gtk_property(entry, :text, String)
    destroy(widget)
    return resp, entry_text
end

@guarded (nothing) function move_cursor_to_next_cell(buffer, textview, direction = :down)

    (found, it_start, it_end) = search(buffer, "##", direction == :down ? :forward : :backward)
    !found && return

    # if we are just bellow a cell going up, skip the ##
    it = get_text_iter_at_cursor(buffer)
    if (direction == :up) && (it.line[Int]-1 == it_start.line[Int])
        place_cursor(buffer, it_start)
        (found, it_start, it_end) = search(buffer, "##", :backward)
        !found && return
    end

    skip(it_start, 1, :lines)#make sure the cursor is in the cell
    place_cursor(buffer, it_start)
    mark = create_mark(buffer, it_start)
    scroll_to(textview, mark, 0, true, 0.0, 0.15)
    nothing
end


text:
"""
    augmentQ(qq, ww, js, iq, qrows)

Copy the eigenvectors corresponding to the largest roots into the
remaining empty rows and columns js of q
"""
function augmentQ!(qq::Array{Float64,2}, ww::Array{Float64,2}, js::Array{Int64,2}, iq::Int64, qrows::Int64)

    if(iq < qrows)
        lastrows = (iq + 1) : qrows
        wrows    = 1 : length(lastrows)
        qq[lastrows, js] = ww[:, wrows]'
    end

    return qq

end # augmentQ


text:
# This package can solve two player dynamic game by collocation method
module DynamicGame

using BasisMatrices
using QuantEcon
using Distributions

export
vmax, coll, collocation_method, residual

# update value function and policy function given the basis coefficient
function vmax(model,
    x::Array{Float64, 2},
    colnodes::Array{Float64, 2},
    b,
    coef::Array{Float64, 2},
    epss::Array{Float64, 2},
    weights::Array{Float64, 1},
    u,
    ux,
    uxx,
    s,
    sx,
    sxx,
    tol=0.000000001,
    maxit=10000)

    xnew = x
    v = zeros((size(colnodes)[1], 2))
    vnew = v
    for p in 1:2
        xl, xu = 0.0, colnodes[:, p]
        order1 = [0 0]
        order1[1, p] = 1
        order2 = [0 0]
        order2[1, p] = 2
        for it in 1:maxit
            util, util_der1, util_der2 = u(model, colnodes, xnew, p), ux(model, colnodes, xnew, p), uxx(model, colnodes, xnew, p)
            Ev, Evx, Evxx = 0.0, 0.0, 0.0
            for k in 1:size(epss)[1]
                eps, weight= epss[k, :], weights[k]
                transition, transition_der1, transition_der2 = s(model, xnew, eps), sx(model, xnew, eps, p), sxx(model, xnew, eps, p)
                vn = funeval(coef[:, p], b, transition)
                vnder1 =  funeval(coef[:, p], b, transition, order1)
                vnder2 = funeval(coef[:, p], b, transition, order2)
                Ev += weight *vn
                Evx += weight* vnder1.* transition_der1
                Evxx += weight * (vnder1.*transition_der2 + vnder2 .* (transition_der1.^2))
            end
            v[:, p] = util + model.delta*Ev
            delx = -(util_der1 + model.delta * Evx) ./ (util_der2 + model.delta*Evxx)
            delx = min.(max.(delx, xl-xnew[:, p]), xu-xnew[:, p])
            xnew[:, p] = x[:, p] + delx
            if norm(delx) < tol
                break
            end
        end
        vnew[:, p] = v[:, p]
    end
    return vnew, xnew
end

# generate elements for collocation method
function coll(smax::Int64, smin::Int64, n::Int64)
    # smax is the maximum of the state variable
    # smin is the minimum of the state variable
    # n is the number of grid for one dimension
    sgrid0 = linspace(smin, smax, n)
    basis = Basis(SplineParams(sgrid0, 0, 3), SplineParams(sgrid0, 0, 3))
    S, (coordx, coordy) = nodes(basis)
    Φ = BasisMatrix(basis, Expanded(), S, 0)
    return basis, S, Φ, coordx, coordy
end

# collocationmethod main loop
function collocation_method(model,
    x_initial::Array{Float64, 2},
    c_initial::Array{Float64, 2},
    S::Array{Float64,2},
    basis,
    Φ,
    e::Array{Float64,2},
    w::Array{Float64,1},
    u,
    ux,
    uxx,
    s,
    sx,
    sxx,
    maxit = 1000,
    tol = 0.000000001)

    c = c_initial
    x = x_initial
    c_error = c
    count = 0
    for it in 1:maxit
        cold = c
        vnew, x = vmax(model, x, S, basis, c, e, w, u, ux, uxx, s, sx, sxx)
        c = Φ.vals[1] \ vnew
        v = vnew
        c_error = cold - c
        count += 1
        if maximum(abs, cold - c) < tol
            print(maximum(abs, cold - c) )
            break
        end
    end
    return x, vnew, c
end

# Bellman_residual calculation
# true_x, c is provided by the above collocation method function
function residual(model,
    newn::Int64,
    smin::Int64,
    smax::Int64,
    true_x::Array{Float64, 2},
    basis,
    c::Array{Float64, 2},
    e::Array{Float64,2},
    w::Array{Float64,1},
    u,
    ux,
    uxx,
    s,
    sx,
    sxx)

    gri = linspace(smin, smax, nn)
    new_grid = gridmake(gri, gri)

    c_x =Φ.vals[1] \ true_x
    newx = funeval(c_x, basis, new_grid)

    v_true = vmax(model, newx[:,:, 1], new_grid, basis, c, e, w, u, ux, uxx, s, sx, sxx)[1][:, 1];
    predict_value = funeval(c, basis, new_grid)[:, 1];

    resid = reshape(v_true - predict_value, nn, nn)
    return resid
end

end


text:
module CollegeEntry

# Distributions only needed for simulations.
using ModelParams: get_object_id
using ArgCheck, Distributions, DocStringExtensions, Lazy, Random
using CommonLH, EconLH, LatexLH, StructLH, ModelObjectsLH, ModelParams

# Entry decisions
export AbstractEntryDecision, AbstractEntrySwitches,
    EntryDecision, EntryDecisionSwitches
export init_entry_decision, entry_probs, fix_entry_probs!, scale_entry_probs!,
    fix_entry_pref_scale!,
    min_entry_prob, max_entry_prob, entry_probs_fixed, entry_pref_scale, subset_types, subset_types!

# Admissions rules
export AbstractAdmissionsRule, AbstractAdmissionsSwitches, AdmissionsOpenSwitches, AdmissionsOpen, AdmissionsCutoffSwitches, AdmissionsCutoff, AdmissionsOneVarSwitches, AdmissionsOneVar
export n_colleges, n_college_sets, college_set, open_admission, admission_probs, prob_coll_set, prob_coll_sets, make_admissions, validate_admissions

# Admission probabilities
export AbstractAdmProbFctSwitches, AbstractAdmProbFct,
    AdmProbFctLogisticSwitches, AdmProbFctLogistic,
    AdmProbFctOpenSwitches, AdmProbFctOpen,
    AdmProbFctLinearSwitches, AdmProbFctLinear,
    AdmProbFctStepSwitches, AdmProbFctStep
export init_admprob_fct_logistic_switches, init_admprob_fct_step_switches, init_admprob_fct, make_admprob_function,  prob_admit
export by_college, by_college!

# Complete entry decisions
export entry_decisions
export colleges_full, capacities, capacities_c, limited_capacity, n_locations, n_types, total_mass
export set_capacities!, increase_capacity!, increase_capacities!, set_local_only_colleges!

# Student rankings
export AbstractRankingSwitches, AbstractRanking, EndowPctRankingSwitches, EndowPctRanking
export make_entry_switches_oneloc, validate_es, set_bounds!
export rank_students, score_students, scale_scores, range_of_scores, make_student_ranking, validate_ranking, validate_ranking_switches, retrieve_draws, n_draws, endow_names

# Results
export AbstractEntryResults, EntryResults, validate_er
export frac_local, frac_local_j, frac_local_c, n_locations, n_colleges, n_types, type_mass_jl, type_mass_j, capacities, enrollment_cl, enrollment_c, entry_probs_jlc, entry_probs_jc, entry_probs_j, expected_values_jl, frac_best_c
export make_test_entry_results

include("helpers.jl")
include("test_helpers.jl")

# Student rankings
include("ranking_types.jl");
include("ranking_endow_pct.jl");

# Admission probabilities
include("admission_prob_functions.jl");

# Admissions rules
include("admissions_types.jl");
include("admissions_open_types.jl");
include("admissions_cutoff_types.jl");
include("admissions_one_indicator.jl");

# Entry decisions
include("types.jl")
include("access_routines.jl")
include("generic.jl")
# include("entry_one_step.jl")
# include("entry_two_step.jl")
# Sequential assignment
# include("sequential.jl")
include("sequential_multi_locations.jl")
include("simulations.jl")

include("entry_results.jl")

end # module


text:
module CEnum

abstract type Cenum{T} end

Base.:|(a::T, b::T) where {T<:Cenum{UInt32}} = UInt32(a) | UInt32(b)
Base.:|(a::T, b::UInt32) where {T<:Cenum{UInt32}} = UInt32(a) | b
Base.:|(a::UInt32, b::T) where {T<:Cenum{UInt32}} = b | a

Base.:&(a::T, b::T) where {T<:Cenum{UInt32}} = UInt32(a) & UInt32(b)
Base.:&(a::T, b::UInt32) where {T<:Cenum{UInt32}} = UInt32(a) & b
Base.:&(a::UInt32, b::T) where {T<:Cenum{UInt32}} = b & a

Base.:(==)(a::Integer, b::Cenum{T}) where {T<:Integer} = a == T(b)
Base.:(==)(a::Cenum, b::Integer) = b == a

# typemin and typemax won't change for an enum, so we might as well inline them per type
Base.typemax(::Type{T}) where {T<:Cenum} = last(enum_values(T))
Base.typemin(::Type{T}) where {T<:Cenum} = first(enum_values(T))

Base.convert(::Type{Integer}, x::Cenum{T}) where {T<:Integer} = Base.bitcast(T, x)
Base.convert(::Type{T}, x::Cenum{T2}) where {T<:Integer,T2<:Integer} = convert(T, Base.bitcast(T2, x))

(::Type{T})(x::Cenum{T2}) where {T<:Integer,T2<:Integer} = T(Base.bitcast(T2, x))::T
(::Type{T})(x) where {T<:Cenum} = convert(T, x)

Base.write(io::IO, x::Cenum) = write(io, Int32(x))
Base.read(io::IO, ::Type{T}) where {T<:Cenum} = T(read(io, Int32))

enum_values(::T) where {T<:Cenum} = enum_values(T)
enum_names(::T) where {T<:Cenum} = enum_names(T)

is_member(::Type{T}, x::Integer) where {T<:Cenum} = is_member(T, enum_values(T), x)

@inline is_member(::Type{T}, r::UnitRange, x::Integer) where {T<:Cenum} = x in r
@inline function is_member(::Type{T}, values::Tuple, x::Integer) where {T<:Cenum}
    lo, hi = typemin(T), typemax(T)
    x<lo || x>hi && return false
    for val in values
        val == x && return true
        val > x && return false # is sorted
    end
    return false
end

function enum_name(x::T) where {T<:Cenum}
    index = something(findfirst(isequal(x), enum_values(T)), 0)
    if index != 0
        return enum_names(T)[index]
    end
    @error "Invalid enum: $(Int(x)), name not found"
end

Base.show(io::IO, x::Cenum) = print(io, enum_name(x), "($(Int(x)))")

function islinear(array)
    isempty(array) && return false # false, really? it's kinda undefined?
    lastval = first(array)
    for val in Iterators.rest(array, 2)
        val-lastval == 1 || return false
    end
    return true
end

macro cenum(name, args...)
    if Meta.isexpr(name, :curly)
        typename, type = name.args
        typename = esc(typename)
        typesize = 8*sizeof(getfield(Base, type))
        typedef_expr = :(primitive type $typename <: CEnum.Cenum{$type} $typesize end)
    elseif isa(name, Symbol)
        # default to UInt32
        typename = esc(name)
        type = UInt32
        typedef_expr = :(primitive type $typename <: CEnum.Cenum{UInt32} 32 end)
    else
        error("Name must be symbol or Name{Type}. Found: $name")
    end
    lastval = -1
    name_values = map([args...]) do arg
        if isa(arg, Symbol)
            lastval += 1
            val = lastval
            sym = arg
        elseif arg.head == :(=) || arg.head == :kw
            sym,val = arg.args
        else
            error("Expression of type $arg not supported. Try only symbol or name = value")
        end
        (sym, val)
    end
    sort!(name_values, by=last) # sort for values
    values = map(last, name_values)

    if islinear(values) # optimize for linear values
        values = :($(first(values)):$(last(values)))
    else
        values = :(tuple($(values...)))
    end
    value_block = Expr(:block)

    for (ename, value) in name_values
        push!(value_block.args, :(const $(esc(ename)) = $typename($value)))
    end

    expr = quote
        $typedef_expr
        function Base.convert(::Type{$typename}, x::Integer)
            is_member($typename, x) || Base.Enums.enum_argument_error($(Expr(:quote, name)), x)
            Base.bitcast($typename, convert($type, x))
        end
        CEnum.enum_names(::Type{$typename}) = tuple($(map(x-> Expr(:quote, first(x)), name_values)...))
        CEnum.enum_values(::Type{$typename}) = $values
        $value_block
    end
    expr
end
export @cenum

end # module


text:
include("src/base.jl")
include("src/envs/classiccontrol_mdp.jl")
include("src/policies/deep_crossentropy_policy.jl")
include("src/solvers/deep_crossentropy_policy_solver.jl")

gym_env = ClassicControlMDP(gym.make("CartPole-v0")[:env])
solver = DeepCrossentropyPolicySolver(100, 100, 0.7; max_frame_iterations = 200, print_every_n = 25, nnet_spec = [20, 10])
policy = solve(solver, gym_env, verbose = true)

# print(policy.action_map)

max_stars_repo_name: dmitrijsc/practical-rl

max_issues_repo_name: dmitrijsc/practical-rl

max_forks_repo_name: dmitrijsc/practical-rl


text:
### TODO: add Adaptive Metropolis-within Gibbs (AMWG) mcsampler and complete BUGS rats example

using Klara

x, = dataset("rats", "age")

Y, = dataset("rats", "weight")


text:
# variant 1:
x = 9
function funscope(n)
  x = 0 # x is in the local scope of the function
  for i = 1:n
    local x # x is local to the for loop
    x = i + 1
    if (x == 7)
        println("This is the local x in for: $x") #> 7
    end
  end
  println("This is the local x in funscope: $x") #> 0
  global x = 15
end
funscope(10)
println("This is the global x: $x") #> 15
#=
This is the local x in for: 7
This is the local x in funscope: 0
This is the global x: 15
=#

# variant 2:
x = 9
function funscope(n)
  x = 0
  for i = 1:n
    x = i + 1
    if (x == 7)
        println("This is the local x in funscope: $x") #> 7
    end
  end
  println("This is the local x in funscope: $x") #> 11
  global x = 15
end
funscope(10)
println("This is the global x: $x") #> 15
#=
This is the local x in funscope: 7
This is the local x in funscope: 11
This is the global x: 15
=#

# variant 3:
x = 9
function funscope(n)
  x = 0
  for i = 1:n
    x = i + 1
    if (x == 7)
        println("This is the local x in for: $x") #> 7
    end
  end
  println("This is the local x in funscope: $x") #> 11
end
funscope(10)
println("This is the global x: $x") #> 9
#=
This is the local x in for: 7
This is the local x in funscope: 11
This is the global x: 9
=#

# without let:
anon = Array{Any}(undef, 2)
for i = 1:2
  anon[i] = ()-> println(i)
  i += 1
end
anon[1]() #> 2
anon[2]() #> 3

# with let:
anon = Array{Any}(undef, 2)
for i = 1:2
  let i = i
      anon[i] = ()-> println(i)
  end
  i += 1
end
anon[1]() #> 1
anon[2]() #> 2

# combined with begin:
begin
    local x = 1
    let
        local x = 2
        println(x) #> 2
    end
    x
    println(x) #> 1
end

# for-loops and comprehensions:
i = 0
for i = 1:10
end
println(i)  #> 10

i = 0
[i for i = 1:10 ]
println(i)  #> 0


text:
module _Ln2

include("ln2_machin.jl")

end


text:
# """
# Module dffunctions.jl provides tools to read data frames expressing
# data series relevant for LaserLab software
# (e.g, molecular cross sections, filters), and describe them when
# relevant as functions.
# """
using DataFrames
using CSV
using Interpolations
using QuadGK

"""
	CsvG

A struct which describes a simple grammar needed to read CSV files
written with spanish/english characters

# Fields
- `delim::Char`  : Delimiter used (e.g., ',' in english, ';' in spanish)
- `decimal::Char`: Symbol to represent decinal point (',' '.')
"""
struct CsvG  # stands for CSV Grammar
	delim::Char
	decimal::Char
end

spG = CsvG(';',',')  # spanish: decimals represented with ',' delimited with ';'
enG = CsvG(',','.')  # english
enG2 = CsvG('\t','.')  # english with tabs

"""
	Gf

A struct representing a generalized function:

# Fields
- `N::Number`: Normalization constant: pdf(x) = f(x)/N.
- `f::Any`: Any integrable function.
- `pdf::Any`: Normalized to area 1 (PDF).
"""
struct Gf          # general function
	N  ::Number
	f  ::Any
	pdf::Any
end

"""
	load_df_from_csv(path::String, fname::String, csvg::CsvG)

Load a dataframe from a csv file.

# Arguments
- `path::String`: a path to the data.
- `fname::String`: name of the (csv) file expressing the df.
- `csvg=spG`: CVS coding (spanish, default) or english.
"""
function load_df_from_csv(path::String, fname::String, csvg::CsvG, header::Integer=1)
    name   = string(path, "/", fname)
    csvf   = CSV.File(name; header=header, delim=csvg.delim, decimal=csvg.decimal)
    return DataFrame(csvf)
end

"""
	dftof(wl, df::DataFrame, cname::String,
			   bkgnd::Float64=0.0)

Return an interpolated function, valid in range wl.

# Arguments
- `wl`::interpolation range.
- `df::DataFrame`: data frame holding the data.
- `cname::String`: name of the column holding data to be interplated.
- `overflow::Real`: value of the data outside interpolation range.
- `scale::Real`: value to re-scale the data
"""
function dftof(wl, df::DataFrame, cname::String, overflow::Real=0.0, scale::Real=1.0)
    li = LinearInterpolation(wl, df[!,cname])
	return gfpdf_(li, wl[1], wl[end], overflow, scale)
end

function gfpdf_(fi, xmin::Real, xmax::Real, bkgnd::Real=0.0, scale::Real=1.0)
	function fn(x)
	   	if x < xmin || x > xmax
			return bkgnd
		else
			return fi(x) * scale
		end
	end
	return fn
end

"""
	qpdf(f, λmin::Real, λmax::Real)

Return the integral of f in the interval (λmin, λmax)
(Syntactic sugar for quadgk)

# Arguments
- `f::Function`: Function to be integrated.
- `λmin::Number`: lower bound of range.
- `λmax::Number`: upper bound of range.
"""
function qpdf(f, λmin::Real, λmax::Real)
	return quadgk(f, λmin, λmax)[1]
end

"""
	ftopdf(wl, f)

Compute the PDF of function f in range wl.

# Arguments
- `wl`: Range of application.
- `f::Function`: Input function.
"""
function ftopdf(wl, f)
	function pdf(x)
		return f(x) / N
	end
    N = qpdf(f, wl[1], wl[end])
	return N, pdf
end

max_stars_repo_name: proscrite/LaserLab

max_issues_repo_name: proscrite/LaserLab

max_forks_repo_name: proscrite/LaserLab


text:
import Dates

function _compute_interval_nonrounded(start_datetime, current_datetime)
    if start_datetime > current_datetime
        throw(ArgumentError("Start datetime must be less than or equal to current datetime"))
    end
    return current_datetime - start_datetime
end


text:
# This file was generated by the Julia Swagger Code Generator
# Do not modify this file directly. Modify the swagger specification instead.

struct ExpressRouteCircuitsApi <: SwaggerApi
    client::Swagger.Client
end

"""

Creates or updates an express route circuit.
Param: resourceGroupName::String (required)
Param: circuitName::String (required)
Param: parameters::ExpressRouteCircuit (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: ExpressRouteCircuit
"""
function _swaggerinternal_expressRouteCircuitsCreateOrUpdate(_api::ExpressRouteCircuitsApi, resourceGroupName::String, circuitName::String, parameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PUT", ExpressRouteCircuit, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/expressRouteCircuits/{circuitName}", ["azure_auth"], parameters)
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "circuitName", circuitName)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function expressRouteCircuitsCreateOrUpdate(_api::ExpressRouteCircuitsApi, resourceGroupName::String, circuitName::String, parameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_expressRouteCircuitsCreateOrUpdate(_api, resourceGroupName, circuitName, parameters, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function expressRouteCircuitsCreateOrUpdate(_api::ExpressRouteCircuitsApi, response_stream::Channel, resourceGroupName::String, circuitName::String, parameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_expressRouteCircuitsCreateOrUpdate(_api, resourceGroupName, circuitName, parameters, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Deletes the specified express route circuit.
Param: resourceGroupName::String (required)
Param: circuitName::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: Nothing
"""
function _swaggerinternal_expressRouteCircuitsDelete(_api::ExpressRouteCircuitsApi, resourceGroupName::String, circuitName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "DELETE", Nothing, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/expressRouteCircuits/{circuitName}", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "circuitName", circuitName)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function expressRouteCircuitsDelete(_api::ExpressRouteCircuitsApi, resourceGroupName::String, circuitName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_expressRouteCircuitsDelete(_api, resourceGroupName, circuitName, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function expressRouteCircuitsDelete(_api::ExpressRouteCircuitsApi, response_stream::Channel, resourceGroupName::String, circuitName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_expressRouteCircuitsDelete(_api, resourceGroupName, circuitName, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Gets information about the specified express route circuit.
Param: resourceGroupName::String (required)
Param: circuitName::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: ExpressRouteCircuit
"""
function _swaggerinternal_expressRouteCircuitsGet(_api::ExpressRouteCircuitsApi, resourceGroupName::String, circuitName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", ExpressRouteCircuit, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/expressRouteCircuits/{circuitName}", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "circuitName", circuitName)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function expressRouteCircuitsGet(_api::ExpressRouteCircuitsApi, resourceGroupName::String, circuitName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_expressRouteCircuitsGet(_api, resourceGroupName, circuitName, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function expressRouteCircuitsGet(_api::ExpressRouteCircuitsApi, response_stream::Channel, resourceGroupName::String, circuitName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_expressRouteCircuitsGet(_api, resourceGroupName, circuitName, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Gets all the express route circuits in a resource group.
Param: resourceGroupName::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: ExpressRouteCircuitListResult
"""
function _swaggerinternal_expressRouteCircuitsList(_api::ExpressRouteCircuitsApi, resourceGroupName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", ExpressRouteCircuitListResult, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/expressRouteCircuits", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function expressRouteCircuitsList(_api::ExpressRouteCircuitsApi, resourceGroupName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_expressRouteCircuitsList(_api, resourceGroupName, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function expressRouteCircuitsList(_api::ExpressRouteCircuitsApi, response_stream::Channel, resourceGroupName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_expressRouteCircuitsList(_api, resourceGroupName, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Gets all the express route circuits in a subscription.
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: ExpressRouteCircuitListResult
"""
function _swaggerinternal_expressRouteCircuitsListAll(_api::ExpressRouteCircuitsApi, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", ExpressRouteCircuitListResult, "/subscriptions/{subscriptionId}/providers/Microsoft.Network/expressRouteCircuits", ["azure_auth"])
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function expressRouteCircuitsListAll(_api::ExpressRouteCircuitsApi, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_expressRouteCircuitsListAll(_api, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function expressRouteCircuitsListAll(_api::ExpressRouteCircuitsApi, response_stream::Channel, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_expressRouteCircuitsListAll(_api, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Updates an express route circuit tags.
Param: resourceGroupName::String (required)
Param: circuitName::String (required)
Param: parameters::TagsObject (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: ExpressRouteCircuit
"""
function _swaggerinternal_expressRouteCircuitsUpdateTags(_api::ExpressRouteCircuitsApi, resourceGroupName::String, circuitName::String, parameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PATCH", ExpressRouteCircuit, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/expressRouteCircuits/{circuitName}", ["azure_auth"], parameters)
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "circuitName", circuitName)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function expressRouteCircuitsUpdateTags(_api::ExpressRouteCircuitsApi, resourceGroupName::String, circuitName::String, parameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_expressRouteCircuitsUpdateTags(_api, resourceGroupName, circuitName, parameters, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function expressRouteCircuitsUpdateTags(_api::ExpressRouteCircuitsApi, response_stream::Channel, resourceGroupName::String, circuitName::String, parameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_expressRouteCircuitsUpdateTags(_api, resourceGroupName, circuitName, parameters, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

export expressRouteCircuitsCreateOrUpdate, expressRouteCircuitsDelete, expressRouteCircuitsGet, expressRouteCircuitsList, expressRouteCircuitsListAll, expressRouteCircuitsUpdateTags


text:
# Julia translation of http://nbviewer.jupyter.org/github/barbagroup/AeroPython/blob/master/lessons/03_Lesson03_doublet.ipynb
# Lesson 3 doublet

using PyPlot
using Distributions

close("all")
meshgrid(x,y) = (repmat(x',length(y),1),repmat(y,1,length(x)))

N = 50                                # number of points in each direction
x_start, x_end = -2.0, 2.0            # boundaries in the x-direction
y_start, y_end = -1.0, 1.0            # boundaries in the y-direction
x = linspace(x_start, x_end, N)    # creates a 1D-array with the x-coordinates
y = linspace(y_start, y_end, N)    # creates a 1D-array with the y-coordinates

X,Y=meshgrid(x,y)

kappa = 1.0

x_doublet, y_doublet = 0.0, 0.0   # location of the source

function get_velocity_doublet(strength, xd, yd, X, Y):
    """Returns the velocity field generated by a doublet.

    Arguments
    ---------
    strength -- strength of the doublet.
    xd, yd -- coordinates of the doublet.
    X, Y -- mesh grid.
    """
    u = - strength/(2*pi).*((X-xd).^2-(Y-yd).^2)./((X-xd).^2+(Y-yd).^2).^2
    v = - strength/(2*pi)*2.0.*(X-xd).*(Y-yd)./((X-xd).^2+(Y-yd).^2).^2

    return u, v
  end

function get_stream_function_doublet(strength, xd, yd, X, Y):
    """Returns the stream-function generated by a doublet.

    Arguments
    ---------
    strength -- strength of the doublet.
    xd, yd -- coordinates of the doublet.
    X, Y -- mesh grid.
    """
    psi = - strength/(2*pi).*(Y-yd)./((X-xd).^2+(Y-yd).^2)

    return psi
  end

  # computes the velocity field on the mesh grid
u_doublet, v_doublet = get_velocity_doublet(kappa, x_doublet, y_doublet, X, Y)

# computes the stream-function on the mesh grid
psi_doublet = get_stream_function_doublet(kappa, x_doublet, y_doublet, X, Y)

  # plots the streamlines
  size = 10
  PyPlot.figure(figsize=(size, (y_end-y_start)/(x_end-x_start)*size))
  PyPlot.grid(true)
  PyPlot.xlabel("x", fontsize=16)
  PyPlot.ylabel("y", fontsize=16)
  PyPlot.xlim(x_start, x_end)
  PyPlot.ylim(y_start, y_end)
  PyPlot.streamplot(X, Y, u_doublet, v_doublet, density=2, linewidth=1, arrowsize=1, arrowstyle="->")
  PyPlot.scatter(x_doublet, y_doublet, color="#CD2305", s=80, marker="o")

# Freestream and Doublet

  u_inf = 1.0

  # computes the freestream velocity field
  u_freestream = u_inf * ones((N, N))
  v_freestream = zeros((N, N))

  # computes the stream-function
  psi_freestream = u_inf * Y

  u = u_freestream + u_doublet
  v = v_freestream + v_doublet
  psi = psi_freestream + psi_doublet

  # plots the streamlines
  size = 10
  PyPlot.figure(figsize=(size, (y_end-y_start)/(x_end-x_start)*size))
  PyPlot.grid(true)
  PyPlot.xlabel("x", fontsize=16)
  PyPlot.ylabel("y", fontsize=16)
  PyPlot.xlim(x_start, x_end)
  PyPlot.ylim(y_start, y_end)
  PyPlot.streamplot(X, Y, u, v, density=2, linewidth=1, arrowsize=1, arrowstyle="->")
  PyPlot.contour(X, Y, psi, levels=[0.], colors="#CD2305", linewidths=2, linestyles="solid");
  PyPlot.scatter(x_doublet, y_doublet, color="#CD2305", s=80, marker="o")

  # calculates the stagnation points
x_stagn1, y_stagn1 = +sqrt(kappa/(2*pi*u_inf)), 0
x_stagn2, y_stagn2 = -sqrt(kappa/(2*pi*u_inf)), 0

# adds the stagnation points to the figure
PyPlot.scatter([x_stagn1, x_stagn2], [y_stagn1, y_stagn2], color="g", s=80, marker="o");

# computes the pressure coefficient field
cp = 1.0 - (u.^2+v.^2)./u_inf^2

# plots the pressure coefficient field
size = 10
PyPlot.figure(figsize=(1.1*size, (y_end-y_start)/(x_end-x_start)*size))
PyPlot.xlabel("x", fontsize=16)
PyPlot.ylabel("y", fontsize=16)
PyPlot.xlim(x_start, x_end)
PyPlot.ylim(y_start, y_end)
contf = PyPlot.contourf(X, Y, cp, levels=linspace(-2.0, 1.0, 100), extend="both")
cbar = PyPlot.colorbar(contf)
cbar[:set_label](L"$C_p$", fontsize=16)
cbar[:set_ticks]([-2.0, -1.0, 0.0, 1.0])
PyPlot.scatter(x_doublet, y_doublet, color="#CD2305", s=80, marker="o")
PyPlot.contour(X, Y, psi, levels=[0.], colors="#CD2305", linewidths=2, linestyles="solid");
PyPlot.scatter([x_stagn1, x_stagn2], [y_stagn1, y_stagn2], color="g", s=80, marker="o");


text:
using ..AdiabaticModels: AdiabaticModels

abstract type SpectralDensity end

"Discretize a given spectral density for N oscillators. Returns frequencies and couplings."
function discretize(J::SpectralDensity, N::Integer)
    ωⱼ = ω.(Ref(J), N, 1:N)
    cⱼ = c.(Ref(J), N, ωⱼ)
    return ωⱼ, cⱼ
end

"""
    OhmicSpectralDensity{T} <: SpectralDensity

Ohmic density as detailed in:
[Xin He, Jian Liu, J. Chem. Phys. 151, 024105 (2019)](http://aip.scitation.org/doi/10.1063/1.5108736)
"""
struct OhmicSpectralDensity{T} <: SpectralDensity
    ωᶜ::T
    α::T
end

(J::OhmicSpectralDensity)(ω) = π/2 * J.α * ω * exp(-ω / J.ωᶜ)
ω(J::OhmicSpectralDensity, N, j) = -J.ωᶜ * log(1 - j/(N+1))
c(J::OhmicSpectralDensity, N, ωⱼ) = sqrt(J.α * J.ωᶜ/(N+1)) * ωⱼ

"""
    DebyeSpectralDensity{T} <: SpectralDensity

Debye density as detailed in:
[Xin He, Jian Liu, J. Chem. Phys. 151, 024105 (2019)](http://aip.scitation.org/doi/10.1063/1.5108736)
"""
struct DebyeSpectralDensity{T} <: SpectralDensity
    ωᶜ::T
    λ::T
end

(J::DebyeSpectralDensity)(ω) = 2J.λ * J.ωᶜ * ω / (J.ωᶜ^2 + ω^2)
ω(J::DebyeSpectralDensity, N, j) = J.ωᶜ * tan(π/2 * (1 - j/(N+1)))
c(J::DebyeSpectralDensity, N, ωⱼ) = sqrt(2J.λ/(N+1)) * ωⱼ

"""
    AltDebyeSpectralDensity{T} <: SpectralDensity

Standard Debye spectral density but uses an alternative discretization scheme that requires
a cutoff parameter `ωᵐ`.

# References
[Najeh Rekik, Chang-Yu Hsieh, Holly Freedman, Gabriel Hanna, J. Chem. Phys. 138, 144106 (2013)](https://doi.org/10.1063/1.4799272)
"""
struct AltDebyeSpectralDensity{T} <: SpectralDensity
    ωᶜ::T
    λ::T
    ωᵐ::T
end

(J::AltDebyeSpectralDensity)(ω) = 2J.λ * J.ωᶜ * ω / (J.ωᶜ^2 + ω^2)
ω(J::AltDebyeSpectralDensity, N, j) = tan(j * atan(J.ωᵐ / J.ωᶜ) / N) * J.ωᶜ
c(J::AltDebyeSpectralDensity, N, ωⱼ) = sqrt(4J.λ * atan(J.ωᵐ / J.ωᶜ) / (π * N)) * ωⱼ

"""
    SpinBoson(density::SpectralDensity, N::Integer, ϵ, Δ)

Spin boson model with `N` bosons with given spectral density.

# References
[Xin He, Jian Liu, J. Chem. Phys. 151, 024105 (2019)](http://aip.scitation.org/doi/10.1063/1.5108736)
"""
struct SpinBoson{T} <: DiabaticModel
    ϵ::T
    Δ::T
    ωⱼ::Vector{T}
    cⱼ::Vector{T}
end

NQCModels.nstates(::SpinBoson) = 2
NQCModels.ndofs(model::SpinBoson) = 1

function SpinBoson(density::SpectralDensity, N::Integer, ϵ, Δ)
    ωⱼ, cⱼ = discretize(density, N)
    SpinBoson(ϵ, Δ, ωⱼ, cⱼ)
end

function NQCModels.potential(model::SpinBoson, r::AbstractVector)

    Parameters.@unpack ωⱼ, cⱼ, ϵ, Δ = model

    v0 = 0.0
    for i in eachindex(ωⱼ)
        v0 += ωⱼ[i]^2 * r[i]^2 / 2
    end
    V11 = v0 + ϵ
    V22 = v0 - ϵ

    for i in eachindex(model.cⱼ)
        V11 += cⱼ[i] * r[i]
        V22 -= cⱼ[i] * r[i]
    end

    V12 = Δ

    return Hermitian(SMatrix{2,2}(V11, V12, V12, V22))
end

function NQCModels.derivative!(model::SpinBoson, D::AbstractVector{<:Hermitian}, r::AbstractVector)

    Parameters.@unpack ωⱼ, cⱼ = model

    for i in eachindex(r)
        d0 = ωⱼ[i]^2 * r[i]
        D[i] = Hermitian(SMatrix{2,2}(d0 + cⱼ[i], 0, 0, d0 - cⱼ[i]))
    end

    return D
end

"""
    BosonBath(density::SpectralDensity, N::Integer)

Bosonic bath with given spectral density.

Useful for sampling the bath uncoupled from the spin for spin-boson dynamics.
"""
struct BosonBath{T} <: AdiabaticModels.AdiabaticModel
    ωⱼ::Vector{T}
end

NQCModels.ndofs(model::BosonBath) = 1

function BosonBath(density::SpectralDensity, N::Integer)
    ωⱼ, _ = discretize(density, N)
    BosonBath(ωⱼ)
end

function NQCModels.potential(model::BosonBath, r::AbstractVector)
    return sum(model.ωⱼ .^2 .* r .^2 ./ 2)
end

function NQCModels.derivative!(model::BosonBath, D::AbstractVector, r::AbstractVector)
    for i in eachindex(r)
        D[i] = model.ωⱼ[i]^2 * r[i]
    end
end


text:
#=
Julia script to convert data of hills in Czech Republic into useable format ("N50° 44.161 E15° 44.380" is not a nice field)

Original data were downloaded from http://www.peaklist.org/WWlists/euro600/slovakia/Slovakia200m.html
parsed via https://pdftables.com to XLS
and saved in OpenOffice as CSV file after minor modifications

Author: Pavel Perina
Date:   2021-08-31
=#

import CSV
import DataFrames

dfIn  = CSV.File("Slovakia_P200_prominence.csv"; type=String) |> DataFrames.DataFrame
dfOut = DataFrames.DataFrame(Summit = String[], Elevation = Int[], Latitude=Float64[], Longitude=Float64[])

for row in eachrow(dfIn)
    println(row["Peak"])
    mountain  = row["Peak"]
    elevation = parse(Int,row["Height"])
    n = match(r"(\d*):(\d*):(\d*)", row["Lat"])
    north = parse(Float64, n[1]) + parse(Float64, n[2])/60.0 + parse(Float64, n[3])/3600.0
    e = match(r"(\d*):(\d*):(\d*)", row["Long"])
    east  = parse(Float64, e[1]) + parse(Float64, e[2])/60.0 + parse(Float64, e[3])/3600.0
    push!(dfOut, (mountain, elevation, north, east))
end
CSV.write("data-sk-prom200.tsv",dfOut; delim='\t',quotestrings=true)

max_stars_repo_name: pavel-perina/panorama-jl

max_issues_repo_name: pavel-perina/panorama-jl

max_forks_repo_name: pavel-perina/panorama-jl


text:
abstract type AbstractVectorField end

MathematicalSystems.system(sys::AbstractContinuousSystem) = sys

struct VectorField{T} <: AbstractVectorField
    field::T
end

field(V::VectorField) = V.field

# no-op (for nonlinear systems)
field(f::Function) = f

# function-like evaluation
@inline function (V::VectorField)(args...)
    evaluate(V, args...)
end

@inline function evaluate(V::VectorField, args...)
    return V.field(args...)
end

@inline function evaluate(V::VectorField, x::Number, args...)
    return V.field([x], args...)
end

VectorField(sys::InitialValueProblem) = VectorField(system(sys))

function VectorField(sys::AbstractContinuousSystem)
    if islinear(sys)
        if inputdim(sys) == 0
            field = (x) -> state_matrix(sys) * x
        else
            field = (x, u) -> state_matrix(sys) * x + input_matrix(sys) * u
        end
    elseif isaffine(sys)
        if inputdim(sys) == 0
            field = (x) -> state_matrix(sys) * x + affine_term(sys)
        else
            field = (x, u) -> state_matrix(sys) * x + affine_term(sys) + input_matrix(sys) * u
        end
    elseif sys isa BBCS || sys isa CBBCS || sys isa CBBCCS
        return sys.f
    else
        error("the vector field for a system of type $sys is not implemented yet")
    end

    return VectorField(field)
end

function vector_field(sys::AbstractSystem, args...)
    return evaluate(VectorField(sys), args...)
end

# (x, p, t) -> du
function outofplace_field(ivp::InitialValueProblem)
    vf = VectorField(ivp)

    # function closure over the inital-value problem
    f = function f_outofplace(x, p, t)
             vf(x)
         end
    return f
end

# f!(dx, x, p, t)
function inplace_field!(ivp::InitialValueProblem)
    vf = VectorField(ivp)

    # function closure over the inital-value problem
    f! = function f_inplace!(dx, x, p, t)
             dx .= vf(x)
         end
    return f!
end

# for "black-box" MathematicalSystems, return the function field directly

function inplace_field!(ivp::IVP{<:NonlinearSystem})
    return ivp.s.f # TODO getter?
end


text:
# IO types that can be passed to `pipeline`
const NativeIO = Union{typeof(stdout),typeof(devnull),IOStream}  # whatelse?

function communicate(cmd; input, stdin::IO = IOBuffer(input), stdout::IO = IOBuffer(), stderr::IO = stderr)
    inio = Pipe()
    outio = stdout isa NativeIO ? Pipe() : stdout
    errio = stderr isa NativeIO ? Pipe() : stderr
    @sync begin
        proc = run(
            pipeline(cmd; stdin = inio, stdout = outio, stderr = errio);
            wait = false,
        )
        outio isa Pipe && close(outio.in)
        errio isa Pipe && close(errio.in)
        try
            stdout === outio || @async write(stdout, outio)
            stderr === errio || @async write(stderr, errio)
            try
                write(inio, stdin)
            finally
                close(inio)
            end
            wait(proc)
        catch
            stdout === outio || close(outio)
            stderr === errio || close(errio)
            close(inio)
            rethrow()
        end
    end
    return (; stdout = stdout, stderr = stderr)
end

# Use README as the docstring of the module:
function define_docstring()
    path = joinpath(dirname(@__DIR__), "README.md")
    include_dependency(path)
    doc = replace(read(path, String), r"^```julia"m => "```jldoctest README")
    @eval BenchmarkConfigSweeps $Base.@doc $doc BenchmarkConfigSweeps
end


text:
include("layer.jl")

"""
Square error loss function
"""
square_error(output, label) = (error = output - label; 1/2 * dot(error, error))

"""
Compute partial derivatives of the loss function with respect to output
"""
function partial_error(foo::Function, output, label)
    if foo == square_error
        return output - label
    else
        error("not implemented for this partial $foo")
    end
end

"""
StackNet is network with layers structure like a stack
"""
type StackNet
    layers::Array{Layer, 1}
    loss_func::Function
    batch_size::Integer

    StackNet(loss_func::Function; batch_size=5) = begin
        new(Array{Layer, 1}(), loss_func, batch_size)
    end
end

add_layer(net::StackNet, layer::Layer) = push!(net.layers, layer)

"""
do the forward computation on the entire stack network
"""
function forward(net::StackNet, sample)
    outputs = sample
    for i = 1:length(net.layers)
        outputs = forward(net.layers[i], outputs)
    end
    outputs
end

"""
correct the network with a single sample error
"""
function backward(net::StackNet, last_output, label)
    error = partial_error(net.loss_func, last_output, label)
    for i = length(net.layers):-1:1
        error = backward(net.layers[i], error)
    end
end

"""
mini-batch update each layer
"""
function batch_update(net::StackNet; eta=0.03)
    for i = 1:length(net.layers)
        batch_update(net.layers[i], eta=(eta / net.batch_size))
    end
end

"""
show the net
"""
function shownet(net::StackNet)
    head = """
    net::StackNet
    loss: $(net.loss_func)
    Layers: $(length(net.layers))
    """
    layer = ["""
    -----------------
        $(net.layers[i].activation)
        weights $(net.layers[i].weights)
        bias $(net.layers[i].bias)
        inputs $(net.layers[i].inputs)
        outputs $(net.layers[i].outputs)
    """ for i in 1:length(net.layers)]
    head * join(layer, "\n")
end

max_stars_repo_name: zxteloiv/julia-ex

max_issues_repo_name: zxteloiv/julia-ex

max_forks_repo_name: zxteloiv/julia-ex


text:
module ${modname}
import ..OpenCV

${code}

${submodule_imports}
end


text:
import Base.@kwdef

@kwdef mutable struct Person
    name::AbstractString = ""
    id::Number = 1
    address::AbstractString = ""
    friends::Dict{AbstractString, Person} = Dict()
end

@kwdef mutable struct PersonApp
    people::Vector{Person} = Person[]
    namefield = ""
    addressfield = ""
    selected_person::Union{Nothing, Person} = nothing
    next_id::Number = 1
    new_person_tooltip = "A new person needs a name"
    new_person_enabled = false
    editing_enabled = false
end

sort_people(app::PersonApp) = app.people = sort!(app.people, by = p-> lowercase(p.name))

person_index(app::PersonApp) = something(findfirst(x-> x == app.selected_person, app.people), 0)
function person_index(app::PersonApp, index::Number)
    println("SELECTING PERSON $index")
    show_person(app, 1 <= index <= length(app.people) ? app.people[index] : nothing)
end

function clear_person(app::PersonApp)
    app.selected_person = nothing
    app.namefield = ""
    app.addressfield = ""
    check_fields(app)
end

show_person(app::PersonApp, index::Number) = show_person(app, app.sorted_people[index])
function show_person(app::PersonApp, p::Person)
    app.selected_person = p
    app.namefield = something(p.name, "")
    app.addressfield = something(p.address, "")
    check_fields(app)
    println("###\n### SHOWING $(p === nothing ? "nothing" : p.name * ", ID: " * string(p.id))")
    println("###\n### INDEX: $(person_index(app))")
end

addressfield(app::PersonApp) = app.addressfield
function addressfield(app::PersonApp, value)
    app.addressfield = value
    check_fields(app)
end

namefield(app::PersonApp) = app.namefield
function namefield(app::PersonApp, value)
    app.namefield = value
    check_fields(app)
end

function check_fields(app::PersonApp)
    println("CHECKING FIELDS OF $app")
    app.new_person_enabled = false
    app.editing_enabled = app.selected_person !== nothing
    app.new_person_tooltip = ""
    if app.namefield == ""
        app.new_person_tooltip = "A new person needs a name"
    elseif app.addressfield == ""
        app.new_person_tooltip = "A new person needs an address"
    elseif findfirst(p-> p.name == app.namefield, app.people) !== nothing
        app.new_person_tooltip = "There is already a person named $(app.namefield)"
    else
        app.new_person_enabled = true
    end
end

function new_person(app::PersonApp)
    p = Person(
        id = app.next_id,
        name = app.namefield,
        address = app.addressfield)
    app.next_id += 1
    push!(app.people, p)
    sort_people(app)
    show_person(app, p)
    println("Created a person")
end

function change_person(app::PersonApp)
    p = app.selected_person
    p.name = app.namefield
    p.address = app.addressfield
    sort_people(app)
end

function delete_person(app::PersonApp, p::Person)
    println("###\n### DELETE $(p)")
    p === nothing && return
    splice!(app.people, person_index(app))
end


text:
function plot_res_at_ind(model::M1d1d, res::Vector{Results1d1d},
    t_ind::Integer, degC::Bool = false)

    ylabeltxt = "Temperature in K"
    TinX = T -> T
    if degC
        TinX = T -> (T .- 273.15)
        ylabeltxt = "Temperature in °C"
    end

    t = res[t_ind].t

    x = pp_get_bulk_mesh_coords(res[t_ind], model)
    # println("Plotting results for time ", seconds_to_min_seconds(t), " seconds")

    scrap_conduction = false
    i = 1
    t_cum_phase_dur = 0.0
    while t_cum_phase_dur <= t && i <= length(model.sim_phase)
        t_cum_phase_dur += model.sim_phase[i].duration
        scrap_conduction = model.sim_phase[i].submodels.scrap_discretization_model_enabled
        i += 1
    end

    if scrap_conduction
        pl = plot(x, TinX(res[t_ind].T.s), label = "T solid (mean)");
        T_sub_max = [res[t_ind].T.s_sub[i][1] for i in 1:length(res[end].T.s_sub)]
        T_sub_min = [res[t_ind].T.s_sub[i][end] for i in 1:length(res[end].T.s_sub)]
        plot!(pl, x, TinX(T_sub_max), label = "T solid (max)");
        plot!(pl, x, TinX(T_sub_min), label = "T solid (min)");
    else
        pl = plot(x, TinX(res[t_ind].T.s), label = "T solid");
    end

    plot!(pl, title = seconds_to_min_seconds(t),
            font = font(12,"Helvetica", :black), xlabel = "x in m",
            ylabel = ylabeltxt)

    plot!(pl, x, TinX(res[t_ind].T.f), label = "T fluid");

    return pl;
end

function pp_get_bulk_mesh_coords(res::Results1d1d, model::M1d1d)
    t = res.t
    mesh = nothing
    dur = 0.0

    for pid = 1:length(model.sim_phase)
        dur += model.sim_phase[pid].duration

        if t <= dur
            mesh = M1d1dMesh(model, pid)
            break
        end
    end

    if isnothing(mesh)
        error("No mesh!")
    end

    return [i*mesh.solid_cells.len for i=0:1:mesh.no_cells-1]
end

function seconds_to_min_seconds(seconds::Real)
    min = floor(Int64, seconds/60)
    sec = round(Int64,mod(seconds,60))

    return string(min) * " min " * string(sec) * " sec"
end

function post_process_results(pp_path::String, casename::String, model::M1d1d,
        res::Vector{Results1d1d};  in_deg_C = true, ylim_cust = nothing, dpi_pic=100)

    pp_img_path = joinpath(pp_path,"img",casename)
    clear_check_folder(pp_img_path)
    println("Generating images for all saved timesteps, saving to folder ", pp_img_path)
    progress = Progress(length(res), 1)
    for i =1:length(res)
        pl = model1d1d.plot_res_at_ind(model, res, i, in_deg_C);
        plot!(pl, dpi=dpi_pic, fmt=:png);
        isnothing(ylim_cust) ? nothing : plot!(pl, ylim = ylim_cust)
        png(pl, joinpath(pp_img_path,
                casename * "-" *replace(seconds_to_min_seconds(res[i].t)," " => "_") * ".png") );
        next!(progress)
    end

    return
end

function print_case_info(m::M1d1d)
    println("-------------------------------------------")
    for i=1:1:length(m.bulk)

        println("Bulk number: ", i)
        println("Bulk mass flow: ", m.bulk[i].mass_flow)
        println("Bulk density: ", m.bulk[i].density)
        println("Bulk porosity: ", m.bulk[i].porosity)
        println("Bulk cross section area: ", m.bulk[i].cross_sect_surf_area)

        println("Scrap part surface area: ", m.bulk[i].scrap_props.surf_area)
        println("Scrap part thickness: ", m.bulk[i].scrap_props.char_thickness)
        println("Scrap part volume: ", m.bulk[i].scrap_props.vol)

        mesh = M1d1dMesh(m,i)
        printInfo(mesh)
        println("\n\n")
    end

end

function clear_check_folder(path::String)
    # check if folder is empty / exists
    if !ispath(path) && !isfile(path)
            mkpath(path)
    elseif isfile(path)
            error("cannot make path, because path is allready a file location")
    end
end


text:
abstract type UnaryOperator end

for op in [:PrefixIncrement, :PrefixDecrement,
           :AddressOperator, :IndirectionOperator,
           :One2OneMappedUnaryOperator]
    @eval struct $op <: UnaryOperator end
end

const C2JULIA_UNARY_OPERATOR_MAP = Dict("+" => One2OneMappedUnaryOperator(),
                                        "-" => One2OneMappedUnaryOperator(),
                                        "!" => One2OneMappedUnaryOperator(),
                                        "~" => One2OneMappedUnaryOperator(),
                                        "sizeof" => One2OneMappedUnaryOperator(),
                                        "++" => PrefixIncrement(),
                                        "--" => PrefixDecrement(),
                                        "&" => AddressOperator(),
                                        "*" => IndirectionOperator(),
                                        )

function translate(::PrefixIncrement, cursor::CLUnaryOperator, op::AbstractString, toks::TokenList)
    oprand_cursor = children(cursor)[]
    if typeof(first(toks)) == Punctuation
        ex = Expr(:macrocall, Symbol("@++"), nothing, translate(oprand_cursor).expr)
        return MetaExpr(ex, cursor)
    else
        ex = Expr(:(+=), translate(oprand_cursor).expr, 1)
        return MetaExpr(ex, cursor)
    end
end

function translate(::PrefixDecrement, cursor::CLUnaryOperator, op::AbstractString, toks::TokenList)
    oprand_cursor = children(cursor)[]
    if typeof(first(toks)) == Punctuation
        ex = Expr(:macrocall, Symbol("@-"), nothing, translate(oprand_cursor).expr)
        return MetaExpr(ex, cursor)
    else
        ex = Expr(:(-=), translate(oprand_cursor).expr, 1)
        return MetaExpr(ex, cursor)
    end
end

function translate(::AddressOperator, cursor::CLUnaryOperator, op::AbstractString, toks::TokenList)
    meta = translate(first(children(cursor)))
    jltype_sym = clang2julia(type(meta.leafcursor))
    if jltype_sym isa Expr
        # dirty workaround
        jltype_sym = jltype_sym.args[2]
    end
    if isdefined(Base, jltype_sym) && isbitstype(getfield(Base, jltype_sym))  # TODO: ismutable?
        # immutable isbitstypes needs to be translated to `Ref`s to match C's behavior
        meta.expr = Expr(:call, :Ref, meta.expr)
    end
    meta.info = "AddressOperator"
    return meta
end

function translate(::IndirectionOperator, cursor::CLUnaryOperator, op::AbstractString, toks::TokenList)
    meta = translate(first(children(cursor)))
    jltype_sym = clang2julia(type(meta.leafcursor))
    if jltype_sym isa Expr
        # dirty workaround
        jltype_sym = jltype_sym.args[2]
    end
    if isdefined(Base, jltype_sym) && isbitstype(getfield(Base, jltype_sym))  # TODO: ismutable?
        meta.expr = Expr(:ref, meta.expr)
    end
    return meta
end

function translate(::One2OneMappedUnaryOperator, cursor::CLUnaryOperator, op::AbstractString, toks::TokenList)
    operand_meta = translate(first(children(cursor)))
    return MetaExpr(Expr(:call, Symbol(op), operand_meta.expr), cursor)
end

function translate(cursor::CLUnaryOperator)
    op = ""
    toks = tokenize(cursor)
    # hmm, this is just a workaround, pending https://reviews.llvm.org/D10833
    GC.@preserve toks begin
        for tok in toks
            txt = tok.text
            if typeof(tok) == Punctuation && haskey(C2JULIA_UNARY_OPERATOR_MAP, txt)
                op = txt
                break
            end
        end
    end
    return translate(C2JULIA_UNARY_OPERATOR_MAP[op], cursor, op, toks)
end

abstract type BinaryOperator end

for op in [:ArithmeticBinaryOperator, :RelationalBinaryOperator,
           :BitwiseBinaryOperator, :LogicalBinaryOperator, :AssignmentBinaryOperator]
    @eval struct $op <: BinaryOperator end
end

const C2JULIA_BINARY_OPERATOR_MAP = Dict("+" => ArithmeticBinaryOperator(),
                                         "-" => ArithmeticBinaryOperator(),
                                         "*" => ArithmeticBinaryOperator(),
                                         "/" => ArithmeticBinaryOperator(),
                                         "%" => ArithmeticBinaryOperator(),
                                         "<" => RelationalBinaryOperator(),
                                         ">" => RelationalBinaryOperator(),
                                         "==" => RelationalBinaryOperator(),
                                         "!=" => RelationalBinaryOperator(),
                                         ">=" => RelationalBinaryOperator(),
                                         "<=" => RelationalBinaryOperator(),
                                         "~" => BitwiseBinaryOperator(),
                                         "^" => BitwiseBinaryOperator(),
                                         "|" => BitwiseBinaryOperator(),
                                         "&" => BitwiseBinaryOperator(),
                                         "<<" => BitwiseBinaryOperator(),
                                         ">>" => BitwiseBinaryOperator(),
                                         "||" => LogicalBinaryOperator(),
                                         "&&" => LogicalBinaryOperator(),
                                         "=" => AssignmentBinaryOperator(),
                                         "+=" => AssignmentBinaryOperator(),
                                         "-=" => AssignmentBinaryOperator(),
                                         "*=" => AssignmentBinaryOperator(),
                                         "/=" => AssignmentBinaryOperator(),
                                         "%=" => AssignmentBinaryOperator(),
                                         "|=" => AssignmentBinaryOperator(),
                                         "&=" => AssignmentBinaryOperator(),
                                         "<<=" => AssignmentBinaryOperator(),
                                         ">>=" => AssignmentBinaryOperator(),
                                        )

function count_parens(cursor)
    n = 0
    toks = tokenize(cursor)
    for tok in toks
        txt = tok.text
        if txt == "("
            n += 1
        else
            break
        end
    end
    return n
end

function translate(cursor::Union{CLBinaryOperator,CLCompoundAssignOperator})
    # hmm, this is just a workaround, pending https://reviews.llvm.org/D10833
    paren_num = count_parens(cursor)
    child_cursors = children(cursor)
    lhs_cursor = first(child_cursors)
    rhs_cursor = last(child_cursors)
    tmp_cursor = lhs_cursor
    for i = 1:paren_num-1
        xxx = children(tmp_cursor)
        tmp_cursor = first(children(tmp_cursor))
    end
    GC.@preserve tmp_cursor begin
        lhs_last_idx = length(tokenize(tmp_cursor))
        toks = tokenize(cursor)
        op = ""
        for tok in collect(toks)[lhs_last_idx:end]
            txt = tok.text
            if typeof(tok) == Punctuation && haskey(C2JULIA_BINARY_OPERATOR_MAP, txt)
                op = txt
                break
            end
        end
    end
    lhs_meta = translate(lhs_cursor)
    rhs_meta = translate(rhs_cursor)
    return MetaExpr(Expr(:call, Symbol(op), lhs_meta.expr, rhs_meta.expr))
end

function translate(cursor::CLConditionalOperator)
    child_cursors = children(cursor)
    condition_meta = translate(child_cursors[1])
    branch1_meta = translate(child_cursors[2])
    branch2_meta = translate(child_cursors[3])
    ex = Expr(:if, condition_meta.expr, branch1_meta.expr, branch2_meta.expr)
    return MetaExpr(ex)
end