text:
## TRAITS FOR MEASURES

is_measure_type(::Any) = false

const MEASURE_TRAITS =
    [:name, :target_scitype, :supports_weights, :prediction_type, :orientation,
     :reports_each_observation, :aggregation, :is_feature_dependent, :docstring,
     :distribution_type]

# already defined in model_traits.jl:
# name              - fallback for non-MLJType is string(M) where M is arg
# target_scitype    - fallback value = Unknown
# supports_weights  - fallback value = false
# prediction_type   - fallback value = :unknown (also: :deterministic,
#                                           :probabilistic, :interval)
# docstring         - fallback value is value of `name` trait.

# specfic to measures:
orientation(::Type) = :loss  # other options are :score, :other
reports_each_observation(::Type) = false
aggregation(::Type) = Mean()  # other option is Sum() or callable object
is_feature_dependent(::Type) = false

# extend to instances:
orientation(m) = orientation(typeof(m))
reports_each_observation(m) = reports_each_observation(typeof(m))
aggregation(m) = aggregation(typeof(m))
is_feature_dependent(m) = is_feature_dependent(typeof(m))

# specific to probabilistic measures:
distribution_type(::Type) = missing

## AGGREGATION

abstract type AggregationMode end

struct Sum <: AggregationMode end
(::Sum)(v) = sum(v)

struct Mean <: AggregationMode end
(::Mean)(v) = mean(v)

# for rms and it's cousins:
struct RootMeanSquare <: AggregationMode end
(::RootMeanSquare)(v) = sqrt(mean(v.^2))

aggregate(v, measure) = aggregation(measure)(v)

# aggregation is no-op on scalars:
const MeasureValue = Union{Real,Tuple{<:Real,<:Real}} # number or interval
aggregate(x::MeasureValue, measure) = x

## DISPATCH FOR EVALUATION

# yhat - predictions (point or probabilisitic)
# X - features
# y - target observations
# w - per-observation weights

function value(measure, yhat, X, y, w)
    vfdep     = Val(is_feature_dependent(measure))
    vsweights = Val(supports_weights(measure))
    return value(measure, yhat, X, y, w, vfdep, vsweights)
end

## DEFAULT EVALUATION INTERFACE

#  is feature independent, weights not supported:
value(m, yhat, X, y, w, ::Val{false}, ::Val{false}) = m(yhat, y)

#  is feature dependent:, weights not supported:
value(m, yhat, X, y, w, ::Val{true}, ::Val{false}) = m(yhat, X, y)

#  is feature independent, weights supported:
value(m, yhat, X, y, w,         ::Val{false}, ::Val{true}) = m(yhat, y, w)
value(m, yhat, X, y, ::Nothing, ::Val{false}, ::Val{true}) = m(yhat, y)

#  is feature dependent, weights supported:
value(m, yhat, X, y, w,         ::Val{true}, ::Val{true}) = m(yhat, X, y, w)
value(m, yhat, X, y, ::Nothing, ::Val{true}, ::Val{true}) = m(yhat, X, y)

## helper

function check_pools(ŷ, y)
    levels(y) == levels(ŷ[1]) ||
        error("Conflicting categorical pools found "*
              "in observations and predictions. ")
    return nothing
end

## FOR BUILT-IN MEASURES

abstract type Measure <: MLJType end
is_measure_type(::Type{<:Measure}) = true
is_measure(m) = is_measure_type(typeof(m))

## DISPLAY AND INFO

Base.show(stream::IO, ::MIME"text/plain", m::Measure) =
    print(stream, "$(name(m)) (callable Measure)")
Base.show(stream::IO, m::Measure) = print(stream, name(m))

function MLJScientificTypes.info(M, ::Val{:measure_type})
    values = Tuple(@eval($trait($M)) for trait in MEASURE_TRAITS)
    return NamedTuple{Tuple(MEASURE_TRAITS)}(values)
end

MLJScientificTypes.info(m, ::Val{:measure}) = info(typeof(m))

"""
    metadata_measure(T; kw...)

Helper function to write the metadata for a single measure.
"""
function metadata_measure(T; name::String="",
                          target_scitype=Unknown,
                          prediction_type::Symbol=:unknown,
                          orientation::Symbol=:unknown,
                          reports_each_observation::Bool=true,
                          aggregation=Mean(),
                          is_feature_dependent::Bool=false,
                          supports_weights::Bool=false,
                          docstring::String="",
                          distribution_type=missing)
    pred_str        = "$prediction_type"
    orientation_str = "$orientation"
    dist = ifelse(ismissing(distribution_type), missing, "$distribution_type")
    ex = quote
        if !isempty($name)
            MMI.name(::Type{<:$T}) = $name
        end
        if !isempty($docstring)
            MMI.docstring(::Type{<:$T}) = $docstring
        end
        # traits common with models
        MMI.target_scitype(::Type{<:$T}) = $target_scitype
        MMI.prediction_type(::Type{<:$T}) = Symbol($pred_str)
        MMI.supports_weights(::Type{<:$T}) = $supports_weights
        # traits specific to measures
        orientation(::Type{<:$T}) = Symbol($orientation_str)
        reports_each_observation(::Type{<:$T}) = $reports_each_observation
        aggregation(::Type{<:$T}) = $aggregation
        is_feature_dependent(::Type{<:$T}) = $is_feature_dependent
        distribution_type(::Type{<:$T}) = $dist
    end
    parentmodule(T).eval(ex)
end

## INCLUDE SPECIFIC MEASURES AND TOOLS

include("continuous.jl")
include("confusion_matrix.jl")
include("finite.jl")
include("loss_functions_interface.jl")

## DEFAULT MEASURES
default_measure(T, S) = nothing

# Deterministic + Continuous / Count ==> RMS
default_measure(::Type{<:Deterministic},
                ::Type{<:Union{Vec{<:Continuous}, Vec{<:Count}}}) = rms

# Deterministic + Finite ==> Misclassification rate
default_measure(::Type{<:Deterministic},
                ::Type{<:Vec{<:Finite}}) = misclassification_rate

# default_measure(::Type{Probabilistic},
#                 ::Type{<:Union{Vec{<:Continuous},
#                                Vec{<:Count}}}) = ???

# Probabilistic + Finite ==> Cross entropy
default_measure(::Type{<:Probabilistic},
                ::Type{<:Vec{<:Finite}}) = cross_entropy

# Fallbacks
default_measure(M::Type{<:Supervised}) = default_measure(M, target_scitype(M))
default_measure(::M) where M <: Supervised = default_measure(M)


text:
"""
    varN(B::LogBinner[, lvl])

Calculates the variance/N of a given level in the Binning Analysis.
"""
varN(B::LogBinner, lvl::Integer = _reliable_level(B)) =
    varN(B.accumulators[lvl])

"""
    var(B::LogBinner[, lvl])

Calculates the variance of a given level in the Binning Analysis.
"""
var(B::LogBinner{T,N}, lvl::Integer = _reliable_level(B)) where {N, T} =
    var(B.accumulators[lvl])

"""
    all_vars(B::LogBinner)

Calculates the variance for each level of the Binning Analysis.
"""
function all_vars(B::LogBinner{T,N}) where {T,N}
    [var(B, lvl) for lvl in 1:N if count(B, lvl) > 1]
end

"""
    all_varNs(B::LogBinner)

Calculates the variance/N for each level of the Binning Analysis.
"""
function all_varNs(B::LogBinner{T,N}) where {T,N}
    [varN(B, lvl) for lvl in 1:N if count(B, lvl) > 1]
end

################################################################################

# NOTE works for all
"""
    mean(B::LogBinner[, lvl])

Calculates the mean for a given level in the Binning Analysis.
"""
mean(B::LogBinner, lvl::Integer = 1) = mean(B.accumulators[lvl])

# NOTE works for all
"""
    all_means(B::LogBinner)

Calculates the mean for each level of the `LogBinner`.
"""
function all_means(B::LogBinner{T,N}) where {T,N}
    [mean(B, lvl) for lvl in 1:N if count(B, lvl) > 1]
end

################################################################################

"""
    tau(B::LogBinner[, lvl])

Calculates the autocorrelation time tau.
"""
function tau(B::LogBinner{T,N}, lvl::Integer = _reliable_level(B)) where {N , T <: Number}
    var_0 = varN(B, 1)
    var_l = varN(B, lvl)
    0.5 * (var_l / var_0 - 1)
end
function tau(B::LogBinner{T,N}, lvl::Integer = _reliable_level(B)) where {N , T <: AbstractArray}
    var_0 = varN(B, 1)
    var_l = varN(B, lvl)
    @. 0.5 * (var_l / var_0 - 1)
end

"""
    all_taus(B::LogBinner)

Calculates the autocorrelation time tau for each level of the `LogBinner`.
"""
function all_taus(B::LogBinner{T,N}) where {T,N}
    [tau(B, lvl) for lvl in 1:N if count(B, lvl) > 1]
end

################################################################################

# Heuristic for selecting the level with the (presumably) most reliable
# standard error estimate:
# Take the highest lvl with at least 32 bins.
# (Chose 32 based on https://doi.org/10.1119/1.3247985)
function _reliable_level(B::LogBinner{T,N})::Int64 where {T,N}
    isempty(B) && (return 1)                # results in NaN in std_error
    i = findlast(x -> x.count >= 32, B.accumulators)
    something(i, 1)
end

 """
    std_error(B::LogBinner[, lvl])

Calculates the standard error of the mean.
"""
std_error(B::LogBinner{T,N}, lvl::Integer=_reliable_level(B)) where {N, T} =
    std_error(B.accumulators[lvl])

"""
    all_std_errors(B::LogBinner)

Calculates the standard error for each level of the Binning Analysis.
"""
function all_std_errors(B::LogBinner{T,N}) where {N, T}
    [std_error(B, lvl) for lvl in 1:N if count(B, lvl) > 1]
end

"""
    convergence(B::LogBinner, lvl)

Computes the difference between the variance of this lvl and the last,
normalized to the last lvl. If this value tends to 0, the Binning Analysis has
converged.
"""
function convergence(B::LogBinner) end

function convergence(B::LogBinner{T,N}, lvl::Integer=_reliable_level(B)) where {N, T <: Number}
    abs((varN(B, lvl+1) - varN(B, lvl)) / varN(B, lvl))
end
function convergence(B::LogBinner{T,N}, lvl::Integer=_reliable_level(B)) where {N, T <: AbstractArray}
    mean(abs.((varN(B, lvl+1) .- varN(B, lvl)) ./ varN(B, lvl)))
end

"""
    has_converged(B::LogBinner, lvl[, threshhold = 0.05])

Returns true if the Binning Analysis has converged for a given lvl.
"""
function has_converged(B::LogBinner, lvl::Integer=_reliable_level(B), threshhold::Float64 = 0.05)
    convergence(B, lvl) <= threshhold
end

ext: jl


text:
using Pkg
Pkg.activate(".")
Pkg.instantiate()
##

using DataFrames
using CSV
using Plots
using StatsPlots
using Plots.PlotMeasures
##

fpairs = CSV.read("../data/fpairs.txt", DataFrame, header=false)[:,1]

##

theme(:solarized_light)
#
upscale = 2 #8x upscaling in resolution
fntsm = Plots.font("sans-serif", pointsize=round(8.0*upscale))
fntlg = Plots.font("sans-serif", pointsize=round(10.0*upscale))
default(titlefont=fntlg, guidefont=fntlg, tickfont=fntsm, legendfont=fntsm)
default(size=(400*upscale,600*upscale)) #Plot canvas size

##

loo_ = []
for i in 1:28
    push!(loo_, CSV.read("looFamResults/$(lpad(i,2,"0")).csv", DataFrame))
end

looLong = vcat(loo_...)

loo = unstack(filter(x -> x.parameter == "elpd_loo", looLong), :char, :model, :value)

insertcols!(loo,1,:fpair=>fpairs)
select!(loo, [:fpair, :u, :l])
rename!(loo, [:fpair, :universal, :lineage])

loo[:,:delta] = loo.universal .- loo.lineage

sort!(loo, :delta)

##

scatter(loo.delta, 1:28,
    legend = false,
    yticks= (1:28,loo.fpair),
    xlab="Δ elpd",
    left_margin = upscale*5mm,
    markersize=upscale*3,
    )

savefig("../img/loo.pdf")

##

sort!(loo, :delta, rev=true)

output = DataFrame(
    "feature pair" => loo.fpair,
    "\$\\Delta\$ elpd" => round.(loo.delta, digits=1)
)

CSV.write("../data/tables/loo.tex", output, delim="&", newline="\\\\\n")

max_stars_repo_name: gerhardJaeger/phylogeneticTypology

max_issues_repo_name: gerhardJaeger/phylogeneticTypology

max_forks_repo_name: gerhardJaeger/phylogeneticTypology


text:
#!/usr/bin/env julia

# Load directly while developing. Once stable, add module using Pkg.clone()
# and remove this line.
include("../src/RealTime.jl")

using Plots
using ZMQ
using LibSerialPort
using RealTime
using JSON

# Plot backend
gr(size=(900, 500))

context = Context()
data_source = get_data_source(context, "tcp://localhost:5556")

# Number of points to display
n = 500

# Values for horizontal (time) axis and data
x = Float64[]
y, s = Float64[], Float64[]

while true
    # Get message as a String and convert to a Dict
    msg = get_message(data_source)
    d = JSON.parse(msg)

    # Manage arrays as FIFO queues
    push!(x, d["t"]/1000) # ms to seconds
    push!(y, d["y"])
    push!(s, d["s"])
    if length(x) > n
        for v in (x, y, s)
            shift!(v)
        end
    end

    plot(x, [y,s],
         title="Data stream", # Not displaying with GR backend (?)
         xaxis="time [s]",
         yaxis=("example [units]", (-1.1, 1.1), -1:0.25:1), # title, limits, ticks
         labels=(["Measured","Filtered"]), # legend
         line=([1 2], [:steppre :path], ["gray" "crimson"], [1.0 0.5]), # lineweights, linetypes, colors, alphas
         fill=(0, [0.1 0], "dodgerblue"), # y-origin, alpha, colors
         )

    # Update the plot window
    gui()
end

max_stars_repo_name: andrewadare/realtime

max_issues_repo_name: andrewadare/realtime

max_forks_repo_name: andrewadare/realtime


text:
function launch()

    @static if Sys.isapple()
        # OpenGL 3.2 + GLSL 150
        glsl_version = 150
        GLFW.WindowHint(GLFW.CONTEXT_VERSION_MAJOR, 3)
        GLFW.WindowHint(GLFW.CONTEXT_VERSION_MINOR, 2)
        GLFW.WindowHint(GLFW.OPENGL_PROFILE, GLFW.OPENGL_CORE_PROFILE) # 3.2+ only
        GLFW.WindowHint(GLFW.OPENGL_FORWARD_COMPAT, GL_TRUE) # required on Mac
    else
        # OpenGL 3.0 + GLSL 130
        glsl_version = 130
        GLFW.WindowHint(GLFW.CONTEXT_VERSION_MAJOR, 3)
        GLFW.WindowHint(GLFW.CONTEXT_VERSION_MINOR, 0)
        # GLFW.WindowHint(GLFW.OPENGL_PROFILE, GLFW.OPENGL_CORE_PROFILE) # 3.2+ only
        # GLFW.WindowHint(GLFW.OPENGL_FORWARD_COMPAT, GL_TRUE) # 3.0+ only
    end

    # setup GLFW error callback
    error_callback(err::GLFW.GLFWError) = @error "GLFW ERROR: code $(err.code) msg: $(err.description)"
    GLFW.SetErrorCallback(error_callback)

    # create window
    window = GLFW.CreateWindow(1600, 1400, "ElectroDermal Activity Analysis")
    @assert window != C_NULL
    GLFW.MakeContextCurrent(window)
    GLFW.SwapInterval(1)  # enable vsync

    # setup Dear ImGui context
    ctx = CImGui.CreateContext()

    # setup Dear ImGui style
    # CImGui.StyleColorsDark()
    # CImGui.StyleColorsClassic()
    CImGui.StyleColorsLight()

    # load Fonts
    # - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use `CImGui.PushFont/PopFont` to select them.
    # - `CImGui.AddFontFromFileTTF` will return the `Ptr{ImFont}` so you can store it if you need to select the font among multiple.
    # - If the file cannot be loaded, the function will return C_NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
    # - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling `CImGui.Build()`/`GetTexDataAsXXXX()``, which `ImGui_ImplXXXX_NewFrame` below will call.
    # - Read 'fonts/README.txt' for more instructions and details.
    # fonts_dir = joinpath(@__DIR__, "..", "fonts")
    # fonts = CImGui.GetIO().Fonts
    # default_font = CImGui.AddFontDefault(fonts)
    # CImGui.AddFontFromFileTTF(fonts, joinpath(fonts_dir, "Cousine-Regular.ttf"), 15)
    # CImGui.AddFontFromFileTTF(fonts, joinpath(fonts_dir, "DroidSans.ttf"), 16)
    # CImGui.AddFontFromFileTTF(fonts, joinpath(fonts_dir, "Karla-Regular.ttf"), 10)
    # CImGui.AddFontFromFileTTF(fonts, joinpath(fonts_dir, "ProggyTiny.ttf"), 10)
    # CImGui.AddFontFromFileTTF(fonts, joinpath(fonts_dir, "Roboto-Medium.ttf"), 16)
    # @assert default_font != C_NULL

    # setup Platform/Renderer bindings
    ImGui_ImplGlfw_InitForOpenGL(window, true)
    ImGui_ImplOpenGL3_Init(glsl_version)
    clear_color = Cfloat[0.45, 0.55, 0.60, 1.00]

    open_file_dialog = OpenFileDialog(pwd(),"", pwd(),"", false, false,Date(0),DataFrame(),DataFrame(),false)
    open_file_dialog2 = OpenFileDialog(pwd(),"",pwd(),"",false,false,Date(0),DataFrame(),DataFrame(),false)
    open_file_dialog3 = OpenFileDialog(pwd(),"",pwd(),"",false,false,Date(0),DataFrame(),DataFrame(),false)
    # data = DataFrame()
    # dt = Float32[]
    # data2 = DataFrame()
    # dt2 = Float32[]
    Open_files = false
    Open_files2 = false
    Open_files3 = false
    #data_length = 0
    #eda_data = nothing
    #isnothing(eda_data)
    while !GLFW.WindowShouldClose(window)
        GLFW.PollEvents()
        # start the Dear ImGui frame
        ImGui_ImplOpenGL3_NewFrame()
        ImGui_ImplGlfw_NewFrame()
        CImGui.NewFrame()

        if CImGui.BeginMainMenuBar()
            if CImGui.BeginMenu("File")
                populate_file_menu!(open_file_dialog,open_file_dialog2,open_file_dialog3) #visiblity = true
                #populate_file_menu!(open_file_dialog2)
                CImGui.EndMenu()
            end
            CImGui.EndMainMenuBar()
        end
        if isvisible(open_file_dialog)
            display_dialog!(open_file_dialog)
            if has_pending_action(open_file_dialog)
                # Check filename and perform different action.
                if occursin("eda",lowercase(get_file(open_file_dialog,ConfirmedStatus())))&& occursin("csv",lowercase(get_file(open_file_dialog,ConfirmedStatus())))
                    set_data_import(open_file_dialog,perform_dialog_action(open_file_dialog))
                    # eda_data = ...
                    # hr_data = ...
                    consume_action!(open_file_dialog)
                    #dt = Cfloat.(data[3:end,1])

                    Base.display(get_data_import(open_file_dialog))
                    Open_files = true
                    set_imported(open_file_dialog)
                    # status = ConfirmedStatus();
                else
                    # CImGui.Begin("Error!")
                    # CImGui.Text("This is not the target file!")
                    Base.display(get_file(open_file_dialog,ConfirmedStatus()))
                    CImGui.OpenPopup("Incorrect File?")
                    consume_action!(open_file_dialog)
                end
            end
        end
        if isvisible(open_file_dialog2)
            display_dialog!(open_file_dialog2)
            if has_pending_action(open_file_dialog2)
                if occursin("hr",lowercase(get_file(open_file_dialog2,ConfirmedStatus())))&&occursin("csv",lowercase(get_file(open_file_dialog2,ConfirmedStatus())))
                    set_data_import(open_file_dialog2,perform_dialog_action(open_file_dialog2))
                    consume_action!(open_file_dialog2)
                    #dt = Cfloat.(data[3:end,1])
                    Base.display(get_data_import(open_file_dialog2))
                    Open_files2 = true
                    set_imported(open_file_dialog2)
                    #status2 = ConfirmedStatus()
                else
                    Base.display(get_file(open_file_dialog2,UnconfirmedStatus()))
                    consume_action!(open_file_dialog2)
                    CImGui.OpenPopup("Incorrect File?")
                end
                # data2 = perform_dialog_action(open_file_dialog2)
                # consume_action!(open_file_dialog2)
                # #dt = Cfloat.(data[3:end,1])
                # Base.display(data2)
                # Open_files2 = true
            end
        end
        if isvisible(open_file_dialog3)
            display_dialog!(open_file_dialog3)
            if has_pending_action(open_file_dialog3)
                # Check filename and perform different action.
                if occursin("tags",lowercase(get_file(open_file_dialog3,ConfirmedStatus())))&& occursin("csv",lowercase(get_file(open_file_dialog3,ConfirmedStatus())))
                    set_data_import(open_file_dialog3,perform_dialog_action(open_file_dialog3))
                    # eda_data = ...
                    # hr_data = ...
                    consume_action!(open_file_dialog3)
                    #dt = Cfloat.(data[3:end,1])

                    Base.display(get_data_import(open_file_dialog3))
                    Open_files3 = true
                    set_imported(open_file_dialog3)
                    # status = ConfirmedStatus();
                else
                    # CImGui.Begin("Error!")
                    # CImGui.Text("This is not the target file!")
                    Base.display(get_file(open_file_dialog3,ConfirmedStatus()))
                    CImGui.OpenPopup("Incorrect File?")
                    consume_action!(open_file_dialog3)
                end
            end
        end

        if CImGui.BeginPopupModal("Incorrect File?", C_NULL, CImGui.ImGuiWindowFlags_AlwaysAutoResize)
            CImGui.Text("File does not conform to expected schema.\nPlease verify that: \n   (1) the file exists; \n   (2) you have permission to access the file; \n (3) you have chosen the right file type. \n \n")
            CImGui.Separator()
            CImGui.Button("OK", (120, 0)) && CImGui.CloseCurrentPopup()
            CImGui.SetItemDefaultFocus()
            CImGui.EndPopup()
        end

        #@c CImGui.Checkbox("Open files", &Open_files)
        if Open_files || Open_files2
            if !Open_files2 && Open_files
                # data_length = ...
                plotData(open_file_dialog,"EDA Measurements",open_file_dialog3)
            elseif !Open_files && Open_files2
                plotData(open_file_dialog2,"HR Measurements",open_file_dialog3)
            elseif Open_files && Open_files2
                plotData2(open_file_dialog,open_file_dialog2,open_file_dialog3)
            end
            CImGui.End()
        end

        # rendering
        CImGui.Render()
        GLFW.MakeContextCurrent(window)
        display_w, display_h = GLFW.GetFramebufferSize(window)
        glViewport(0, 0, display_w, display_h)
        glClearColor(clear_color...)
        glClear(GL_COLOR_BUFFER_BIT)
        ImGui_ImplOpenGL3_RenderDrawData(CImGui.GetDrawData())

        GLFW.MakeContextCurrent(window)
        GLFW.SwapBuffers(window)
    end

    # cleanup
    ImGui_ImplOpenGL3_Shutdown()
    ImGui_ImplGlfw_Shutdown()
    CImGui.DestroyContext(ctx)

    GLFW.DestroyWindow(window)
end

function perform_dialog_action(dialog::OpenFileDialog)
    directory = get_directory(dialog, ConfirmedStatus())
    file_name = get_file(dialog, ConfirmedStatus())
    path = joinpath(directory, file_name)
    data = CSV.File(path ; header= [get_file(dialog,ConfirmedStatus())]) |> DataFrame
end

function populate_file_menu!(dialog::AbstractDialog,dialog2::AbstractDialog,dialog3::AbstractDialog)
    if CImGui.BeginMenu("Import")
        if CImGui.MenuItem("Open EDA")
            set_visibility!(dialog, true)
        end
        if CImGui.MenuItem("Open HR")
            set_visibility!(dialog2, true)
        end
        if CImGui.MenuItem("Open tags")
            set_visibility!(dialog3,true)
        end
        CImGui.EndMenu()
    end
    # if CImGui.MenuItem("Save", "Ctrl+s")
    # end
    if CImGui.BeginMenu("Save as")
        if CImGui.MenuItem("Export EDA")
            #data = CSV.File("C:\\Users\\msi-\\Desktop\\EDA project\\EDA1.jl\\src\\EDA.csv" ; header= ["edaSave"]) |> DataFrame
            if isis_imported(dialog)
                saveCsv(dialog,"edaSave.csv")
            end
            # saveCsv(dialog,"edaSave.csv")
        end
        if CImGui.MenuItem("Export HR")
            if isis_imported(dialog2)
                saveCsv(dialog2,"hrSave.csv")
            end
            # saveCsv(dialog2,"hrSave.csv")
        end
        CImGui.EndMenu()
    end
    if CImGui.MenuItem("Quit", "Alt+F4")
    end
end

function extract_string(buffer)
     first_nul = findfirst(isequal('\0'), buffer) - 1
     buffer[1:first_nul]
end

function plotData(dialog::AbstractDialog,name::String,dialog3::AbstractDialog)
    begin
        #df = CSV.read("F:\\julia\\CSV\\EDA.csv", header = ["EDA"])
        #df = CSV.read("C:\\Users\\msi-\\Desktop\\EDA\\EDA.jl\\src\\HR.csv", header = ["HR"])
        CImGui.Begin("Plot")
        CImGui.Text("Plot")
        data = get_data_import(dialog)
        df_data =sort(Cfloat.(data[3:end,1]))
        max_value = df_data[end,1]
        #max = Cfloat(max_value)
        #length = size(df,1)-2
        len = size(data,1)-2
        #@show typeof(len)

        st = data[1,1]
        freq = data[2,1]
        buf="1"*"\0"^(15)
        hou_arr = [ string(s) for s = 0:23]
        min_arr = [ string(s) for s = 0:59]
        sec_arr = [ string(s) for s = 0:59]

        #buf2="00:00:00"*"\0"^(8)
        start_time, end_time, SorE, in_hou, in_min, in_sec = @cstatic start_time=Cint(1) end_time=Cint(2) SorE=Cint(0) in_hou=Cint(1) in_min=Cint(1) in_sec=Cint(1) begin
            @c CImGui.SliderInt("Start Time", &start_time, 1,len)
            CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
            time1=Dates.unix2datetime(st+(start_time-1)/freq)
            set_time(dialog,time1)
            CImGui.Text(string(Time(time1)))
            @c CImGui.SliderInt("End Time", &end_time, 2,len)
            CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
            time2=Dates.unix2datetime(st+(end_time-1)/freq)
            CImGui.Text(string(Time(time2)))
            if start_time > end_time -1
                start_time = end_time - Cint(1)
            #elseif start_time < end_time - 2000*freq
            #    start_time = end_time - Cint(2000*freq)
            end
            @c CImGui.Combo("###0",&SorE," \0start\0end\0")
            if SorE==1
                CImGui.Text("Start time:")
                CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                CImGui.PushItemWidth(50)
                # CImGui.InputText("",buf,length(buf))
                @c CImGui.Combo(":###1", &in_hou, hou_arr,length(hou_arr))
                CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                @c CImGui.Combo(":###2", &in_min, min_arr,length(min_arr))
                CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                @c CImGui.Combo("###3", &in_sec, sec_arr,length(sec_arr))
                CImGui.PopItemWidth()
                #tmp_time = Date(Dates.unix2datetime(st))+Time(in_hou-1,in_min-1,in_sec-1)
                #start_time=(tmp_time-Dates.unix2datetime(st))/1000*freq+1
                tmp_time = Time(in_hou,in_min,in_sec)
                for i=1:len
                    if tmp_time==Time(Dates.unix2datetime(st+Cint(i-1)/freq))
                        start_time=Cint(i)
                        break
                    end
                end
            elseif SorE==2
                CImGui.Text("End time:")
                CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                CImGui.PushItemWidth(50)
                # CImGui.InputText("",buf,length(buf))
                @c CImGui.Combo(":###4", &in_hou, hou_arr,length(hou_arr))
                CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                @c CImGui.Combo(":###5", &in_min, min_arr,length(min_arr))
                CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                @c CImGui.Combo("###6", &in_sec, sec_arr,length(sec_arr))
                CImGui.PopItemWidth()
                # CImGui.Text(string("End time:",extract_string(buf)))
                #tmp_time = Date(Dates.unix2datetime(st))+Time(in_hou-1,in_min-1,in_sec-1)
                #end_time=(tmp_time-Dates.unix2datetime(st))/1000*freq+1
                tmp_time = Time(in_hou,in_min,in_sec)
                for i=2:len
                    if tmp_time==Time(Dates.unix2datetime(st+Cint(i-1)/freq))
                        end_time=Cint(i)
                        break
                    end
                end
            end
            # CImGui.SameLine(5.0,CImGui.GetStyle().ItemInnerSpacing.x)
            # CImGui.Text("End time:")
            # CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
            # CImGui.InputText("",buf2,length(buf2))
            # CImGui.Text(extract_string(buf2))
        end
        plot_data = Cfloat.(data[(start_time+2):(end_time+2),1])
        set_data_export(dialog,data[(start_time+2):(end_time+2),[1]])
        # st = data[1,1]
        # freq = data[2,1]
        mean1= mean(plot_data)

        CImGui.Text("Color")
            sz, thickness, col = @cstatic sz=Cfloat(36.0) thickness=Cfloat(4.0) col=Cfloat[1.0,0.0,0.4,0.2] begin
                CImGui.ColorEdit4("Color", col)
            end
            p = CImGui.GetCursorScreenPos()
            col32 = CImGui.ColorConvertFloat4ToU32(ImVec4(col...))

            begin
                width = 1200
                height = 200

                CImGui.PlotLines(name, plot_data, length(plot_data), 0 , string("Mean:",string(mean1)), 0, Cfloat(max_value*1.2), (width,height))
                draw_list = CImGui.GetWindowDrawList()
                x::Cfloat = p.x
                y::Cfloat = p.y
                spacing = 8.0
                # Draws (almost transparent) horizontal bars
                for yₙ in range(y, step = 40, stop = y + height - 40)
                    CImGui.AddRectFilled(draw_list, ImVec2(x, yₙ), ImVec2(x+width, yₙ+20), col32);
                end
            end

            #draw the x axis of EDA data
            p = CImGui.GetCursorScreenPos()
            begin
                width = 1200
                col_ = Cfloat[0.0,0.0,0.0,1.0]
                col32_ = CImGui.ColorConvertFloat4ToU32(ImVec4(col_...))
                draw_list = CImGui.GetWindowDrawList()
                x = p.x
                y = p.y

                time = Dates.unix2datetime(st+ (start_time-1)/freq)
                f = Cfloat(1 / freq)
                CImGui.AddLine(draw_list, ImVec2(x, y), ImVec2(x+width, y), col32_, Cfloat(1));
                for xₙ in range(x, step = 120, stop = x + width)
                    hou = hour(time);
                    min = minute(time);
                    sec = second(time);
                    mil = millisecond(time);
                    #if sec ==0 && mil ==0
                    CImGui.AddLine(draw_list, ImVec2(xₙ, y), ImVec2(xₙ, y-5), col32_, Cfloat(1));   ###################################
                    #if mil ==0
                    #CImGui.AddText(draw_list, ImVec2(xₙ, y), col32, string(string(min), ":", string(sec)));
                    CImGui.AddText(draw_list, ImVec2(xₙ, y), col32_, string(string(hou), ":", string(min), ":", string(sec)));   ###############################
                    next_time = time + Dates.Millisecond(Cint((end_time-start_time+1)*f*100));
                    time = next_time;
                end
            end

            #draw the EDA overview
            CImGui.NewLine()
            overview_data = Cfloat.(data[3:end,1])
            begin
                width = 1200
                height = 100
                CImGui.PlotLines("Overview", overview_data, length(overview_data), 0 , name, 0, Cfloat(max_value*1.2), (width,height))
                draw_list = CImGui.GetWindowDrawList()
                p = CImGui.GetCursorScreenPos()
                x = p.x
                y = p.y
                spacing = 8.0
                time = Dates.unix2datetime(st)
                f = Cfloat(1 / freq)
                CImGui.AddLine(draw_list, ImVec2(x, y), ImVec2(x+width, y), col32_, Cfloat(1));
                for xₙ in range(x, step = 60, stop = x + width)
                    hou = hour(time);
                    min = minute(time);
                    sec = second(time);
                    mil = millisecond(time);
                    #if sec ==0 && mil ==0
                    CImGui.AddLine(draw_list, ImVec2(xₙ, y), ImVec2(xₙ, y-5), col32_, Cfloat(1));   ###################################
                    #if mil ==0
                    #CImGui.AddText(draw_list, ImVec2(xₙ, y), col32, string(string(min), ":", string(sec)));
                    CImGui.AddText(draw_list, ImVec2(xₙ, y), col32_, string(string(hou), ":", string(min), ":", string(sec)));   ###############################
                    next_time = time + Dates.Millisecond(Cint(len*f*50));
                    time = next_time;
                end
                CImGui.AddLine(draw_list, ImVec2(x+Cfloat(1200/(len-1)*(start_time-1)), y), ImVec2(x+Cfloat(1200/(len-1)*(start_time-1)), y-105), col32_, Cfloat(3));
                CImGui.AddLine(draw_list, ImVec2(x+Cfloat(1200/(len-1)*(end_time-1)), y), ImVec2(x+Cfloat(1200/(len-1)*(end_time-1)), y-105), col32_, Cfloat(3));
                if isis_imported(dialog3)
                    data3 = get_data_import(dialog3)
                    len3 = size(data3,1)
                    # Base.display(len3)
                    #Cfloat.(data[(start_time+2):(end_time+2),1])
                    for i=1:len3
                        CImGui.AddLine(draw_list, ImVec2(x+Cfloat(1200/(len-1)*(data3[i,1]-st)), y), ImVec2(x+Cfloat(1200/(len-1)*(data3[i,1]-st)), y-105), col32, Cfloat(3));
                    end
                end
            end
    end
end

function plotData2(dialog::AbstractDialog,dialog2::AbstractDialog,dialog3::AbstractDialog)
    begin
        CImGui.Begin("Plot")
        CImGui.Text("Plot")
        data = get_data_import(dialog)
        data2 = get_data_import(dialog2)
        df_data =sort(Cfloat.(data[3:end,1]))
        df_data2 =sort(Cfloat.(data2[3:end,1]))
        max_value = df_data[end,1]
        max_value2 = df_data2[end,1]
        len = size(data,1)-2
        len2 = size(data2,1) -2
        st = data[1,1]
        freq = data[2,1]
        st2 = data2[1,1]
        freq2 = data2[2,1]
        # buf="type sth here"*"\0"^(127)
        hou_arr = [ string(s) for s = 0:23]
        min_arr = [ string(s) for s = 0:59]
        sec_arr = [ string(s) for s = 0:59]
        start_time, end_time, syn, start_time2, end_time2= @cstatic start_time=Cint(1) end_time=Cint(2) syn=false start_time2=Cint(1) end_time2=Cint(2) begin
            if syn==false
                @c CImGui.SliderInt("Start Time", &start_time, 1,len)
                CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                time1=Dates.unix2datetime(st+(start_time-1)/freq)
                set_time(dialog,time1)
                CImGui.Text(string(Time(time1)))
                CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                @c CImGui.Checkbox("synchronize",&syn)
                @c CImGui.SliderInt("End Time", &end_time, 2,len)
                CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                time2=Dates.unix2datetime(st+(end_time-1)/freq)
                CImGui.Text(string(Time(time2)))
                if start_time > end_time -1
                    start_time = end_time - Cint(1)
                # elseif start_time < end_time - 2000*freq
                #    start_time = end_time - Cint(2000*freq)
                end
                # CImGui.InputText("",buf,length(buf))
                # CImGui.Text(extract_string(buf))
                SorE, in_hou, in_min, in_sec =@cstatic  SorE=Cint(0) in_hou=Cint(1) in_min=Cint(1) in_sec=Cint(1) begin
                    @c CImGui.Combo("###0",&SorE," \0start\0end\0")
                    if SorE==1
                        CImGui.Text("Start time:")
                        CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                        CImGui.PushItemWidth(50)
                        # CImGui.InputText("",buf,length(buf))
                        @c CImGui.Combo(":###1", &in_hou, hou_arr,length(hou_arr))
                        CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                        @c CImGui.Combo(":###2", &in_min, min_arr,length(min_arr))
                        CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                        @c CImGui.Combo("###3", &in_sec, sec_arr,length(sec_arr))
                        CImGui.PopItemWidth()
                        #tmp_time = Date(Dates.unix2datetime(st))+Time(in_hou-1,in_min-1,in_sec-1)
                        #start_time=(tmp_time-Dates.unix2datetime(st))/1000*freq+1
                        tmp_time = Time(in_hou,in_min,in_sec)
                        for i=1:len
                            if tmp_time==Time(Dates.unix2datetime(st+Cint(i-1)/freq))
                                start_time=Cint(i)
                                break
                            end
                        end
                    elseif SorE==2
                        CImGui.Text("End time:")
                        CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                        CImGui.PushItemWidth(50)
                        # CImGui.InputText("",buf,length(buf))
                        @c CImGui.Combo(":###4", &in_hou, hou_arr,length(hou_arr))
                        CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                        @c CImGui.Combo(":###5", &in_min, min_arr,length(min_arr))
                        CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                        @c CImGui.Combo("###6", &in_sec, sec_arr,length(sec_arr))
                        CImGui.PopItemWidth()
                        # CImGui.Text(string("End time:",extract_string(buf)))
                        #tmp_time = Date(Dates.unix2datetime(st))+Time(in_hou-1,in_min-1,in_sec-1)
                        #end_time=(tmp_time-Dates.unix2datetime(st))/1000*freq+1
                        tmp_time = Time(in_hou,in_min,in_sec)
                        for i=2:len
                            if tmp_time==Time(Dates.unix2datetime(st+Cint(i-1)/freq))
                                end_time=Cint(i)
                                break
                            end
                        end
                    end
                end

                @c CImGui.SliderInt("Start Time2", &start_time2, 1,len2)
                CImGui.SameLine()
                time3=Dates.unix2datetime(st2+(start_time2-1)/freq2)
                set_time(dialog2,time3)
                CImGui.Text(string(Time(time3)))
                @c CImGui.SliderInt("End Time2", &end_time2, 2,len2)
                CImGui.SameLine()
                time4=Dates.unix2datetime(st2+(end_time2-1)/freq2)
                CImGui.Text(string(Time(time4)))
                if start_time2 > end_time2 -1
                    start_time2 = end_time2 - Cint(1)
                # elseif start_time2 < end_time2 - 2000*freq2
                #    start_time2 = end_time2 - Cint(2000*freq2)
                end
                SorE2, in_hou2, in_min2, in_sec2 =@cstatic SorE2=Cint(0) in_hou2=Cint(1) in_min2=Cint(1) in_sec2=Cint(1) begin
                    @c CImGui.Combo("###10",&SorE2," \0start\0end\0")
                    if SorE2==1
                        CImGui.Text("Start time:")
                        CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                        CImGui.PushItemWidth(50)
                        # CImGui.InputText("",buf,length(buf))
                        @c CImGui.Combo(":###11", &in_hou2, hou_arr,length(hou_arr))
                        CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                        @c CImGui.Combo(":###12", &in_min2, min_arr,length(min_arr))
                        CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                        @c CImGui.Combo("###13", &in_sec2, sec_arr,length(sec_arr))
                        CImGui.PopItemWidth()
                        #tmp_time = Date(Dates.unix2datetime(st))+Time(in_hou-1,in_min-1,in_sec-1)
                        #start_time=(tmp_time-Dates.unix2datetime(st))/1000*freq+1
                        tmp_time2 = Time(in_hou2,in_min2,in_sec2)
                        for j=1:len2
                            if tmp_time2==Time(Dates.unix2datetime(st2+Cint(j-1)/freq2))
                                start_time2=Cint(j)
                                break
                            end
                        end
                    elseif SorE2==2
                        CImGui.Text("End time:")
                        CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                        CImGui.PushItemWidth(50)
                        # CImGui.InputText("",buf,length(buf))
                        @c CImGui.Combo(":###14", &in_hou2, hou_arr,length(hou_arr))
                        CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                        @c CImGui.Combo(":###15", &in_min2, min_arr,length(min_arr))
                        CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                        @c CImGui.Combo("###16", &in_sec2, sec_arr,length(sec_arr))
                        CImGui.PopItemWidth()
                        # CImGui.Text(string("End time:",extract_string(buf)))
                        #tmp_time = Date(Dates.unix2datetime(st))+Time(in_hou-1,in_min-1,in_sec-1)
                        #end_time=(tmp_time-Dates.unix2datetime(st))/1000*freq+1
                        tmp_time2 = Time(in_hou2,in_min2,in_sec2)
                        for j=2:len2
                            if tmp_time2==Time(Dates.unix2datetime(st2+Cint(j-1)/freq2))
                                end_time2=Cint(j)
                                break
                            end
                        end
                    end
                end
            else
                if freq2>=freq
                    @c CImGui.SliderInt("Start Time", &start_time, 1,len)
                    CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                    time1=Dates.unix2datetime(st+(start_time-1)/freq)
                    CImGui.Text(string(Time(time1)))
                    CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                    @c CImGui.Checkbox("synchronize",&syn)
                    @c CImGui.SliderInt("End Time", &end_time, 2,len)
                    CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                    time2=Dates.unix2datetime(st+(end_time-1)/freq)
                    CImGui.Text(string(Time(time2)))
                    if start_time > end_time -1
                        start_time = end_time - Cint(1)
                    # elseif start_time < end_time - 2000*freq
                    #    start_time = end_time - Cint(2000*freq)
                    end
                    SorE, in_hou, in_min, in_sec =@cstatic  SorE=Cint(0) in_hou=Cint(1) in_min=Cint(1) in_sec=Cint(1) begin
                        @c CImGui.Combo("###0",&SorE," \0start\0end\0")
                        if SorE==1
                            CImGui.Text("Start time:")
                            CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                            CImGui.PushItemWidth(50)
                            # CImGui.InputText("",buf,length(buf))
                            @c CImGui.Combo(":###1", &in_hou, hou_arr,length(hou_arr))
                            CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                            @c CImGui.Combo(":###2", &in_min, min_arr,length(min_arr))
                            CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                            @c CImGui.Combo("###3", &in_sec, sec_arr,length(sec_arr))
                            CImGui.PopItemWidth()
                            #tmp_time = Date(Dates.unix2datetime(st))+Time(in_hou-1,in_min-1,in_sec-1)
                            #start_time=(tmp_time-Dates.unix2datetime(st))/1000*freq+1
                            tmp_time = Time(in_hou,in_min,in_sec)
                            for i=1:len
                                if tmp_time==Time(Dates.unix2datetime(st+Cint(i-1)/freq))
                                    start_time=Cint(i)
                                    break
                                end
                            end
                        elseif SorE==2
                            CImGui.Text("End time:")
                            CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                            CImGui.PushItemWidth(50)
                            # CImGui.InputText("",buf,length(buf))
                            @c CImGui.Combo(":###4", &in_hou, hou_arr,length(hou_arr))
                            CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                            @c CImGui.Combo(":###5", &in_min, min_arr,length(min_arr))
                            CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                            @c CImGui.Combo("###6", &in_sec, sec_arr,length(sec_arr))
                            CImGui.PopItemWidth()
                            # CImGui.Text(string("End time:",extract_string(buf)))
                            #tmp_time = Date(Dates.unix2datetime(st))+Time(in_hou-1,in_min-1,in_sec-1)
                            #end_time=(tmp_time-Dates.unix2datetime(st))/1000*freq+1
                            tmp_time = Time(in_hou,in_min,in_sec)
                            for i=2:len
                                if tmp_time==Time(Dates.unix2datetime(st+Cint(i-1)/freq))
                                    end_time=Cint(i)
                                    break
                                end
                            end
                        end
                    end
                    start_time2=Cint((st-st2+(start_time-1)/freq)*freq2+1)
                    if start_time2>len2-1
                        start_time2=Cint(len2-1)
                    end
                    end_time2=Cint((st-st2+(end_time-1)/freq)*freq2+1)
                    if end_time2>len2
                        end_time2=Cint(len2)
                    end
                else
                    @c CImGui.SliderInt("Start Time", &start_time2, 1,len2)
                    CImGui.SameLine()
                    time3=Dates.unix2datetime(st2+(start_time2-1)/freq2)
                    CImGui.Text(string(Time(time3)))
                    CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                    @c CImGui.Checkbox("synchronize",&syn)
                    @c CImGui.SliderInt("End Time", &end_time2, 2,len2)
                    CImGui.SameLine()
                    time4=Dates.unix2datetime(st2+(end_time2-1)/freq2)
                    CImGui.Text(string(Time(time4)))
                    if start_time2 > end_time2 -1
                        start_time2 = end_time2 - Cint(1)
                    # elseif start_time2 < end_time2 - 2000*freq2
                    #    start_time2 = end_time2 - Cint(2000*freq2)
                    end
                    SorE2, in_hou2, in_min2, in_sec2 =@cstatic SorE2=Cint(0) in_hou2=Cint(1) in_min2=Cint(1) in_sec2=Cint(1) begin
                        @c CImGui.Combo("###10",&SorE2," \0start\0end\0")
                        if SorE2==1
                            CImGui.Text("Start time:")
                            CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                            CImGui.PushItemWidth(50)
                            # CImGui.InputText("",buf,length(buf))
                            @c CImGui.Combo(":###11", &in_hou2, hou_arr,length(hou_arr))
                            CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                            @c CImGui.Combo(":###12", &in_min2, min_arr,length(min_arr))
                            CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                            @c CImGui.Combo("###13", &in_sec2, sec_arr,length(sec_arr))
                            CImGui.PopItemWidth()
                            #tmp_time = Date(Dates.unix2datetime(st))+Time(in_hou-1,in_min-1,in_sec-1)
                            #start_time=(tmp_time-Dates.unix2datetime(st))/1000*freq+1
                            tmp_time2 = Time(in_hou2,in_min2,in_sec2)
                            for j=1:len2
                                if tmp_time2==Time(Dates.unix2datetime(st2+Cint(j-1)/freq2))
                                    start_time2=Cint(j)
                                    break
                                end
                            end
                        elseif SorE2==2
                            CImGui.Text("End time:")
                            CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                            CImGui.PushItemWidth(50)
                            # CImGui.InputText("",buf,length(buf))
                            @c CImGui.Combo(":###14", &in_hou2, hou_arr,length(hou_arr))
                            CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                            @c CImGui.Combo(":###15", &in_min2, min_arr,length(min_arr))
                            CImGui.SameLine(0.0,CImGui.GetStyle().ItemInnerSpacing.x)
                            @c CImGui.Combo("###16", &in_sec2, sec_arr,length(sec_arr))
                            CImGui.PopItemWidth()
                            # CImGui.Text(string("End time:",extract_string(buf)))
                            #tmp_time = Date(Dates.unix2datetime(st))+Time(in_hou-1,in_min-1,in_sec-1)
                            #end_time=(tmp_time-Dates.unix2datetime(st))/1000*freq+1
                            tmp_time2 = Time(in_hou2,in_min2,in_sec2)
                            for j=2:len2
                                if tmp_time2==Time(Dates.unix2datetime(st2+Cint(j-1)/freq2))
                                    end_time2=Cint(j)
                                    break
                                end
                            end
                        end
                    end
                    #st+(start_time-1)/freq=st2+(start_time2-1)/freq2
                    start_time=Cint((st2-st+(start_time2-1)/freq2)*freq+1)
                    if start_time>len-1
                        start_time=Cint(len-1)
                    end
                    end_time=Cint((st2-st+(end_time2-1)/freq2)*freq+1)
                    if end_time>len
                        end_time=Cint(len)
                    end
                end
            end
        end
        set_data_export(dialog,data[(start_time+2):(end_time+2),[1]])
        plot_data = Cfloat.(data[(start_time+2):(end_time+2),1])
        # st = data[1,1]
        # freq = data[2,1]
        mean1= mean(plot_data)
        #CImGui.Text(string(mean1))
        set_data_export(dialog2,data2[(start_time2+2):(end_time2+2),[1]])
        plot_data2 = Cfloat.(data2[(start_time2+2):(end_time2+2),1])
        mean2= mean(plot_data2)
        # st2 = data2[1,1]
        # freq2 = data2[2,1]

        CImGui.Text("Color")
            sz, thickness, col = @cstatic sz=Cfloat(36.0) thickness=Cfloat(4.0) col=Cfloat[1.0,0.0,0.4,0.2] begin
                CImGui.ColorEdit4("Color", col)
            end
            p = CImGui.GetCursorScreenPos()
            col32 = CImGui.ColorConvertFloat4ToU32(ImVec4(col...))

        #Plotting Data 1(EDA data)
        begin
            width = 1200
            height = 200
            CImGui.PlotLines("EDA Measurements", plot_data, length(plot_data), 0 , string("EDA Mean:",string(mean1)), 0, Cfloat(max_value*1.2), (width,height))
            draw_list = CImGui.GetWindowDrawList()
            x::Cfloat = p.x
            y::Cfloat = p.y
            spacing = 8.0
            # Draws (almost transparent) horizontal bars
            for yₙ in range(y, step = 40, stop = y + height - 40)
                CImGui.AddRectFilled(draw_list, ImVec2(x, yₙ), ImVec2(x+width, yₙ+20), col32);
            end
        end

        #draw the x axis of EDA data
        p = CImGui.GetCursorScreenPos()
        begin
            width = 1200
            col_ = Cfloat[0.0,0.0,0.0,1.0]
            col32_ = CImGui.ColorConvertFloat4ToU32(ImVec4(col_...))
            draw_list = CImGui.GetWindowDrawList()
            x = p.x
            y = p.y

            time = Dates.unix2datetime(st+ (start_time-1)/freq)
            f = Cfloat(1 / freq)
            CImGui.AddLine(draw_list, ImVec2(x, y), ImVec2(x+width, y), col32_, Cfloat(1));
            for xₙ in range(x, step = 120, stop = x + width)
                hou = hour(time);
                min = minute(time);
                sec = second(time);
                mil = millisecond(time);
                #if sec ==0 && mil ==0
                CImGui.AddLine(draw_list, ImVec2(xₙ, y), ImVec2(xₙ, y-5), col32_, Cfloat(1));   ###################################
                #if mil ==0
                #CImGui.AddText(draw_list, ImVec2(xₙ, y), col32, string(string(min), ":", string(sec)));
                CImGui.AddText(draw_list, ImVec2(xₙ, y), col32_, string(string(hou), ":", string(min), ":", string(sec)));   ###############################
                next_time = time + Dates.Millisecond(Cint((end_time-start_time+1)*f*100));
                time = next_time;
            end
        end

        #draw the EDA overview
        CImGui.NewLine()
        overview_data = Cfloat.(data[3:end,1])
        begin
            width = 1200
            height = 100
            CImGui.PlotLines("EDA Overview", overview_data, length(overview_data), 0 , "EDA", 0, Cfloat(max_value*1.2), (width,height))
            draw_list = CImGui.GetWindowDrawList()
            p = CImGui.GetCursorScreenPos()
            x = p.x
            y = p.y
            spacing = 8.0
            time = Dates.unix2datetime(st)
            f = Cfloat(1 / freq)
            CImGui.AddLine(draw_list, ImVec2(x, y), ImVec2(x+width, y), col32_, Cfloat(1));
            for xₙ in range(x, step = 60, stop = x + width)
                hou = hour(time);
                min = minute(time);
                sec = second(time);
                mil = millisecond(time);
                #if sec ==0 && mil ==0
                CImGui.AddLine(draw_list, ImVec2(xₙ, y), ImVec2(xₙ, y-5), col32_, Cfloat(1));   ###################################
                #if mil ==0
                #CImGui.AddText(draw_list, ImVec2(xₙ, y), col32, string(string(min), ":", string(sec)));
                CImGui.AddText(draw_list, ImVec2(xₙ, y), col32_, string(string(hou), ":", string(min), ":", string(sec)));   ###############################
                next_time = time + Dates.Millisecond(Cint(len*f*50));
                time = next_time;
            end
            CImGui.AddLine(draw_list, ImVec2(x+Cfloat(1200/(len-1)*(start_time-1)), y), ImVec2(x+Cfloat(1200/(len-1)*(start_time-1)), y-105), col32_, Cfloat(3));
            CImGui.AddLine(draw_list, ImVec2(x+Cfloat(1200/(len-1)*(end_time-1)), y), ImVec2(x+Cfloat(1200/(len-1)*(end_time-1)), y-105), col32_, Cfloat(3));
            if isis_imported(dialog3)
                data3 = get_data_import(dialog3)
                len3 = size(data3,1)
                # Base.display(len3)
                #Cfloat.(data[(start_time+2):(end_time+2),1])
                for i=1:len3
                    CImGui.AddLine(draw_list, ImVec2(x+Cfloat(1200/(len-1)*(data3[i,1]-st)), y), ImVec2(x+Cfloat(1200/(len-1)*(data3[i,1]-st)), y-105), col32, Cfloat(3));
                end
            end
        end

        CImGui.NewLine()
        CImGui.Separator()
        #plotting Date 2(HR data)
        CImGui.NewLine()
        p = CImGui.GetCursorScreenPos()
        begin
            width = 1200
            height = 200
            CImGui.PlotLines("HR Measurements", plot_data2, length(plot_data2), 0 , string("HR Mean:",string(mean2)), 0, Cfloat(max_value2*1.2), (width,height))
            draw_list2 = CImGui.GetWindowDrawList()
            x = p.x
            y = p.y
            spacing = 8.0
            # Draws (almost transparent) horizontal bars
            for yₙ in range(y, step = 40, stop = y + height - 40)
                CImGui.AddRectFilled(draw_list2, ImVec2(x, yₙ), ImVec2(x+width, yₙ+20), col32);
            end
        end

        #draw the x axis of HR
        p = CImGui.GetCursorScreenPos()
        begin
            width = 1200
            col_ = Cfloat[0.0,0.0,0.0,1.0]
            col32_ = CImGui.ColorConvertFloat4ToU32(ImVec4(col_...))
            draw_list2 = CImGui.GetWindowDrawList()
            x = p.x
            y = p.y

            time2 = Dates.unix2datetime(st2+ (start_time2-1)/freq2)
            f2 = Cfloat(1 / freq2)
            CImGui.AddLine(draw_list2, ImVec2(x, y), ImVec2(x+width, y), col32_, Cfloat(1));
            for xₙ in range(x, step = 120, stop = x + width)
                hou2 = hour(time2);
                min2 = minute(time2);
                sec2 = second(time2);
                mil2 = millisecond(time2);
                CImGui.AddLine(draw_list2, ImVec2(xₙ, y), ImVec2(xₙ, y-5), col32_, Cfloat(1));
                #if mil ==0
                #CImGui.AddText(draw_list, ImVec2(xₙ, y), col32, string(string(min), ":", string(sec)));
                CImGui.AddText(draw_list2, ImVec2(xₙ, y), col32_, string(string(hou2), ":", string(min2), ":", string(sec2)));
                next_time2 = time2 + Dates.Millisecond(Cint((end_time2-start_time2+1)*f2*100));
                time2 = next_time2;
            end
        end

        #draw the overview HR
        CImGui.NewLine()
        overview_data2 = Cfloat.(data2[3:end,1])
        begin
            width = 1200
            height = 100
            CImGui.PlotLines("HR Overview", overview_data2, length(overview_data2), 0 , "HR", 0, Cfloat(max_value2*1.2), (width,height))
            draw_list = CImGui.GetWindowDrawList()
            # for yₙ in range(y, step = 50, stop = y + height)
            #     CImGui.AddRectFilled(draw_list, ImVec2(x, yₙ), ImVec2(x+width, yₙ+20), Cfloat[255.0,255.0,255.0,0.5]);
            # end
            p = CImGui.GetCursorScreenPos()
            x = p.x
            y = p.y
            spacing = 8.0
            time = Dates.unix2datetime(st2)
            f = Cfloat(1 / freq2)
            CImGui.AddLine(draw_list, ImVec2(x, y), ImVec2(x+width, y), col32_, Cfloat(1));
            for xₙ in range(x, step = 60, stop = x + width)
                hou = hour(time);
                min = minute(time);
                sec = second(time);
                mil = millisecond(time);
                #if sec ==0 && mil ==0
                CImGui.AddLine(draw_list, ImVec2(xₙ, y), ImVec2(xₙ, y-5), col32_, Cfloat(1));   ###################################
                #if mil ==0
                #CImGui.AddText(draw_list, ImVec2(xₙ, y), col32, string(string(min), ":", string(sec)));
                CImGui.AddText(draw_list, ImVec2(xₙ, y), col32_, string(string(hou), ":", string(min), ":", string(sec)));   ###############################
                next_time = time + Dates.Millisecond(Cint(len2*f*50));
                time = next_time;
            end
            CImGui.AddLine(draw_list, ImVec2(x+Cfloat(1200/(len2-1)*(start_time2-1)), y), ImVec2(x+Cfloat(1200/(len2-1)*(start_time2-1)), y-105), col32_, Cfloat(3));
            CImGui.AddLine(draw_list, ImVec2(x+Cfloat(1200/(len2-1)*(end_time2-1)), y), ImVec2(x+Cfloat(1200/(len2-1)*(end_time2-1)), y-105), col32_, Cfloat(3));
            if isis_imported(dialog3)
                data3 = get_data_import(dialog3)
                len3 = size(data3,1)
                # Base.display(len3)
                #Cfloat.(data[(start_time+2):(end_time+2),1])
                for i=1:len3
                    CImGui.AddLine(draw_list, ImVec2(x+Cfloat(1200/(len-1)*(data3[i,1]-st)), y), ImVec2(x+Cfloat(1200/(len-1)*(data3[i,1]-st)), y-105), col32, Cfloat(3));
                end
            end
        end
    end
end

function saveCsv(dialog::AbstractDialog,name)
    saveData = perform_dialog_action(dialog)
    startTime = datetime2unix(get_time(dialog))
    frequency_exprot = saveData[2,1]
    df = DataFrame(A = Float64[])
    push!(df,startTime)#import start time
    push!(df,frequency_exprot)#import frequency
    d2 = get_data_export(dialog)
    data_frame_name = names(d2)
    rename!(df,f=>t for(f,t) = zip([:A],data_frame_name))
    # Base.display(df)
    d3 = vcat(df,d2)
    CSV.write(string(startTime," ",name),d3 ; writeheader = false)#export csv file
end


text:
@testset "checkpoint" begin
    @testset "$modelstr" for (modelstr, updatestrs) in (("Ising", ("local_update!", "SW_update!", "Wolff_update!")),
                                                        ("Potts", ("local_update!", "SW_update!", "Wolff_update!")),
                                                        ("Clock", ("local_update!", "SW_update!", "Wolff_update!")),
                                                        ("XY", ("local_update!", "SW_update!", "Wolff_update!")),
                                                        ("QuantumXXZ", ("loop_update!",)),
                                                       )
        model = eval(Symbol(modelstr))
        @testset "$updatestr" for updatestr in updatestrs
            update = eval(Symbol(updatestr))
            p = Parameter("Model"=>model, "Lattice"=>"chain lattice", "L"=>8, "J"=>1.0, "T"=>1.0,
                     "Update Method" => update,
                     "Q"=>5, "S"=>0.5,
                     "Seed"=>SEED,
                     "MCS"=>100, "Thermalization"=>100,
                     "Checkpoint Interval"=>Inf)
            rm("cp_0.dat",force=true)
            runMC(p)
            p["MCS"] = 200
            p["Seed"] = 0
            res1 = runMC(p)
            rm("cp_0.dat",force=true)
            p["Seed"] = SEED
            res2 = runMC(p)
            p["Seed"] = 0
            res3 = runMC(p)
            for name in keys(res1)
                if name in ["MCS per Second", "Time per MCS"]
                    continue
                end
                @testset "$name" begin
                    @test mean(res1[name]) == mean(res2[name])
                    @test mean(res2[name]) == mean(res3[name])
                    @test stderror(res1[name]) == stderror(res2[name])
                    @test stderror(res2[name]) == stderror(res3[name])
                end
            end
            rm("cp_0.dat",force=true)
        end
    end
end


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

mutable struct IoK8sApiCoreV1PersistentVolumeClaimSpec <: SwaggerModel
    accessModes::Any # spec type: Union{ Nothing, Vector{String} } # spec name: accessModes
    dataSource::Any # spec type: Union{ Nothing, IoK8sApiCoreV1TypedLocalObjectReference } # spec name: dataSource
    resources::Any # spec type: Union{ Nothing, IoK8sApiCoreV1ResourceRequirements } # spec name: resources
    selector::Any # spec type: Union{ Nothing, IoK8sApimachineryPkgApisMetaV1LabelSelector } # spec name: selector
    storageClassName::Any # spec type: Union{ Nothing, String } # spec name: storageClassName
    volumeMode::Any # spec type: Union{ Nothing, String } # spec name: volumeMode
    volumeName::Any # spec type: Union{ Nothing, String } # spec name: volumeName

    function IoK8sApiCoreV1PersistentVolumeClaimSpec(;accessModes=nothing, dataSource=nothing, resources=nothing, selector=nothing, storageClassName=nothing, volumeMode=nothing, volumeName=nothing)
        o = new()
        validate_property(IoK8sApiCoreV1PersistentVolumeClaimSpec, Symbol("accessModes"), accessModes)
        setfield!(o, Symbol("accessModes"), accessModes)
        validate_property(IoK8sApiCoreV1PersistentVolumeClaimSpec, Symbol("dataSource"), dataSource)
        setfield!(o, Symbol("dataSource"), dataSource)
        validate_property(IoK8sApiCoreV1PersistentVolumeClaimSpec, Symbol("resources"), resources)
        setfield!(o, Symbol("resources"), resources)
        validate_property(IoK8sApiCoreV1PersistentVolumeClaimSpec, Symbol("selector"), selector)
        setfield!(o, Symbol("selector"), selector)
        validate_property(IoK8sApiCoreV1PersistentVolumeClaimSpec, Symbol("storageClassName"), storageClassName)
        setfield!(o, Symbol("storageClassName"), storageClassName)
        validate_property(IoK8sApiCoreV1PersistentVolumeClaimSpec, Symbol("volumeMode"), volumeMode)
        setfield!(o, Symbol("volumeMode"), volumeMode)
        validate_property(IoK8sApiCoreV1PersistentVolumeClaimSpec, Symbol("volumeName"), volumeName)
        setfield!(o, Symbol("volumeName"), volumeName)
        o
    end
end # type IoK8sApiCoreV1PersistentVolumeClaimSpec

const _property_map_IoK8sApiCoreV1PersistentVolumeClaimSpec = Dict{Symbol,Symbol}(Symbol("accessModes")=>Symbol("accessModes"), Symbol("dataSource")=>Symbol("dataSource"), Symbol("resources")=>Symbol("resources"), Symbol("selector")=>Symbol("selector"), Symbol("storageClassName")=>Symbol("storageClassName"), Symbol("volumeMode")=>Symbol("volumeMode"), Symbol("volumeName")=>Symbol("volumeName"))
const _property_types_IoK8sApiCoreV1PersistentVolumeClaimSpec = Dict{Symbol,String}(Symbol("accessModes")=>"Vector{String}", Symbol("dataSource")=>"IoK8sApiCoreV1TypedLocalObjectReference", Symbol("resources")=>"IoK8sApiCoreV1ResourceRequirements", Symbol("selector")=>"IoK8sApimachineryPkgApisMetaV1LabelSelector", Symbol("storageClassName")=>"String", Symbol("volumeMode")=>"String", Symbol("volumeName")=>"String")
Base.propertynames(::Type{ IoK8sApiCoreV1PersistentVolumeClaimSpec }) = collect(keys(_property_map_IoK8sApiCoreV1PersistentVolumeClaimSpec))
Swagger.property_type(::Type{ IoK8sApiCoreV1PersistentVolumeClaimSpec }, name::Symbol) = Union{Nothing,eval(Meta.parse(_property_types_IoK8sApiCoreV1PersistentVolumeClaimSpec[name]))}
Swagger.field_name(::Type{ IoK8sApiCoreV1PersistentVolumeClaimSpec }, property_name::Symbol) =  _property_map_IoK8sApiCoreV1PersistentVolumeClaimSpec[property_name]

function check_required(o::IoK8sApiCoreV1PersistentVolumeClaimSpec)
    true
end

function validate_property(::Type{ IoK8sApiCoreV1PersistentVolumeClaimSpec }, name::Symbol, val)
end


text:
function testA5b()

    answer = matread("matlabtestdata/testA5b.mat")

    T1 = 600 # ms
    T2 = 100 # ms
    Δf = 10 # Hz
    M = Magnetization(1.0, 0, 0)
    dt = 1 # ms
    time = 0:dt:1000 # ms
    spin = Spin(M, 1, T1, T2, Δf, Position(0,0,0))
    mag = zeros(3,length(time))
    mag[:,1] = Vector(M)
    A = FreePrecessionMatrix()
    B = Magnetization()
    BtoM = Magnetization()
    freeprecess!(A, B, spin, dt)
    for t = 2:length(time)
        applydynamics!(spin, BtoM, A, B)
        mag[:,t] = Vector(spin.M)
    end

    return mag ≈ answer["M"]

end

function testF1a()

    answer = matread("matlabtestdata/testF1a.mat")

    t = 2.3 # ms
    α = π/4 # rad
    θ = 0 # rad
    Δf = -500:5:500 # Hz
    T1 = 600 # ms
    T2 = 100 # ms
    spins = map(Δf -> Spin(1, T1, T2, Δf), Δf)
    rf = InstantaneousRF(α, θ)
    Ae = ExcitationMatrix()
    Af = FreePrecessionMatrix()
    Bf = Magnetization()
    BtoM = Magnetization()
    for f = 1:length(Δf)
        excite!(Ae, spins[f], rf)
        freeprecess!(Af, Bf, spins[f], t)
        applydynamics!(spins[f], BtoM, Ae)
        applydynamics!(spins[f], BtoM, Af, Bf)
        applydynamics!(spins[f], BtoM, Ae)
    end
    sig = map(signal, spins)

    return sig ≈ vec(answer["sig"])

end

function testF1b()

    answer = matread("matlabtestdata/testF1b.mat")

    t = 2.3 # ms
    α = π/4 # rad
    θ = 0 # rad
    Δf = 0 # Hz
    T1 = 600 # ms
    T2 = 100 # ms
    grad = Gradient(0.1, 0, 0) # G/cm
    xpos = -2:0.01:2 # cm
    pos = [Position(x, 0, 0) for x in xpos]
    spins = map(pos -> Spin(1, T1, T2, Δf, pos), pos)
    rf = InstantaneousRF(α, θ)
    Ae = ExcitationMatrix()
    Af = FreePrecessionMatrix()
    Bf = Magnetization()
    BtoM = Magnetization()
    for i = 1:length(xpos)
        excite!(Ae, spins[i], rf)
        freeprecess!(Af, Bf, spins[i], t, grad)
        applydynamics!(spins[i], BtoM, Ae)
        applydynamics!(spins[i], BtoM, Af, Bf)
        applydynamics!(spins[i], BtoM, Ae)
    end
    sig = map(signal, spins)

    return sig ≈ vec(answer["sig"])

end

function testF1c()

    answer = matread("matlabtestdata/testF1c.mat")

    t = 2.3 # ms
    α = π/4 # rad
    θ = 0 # rad
    Δf = 0 # Hz
    T1 = 600 # ms
    T2 = 100 # ms
    grad = Gradient(0.1, 0, 0) # G/cm
    grad2 = Gradient(-0.05, 0, 0) # G/cm
    xpos = -2:0.01:2 # cm
    pos = [Position(x, 0, 0) for x in xpos]
    spins = map(pos -> Spin(1, T1, T2, Δf, pos), pos)
    rf = InstantaneousRF(α, θ)
    Ae = ExcitationMatrix()
    Af = FreePrecessionMatrix()
    Bf = Magnetization()
    Ar = FreePrecessionMatrix()
    Br = Magnetization()
    BtoM = Magnetization()
    for i = 1:length(xpos)
        excite!(Ae, spins[i], rf)
        freeprecess!(Af, Bf, spins[i], t, grad)
        freeprecess!(Ar, Br, spins[i], t, grad2)
        applydynamics!(spins[i], BtoM, Ae)
        applydynamics!(spins[i], BtoM, Af, Bf)
        applydynamics!(spins[i], BtoM, Ae)
        applydynamics!(spins[i], BtoM, Ar, Br)
    end
    sig = map(signal, spins)

    return sig ≈ vec(answer["sig"])

end

function testF2c()

    answer = matread("matlabtestdata/testF2c.mat")

    dt = 0.04 # ms
    t = 0:dt:6 # ms
    rf = 0.05 * sinc.(t .- 3) # G
    Δf = -1000:20:1000 # Hz
    spins = map(Δf -> Spin(1, 600, 100, Δf), Δf)
    A = BlochMatrix()
    B = Magnetization()
    BtoM = Magnetization()
    rf = RF(rf, dt)
    map(spins) do spin
        excite!(A, B, spin, rf)
        applydynamics!(spin, BtoM, A, B)
    end
    sig = map(signal, spins)

    return sig ≈ vec(answer["sig"])

end

function testF3a()

    answer = matread("matlabtestdata/testF3a.mat")

    dt = 0.1 # ms
    t = 0:dt:6 # ms
    T = length(t)
    xpos = -2:0.01:2 # cm
    rf = 0.05 * sinc.(t .- 3) # G
    grad = Gradient(0.1, 0, 0)
    T1 = 600 # ms
    T2 = 100 # ms
    Δf = 0 # Hz
    pos = [Position(x, 0, 0) for x in xpos]
    spins = map(pos -> Spin(1, T1, T2, Δf, pos), pos)
    rf = RF(rf, dt, grad)
    A = BlochMatrix()
    B = Magnetization()
    BtoM = Magnetization()
    for i = 1:length(xpos)
        excite!(A, B, spins[i], rf)
        applydynamics!(spins[i], BtoM, A, B)
    end
    sig = map(signal, spins)

    return sig ≈ vec(answer["sig"])

end

function testF3c()

    answer = matread("matlabtestdata/testF3c.mat")

    dt = 0.05 # ms
    t = 0.1:dt:6 # ms
    T = length(t)
    xpos = -2:0.1:2 # cm
    rf = 0.05 * sinc.(t .- 3) # G
    grad = [Gradient(0.1, 0, 0) for i = 1:T]
    grad2 = Gradient(-0.052, 0, 0)
    T1 = 600 # ms
    T2 = 100 # ms
    Δf = 0 # Hz
    pos = [Position(x, 0, 0) for x in xpos]
    spins = map(pos -> Spin(1, T1, T2, Δf, pos), pos)
    rf = RF(rf, dt, grad)
    Ae = BlochMatrix()
    Be = Magnetization()
    Af = FreePrecessionMatrix()
    Bf = Magnetization()
    BtoM = Magnetization()
    for i = 1:length(xpos)
        excite!(Ae, Be, spins[i], rf)
        freeprecess!(Af, Bf, spins[i], t[end] - dt, grad2)
        applydynamics!(spins[i], BtoM, Ae, Be)
        applydynamics!(spins[i], BtoM, Af, Bf)
    end
    sig = map(signal, spins)
    Mz = map(spin -> spin.M.z, spins)

    @test sig ≈ vec(answer["sig"])
    return Mz ≈ vec(answer["mz"])

end

function testF3d()

    answer = matread("matlabtestdata/testF3d.mat")

    dt = 0.05 # ms
    t = 0.1:dt:6 # ms
    T = length(t)
    xpos = -2:0.1:2 # cm
    rf = 0.05 * sinc.(t .- 3) # G
    grad = [Gradient(0.1, 0, 0) for i = 1:T]
    grad2 = Gradient(-0.052, 0, 0)
    T1 = 600 # ms
    T2 = 100 # ms
    Δf = 100 # Hz
    pos = [Position(x, 0, 0) for x in xpos]
    spins = map(pos -> Spin(1, T1, T2, Δf, pos), pos)
    rf = RF(rf, dt, grad)
    Ae = BlochMatrix()
    Be = Magnetization()
    Af = FreePrecessionMatrix()
    Bf = Magnetization()
    BtoM = Magnetization()
    map(spins) do spin
        excite!(Ae, Be, spin, rf)
        freeprecess!(Af, Bf, spin, t[end] - dt, grad2)
        applydynamics!(spin, BtoM, Ae, Be)
        applydynamics!(spin, BtoM, Af, Bf)
    end
    sig = map(signal, spins)
    Mz = map(spin -> spin.M.z, spins)

    @test sig ≈ vec(answer["sig"])
    return Mz ≈ vec(answer["mz"])

end

function testF3f()

    answer = matread("matlabtestdata/testF3f.mat")

    dt = 0.05 # ms
    t = 0.1:dt:6 # ms
    T = length(t)
    xpos = -5:0.1:5 # cm
    rf = 0.05 * sinc.(t .- 3) .* (exp.(im * 2π * 900 * t/1000) + exp.(-im * 2π * 900 * t/1000)) # G
    grad = [Gradient(0.1, 0, 0) for i = 1:T]
    grad2 = Gradient(-0.052, 0, 0)
    T1 = 600 # ms
    T2 = 100 # ms
    Δf = 0 # Hz
    pos = [Position(x, 0, 0) for x in xpos]
    spins = map(pos -> Spin(1, T1, T2, Δf, pos), pos)
    rf = RF(rf, dt, grad)
    Ae = BlochMatrix()
    Be = Magnetization()
    Af = FreePrecessionMatrix()
    Bf = Magnetization()
    BtoM = Magnetization()
    map(spins) do spin
        excite!(Ae, Be, spin, rf)
        freeprecess!(Af, Bf, spin, t[end] - dt, grad2)
        applydynamics!(spin, BtoM, Ae, Be)
        applydynamics!(spin, BtoM, Af, Bf)
    end
    sig = map(signal, spins)
    Mz = map(spin -> spin.M.z, spins)

    @test sig ≈ vec(answer["sig"])
    return Mz ≈ vec(answer["mz"])

end

function testA5bMC()

    answer = matread("matlabtestdata/testA5b.mat")

    T1 = 600 # ms
    T2 = 100 # ms
    Δf = 10 # Hz
    M = MagnetizationMC((1.0, 0, 0), (0, 0, 0))
    dt = 1 # ms
    time = 0:dt:1000 # ms
    spin = SpinMC(M, 1, [1, 0], [T1, T1], [T2, T2], [Δf, Δf], [Inf, Inf])
    A = BlochMcConnellMatrix(2)
    B = MagnetizationMC(2)
    BtoM = MagnetizationMC(2)
    mag = zeros(3,length(time))
    mag[:,1] = Vector(M[1])
    for t = 2:length(time)
        freeprecess!(A, B, spin, dt)
        applydynamics!(spin, BtoM, A, B)
        mag[:,t] = Vector(spin.M[1])
    end

    return mag ≈ answer["M"]

end

function testF1cMC()

    answer = matread("matlabtestdata/testF1c.mat")

    t = 2.3 # ms
    α = π/4 # rad
    θ = 0 # rad
    Δf = 0 # Hz
    T1 = 600 # ms
    T2 = 100 # ms
    grad = Gradient(0.1, 0, 0) # G/cm
    grad2 = Gradient(-0.05, 0, 0) # G/cm
    xpos = -2:0.01:2 # cm
    pos = [Position(x, 0, 0) for x in xpos]
    spins = map(pos -> SpinMC(1, [1, 0], [T1, T1], [T2, T2], [Δf, Δf], [Inf, Inf], pos), pos)
    rf = InstantaneousRF(α)
    Ae = ExcitationMatrix()
    Af = BlochMcConnellMatrix(2)
    Bf = MagnetizationMC(2)
    Ar = BlochMcConnellMatrix(2)
    Br = MagnetizationMC(2)
    BtoM = MagnetizationMC(2)
    map(spins) do spin
        excite!(Ae, spin, rf)
        freeprecess!(Af, Bf, spin, t, grad)
        freeprecess!(Ar, Br, spin, t, grad2)
        applydynamics!(spin, BtoM, Ae)
        applydynamics!(spin, BtoM, Af, Bf)
        applydynamics!(spin, BtoM, Ae)
        applydynamics!(spin, BtoM, Ar, Br)
    end
    sig = map(signal, spins)

    return sig ≈ vec(answer["sig"])

end

function testF2cMC()

    answer = matread("matlabtestdata/testF2c.mat")

    dt = 0.04 # ms
    t = 0:dt:6 # ms
    rf = 0.05 * sinc.(t .- 3) # G
    Δf = -1000:20:1000 # Hz
    grad = [Gradient(0, 0, 0) for r in rf]
    spins = map(Δf -> SpinMC(1, [1, 0], [600, 10], [100, 10], [Δf, 0], [Inf, Inf]), Δf)
    rf = RF(rf, dt, grad)
    A = BlochMcConnellMatrix(2)
    B = MagnetizationMC(2)
    BtoM = MagnetizationMC(2)
    map(spins) do spin
        excite!(A, B, spin, rf)
        applydynamics!(spin, BtoM, A, B)
    end
    sig = map(signal, spins)

    return sig ≈ vec(answer["sig"])

end

function testF3cMC()

    answer = matread("matlabtestdata/testF3c.mat")

    dt = 0.05 # ms
    t = 0.1:dt:6 # ms
    T = length(t)
    xpos = -2:0.1:2 # cm
    rf = 0.05 * sinc.(t .- 3) # G
    grad1 = Gradient(0.1, 0, 0)
    grad2 = Gradient(-0.052, 0, 0)
    rf = RF(rf, dt, grad1)
    rf0 = RF(zeros(length(rf)), dt, grad2)
    T1 = 600 # ms
    T2 = 100 # ms
    Δf = 0 # Hz
    pos = [Position(x, 0, 0) for x in xpos]
    spins = map(pos -> SpinMC(1, [1, 0], [T1, T1], [T2, T2], [Δf, Δf], [Inf, Inf], pos), pos)
    A1 = BlochMcConnellMatrix(2)
    B1 = MagnetizationMC(2)
    A2 = BlochMcConnellMatrix(2)
    B2 = MagnetizationMC(2)
    BtoM = MagnetizationMC(2)
    map(spins) do spin
        excite!(A1, B1, spin, rf)
        excite!(A2, B2, spin, rf0)
        applydynamics!(spin, BtoM, A1, B1)
        applydynamics!(spin, BtoM, A2, B2)
    end
    sig = map(signal, spins)
    Mz = map(spin -> spin.M[1].z, spins)

    @test sig ≈ vec(answer["sig"])
    return Mz ≈ vec(answer["mz"])

end

function testF3dMC()

    answer = matread("matlabtestdata/testF3d.mat")

    dt = 0.05 # ms
    t = 0.1:dt:6 # ms
    T = length(t)
    xpos = -2:0.1:2 # cm
    rf = 0.05 * sinc.(t .- 3) # G
    grad1 = Gradient(0.1, 0, 0)
    grad2 = Gradient(-0.052, 0, 0)
    rf = RF(rf, dt, grad1)
    rf0 = RF(zeros(length(rf)), dt, grad2)
    T1 = 600 # ms
    T2 = 100 # ms
    Δf = 100 # Hz
    pos = [Position(x, 0, 0) for x in xpos]
    spins = map(pos -> SpinMC(1, [1, 0], [T1, T1], [T2, T2], [Δf, Δf], [Inf, Inf], pos), pos)
    A1 = BlochMcConnellMatrix(2)
    B1 = MagnetizationMC(2)
    A2 = BlochMcConnellMatrix(2)
    B2 = MagnetizationMC(2)
    BtoM = MagnetizationMC(2)
    map(spins) do spin
        excite!(A1, B1, spin, rf)
        excite!(A2, B2, spin, rf0)
        applydynamics!(spin, BtoM, A1, B1)
        applydynamics!(spin, BtoM, A2, B2)
    end
    sig = map(signal, spins)
    Mz = map(spin -> spin.M[1].z, spins)

    @test sig ≈ vec(answer["sig"])
    return Mz ≈ vec(answer["mz"])

end

function testF3fMC()

    answer = matread("matlabtestdata/testF3f.mat")

    dt = 0.05 # ms
    t = 0.1:dt:6 # ms
    T = length(t)
    xpos = -5:0.1:5 # cm
    rf = 0.05 * sinc.(t .- 3) .* (exp.(im * 2π * 900 * t/1000) + exp.(-im * 2π * 900 * t/1000)) # G
    grad1 = Gradient(0.1, 0, 0)
    grad2 = Gradient(-0.052, 0, 0)
    rf = RF(rf, dt, grad1)
    T1 = 600 # ms
    T2 = 100 # ms
    Δf = 0 # Hz
    pos = [Position(x, 0, 0) for x in xpos]
    spins = map(pos -> SpinMC(1, [1, 0], [T1, T1], [T2, T2], [Δf, Δf], [Inf, Inf], pos), pos)
    A1 = BlochMcConnellMatrix(2)
    B1 = MagnetizationMC(2)
    A2 = BlochMcConnellMatrix(2)
    B2 = MagnetizationMC(2)
    BtoM = MagnetizationMC(2)
    map(spins) do spin
        excite!(A1, B1, spin, rf)
        freeprecess!(A2, B2, spin, t[end] - dt, grad2)
        applydynamics!(spin, BtoM, A1, B1)
        applydynamics!(spin, BtoM, A2, B2)
    end
    sig = map(signal, spins)
    Mz = map(spin -> spin.M[1].z, spins)

    @test sig ≈ vec(answer["sig"])
    return Mz ≈ vec(answer["mz"])

end

function testB2c()

    answer = matread("matlabtestdata/testB2c.mat")

    spin = Spin(1, 600, 100, 0)
    mese! = MESEBlochSim(1000, 50, 1)
    mag = mese!(spin)[1]

    return signal(mag) ≈ answer["sig"]

end

function testB2d()

    answer = matread("matlabtestdata/testB2d.mat")

    spin = Spin(1, 600, 100, 0)
    mese! = MESEBlochSim(1000, 50, 8)
    mag = mese!(spin)

    return map(signal, mag) ≈ vec(answer["sig"])

end

function testB2dMC()

    answer = matread("matlabtestdata/testB2d.mat")

    spin = SpinMC(1, [0, 1], [Inf, 600], [Inf, 100], [0, 0], [Inf, Inf])
    mese! = MESEBlochSim(1000, 50, 8)
    mag = mese!(spin)

    return map(signal, mag) ≈ vec(answer["sig"])

end

function testB3a()

    answer = matread("matlabtestdata/testB3a.mat")

    gradz = 0.3 # G/cm
    Tg = 3 # ms
    z = π/2 / (GAMMA * gradz * Tg/1000) # cm
    spin = Spin(1, 600, 100, 0, Position(0,0,z))
    spgr! = SPGRBlochSim(10, 2, π/3, GradientSpoiling(0, 0, gradz, Tg))
    spgr!(spin)

    show(devnull, spgr!)
    show(devnull, "text/plain", spgr!)
    return Vector(spin.M) ≈ vec(answer["M"])

end

function testB3b()

    answer = matread("matlabtestdata/testB3b.mat")

    gradz = 0.3 # G/cm
    Tg = 3 # ms
    zmax = 4π / (GAMMA * gradz * Tg/1000) # cm
    z = ((1:100)/100 .- 0.5) * zmax
    spins = map(z -> Spin(1, 600, 100, 0, Position(0,0,z)), z)
    spgr! = SPGRBlochSim(10, 2, π/3, GradientSpoiling(0, 0, gradz, Tg))
    foreach(spgr!, spins)
    M = mean(spin.M for spin in spins)

    return Vector(M) ≈ vec(answer["M"])

end

function testB3c()

    answer = matread("matlabtestdata/testB3c.mat")

    spin = Spin(1, 600, 100, 0)
    spgr! = SPGRBlochSim(10, 2, π/3)
    spgr!(spin)

    return Vector(spin.M) ≈ vec(answer["M"])

end

function testB5a()

    answer = matread("matlabtestdata/testB5a.mat")

    gradz = 0.3 # G/cm
    Tg = 3 # ms
    zmax = 2π / (GAMMA * gradz * Tg/1000) # cm
    z = (1:100)/100 * zmax
    spins = map(z -> Spin(1, 600, 100, 0, Position(0,0,z)), z)
    spgr! = SPGRBlochSim(10, 2, π/6, RFandGradientSpoiling((0, 0, gradz), Tg), Val(100))
    foreach(spgr!, spins)
    sig = mean(signal(spin.M) for spin in spins)

    return sig ≈ answer["sig"]

end

function testB5b()

    answer = matread("matlabtestdata/testB5b.mat")

    α = LinRange(0, π/2, 51) # rad
    gradz = 0.3 # G/cm
    Tg = 3 # ms
    zmax = 2π / (GAMMA * gradz * Tg/1000) # cm
    z = (1:100)/100 * zmax
    srf = Vector{ComplexF64}(undef, 51)
    for i = 1:51
        spins = map(z -> Spin(1, 600, 100, 0, Position(0,0,z)), z)
        spgr! = SPGRBlochSim(10, 2, α[i], RFandGradientSpoiling((0, 0, gradz), Tg), Val(100))
        foreach(spgr!, spins)
        srf[i] = mean(signal(spin.M) for spin in spins)
    end
    spin = Spin(1, 600, 100, 0)
    sideal = map(α) do α
        spgr! = SPGRBlochSim(10, 2, α)
        spgr!(spin)
        signal(spin)
    end

    @test srf ≈ vec(answer["sig1"])
    return sideal ≈ vec(answer["sig2"])

end

@testset "Compare to MATLAB" begin

    @testset "Single Compartment" begin

        @test testA5b()
        @test testF1a()
        @test testF1b()
        @test testF1c()
        @test testF2c()
        @test testF3a()
        @test testF3c()
        @test testF3d()
        @test testF3f()

    end

    @testset "Multicompartment" begin

        @test testA5bMC()
        @test testF1cMC()
        @test testF2cMC()
        @test testF3cMC()
        @test testF3dMC()
        @test testF3fMC()

    end

    @testset "Sequences" begin

        @testset "MESE" begin

            @test testB2c()
            @test testB2d()
            @test testB2dMC()

        end

        @testset "SPGR" begin

            @test testB3a()
            @test testB3b()
            @test testB3c()
            @test testB5a()
            @test testB5b()

        end

    end

end


text:
using TheNumberLine
using Documenter

makedocs(;
    modules=[TheNumberLine],
    authors="Gael Forget <gforget@mit.edu> and Jane Chapin <janemchapin@gmail.com>",
    repo="https://github.com/gaelforget/TheNumberLine.jl/blob/{commit}{path}#L{line}",
    sitename="TheNumberLine.jl",
    format=Documenter.HTML(;
        prettyurls=get(ENV, "CI", "false") == "true",
        canonical="https://gaelforget.github.io/TheNumberLine.jl",
        assets=String[],
    ),
    pages=[
        "Home" => "index.md",
    ],
)

deploydocs(;
    repo="github.com/gaelforget/TheNumberLine.jl",
)


text:
module SightingDistance

export polSightingDistance, unpolSightingDistance, profile1, profile, fv

using Light, Roots, NLopt

const brct = Float64[0,1000] # bracket for limits of the sighting distances (m)

function polUnmaxSightingDistance(f::Stokes,b::Stokes, disc, c, Sp) # find the sighting distance for a fish against a background. f and b are Polar types
# disc: discrimination threshold, Cmin
# c:    beam attenuation coefficient of the water
# Sp:   sensitivity

	ψ = (Sp - 1.)/(Sp + 1.)
	Pb = profile(b,ψ) # the activity profile of the interneuron

	r = 0. # set initial sighting distance: set sighting distance to zero if it's smaller than zero or larger than say 100 m
	if toZero(0.,f,b,Pb,disc,c,ψ) > 0 # if the result of this function is negative then there is no positive sighitng distance
		r = fzero(r -> toZero(r,f,b,Pb,disc,c,ψ),brct) # find the sighting distance
	end

	return r
end

function toZero(r,f,b,Pb,disc,c,ψ) # gives the difference between the two sides of equation 6 for a given sighting distance
    v = fv(r,f,b,c) # adjust the polarization state of the fish signal to this new sighting distance
    Pv = profile(v,ψ) # get the corresponding activity profile
    abs(Pv - Pb) - disc # return the difference between the discrimination threshold and the normalized absolute difference between the activity profile for the fish and the background
end

profile1(a::Stokes,ψ) = (a.s0 + ψ*a.s1)/(a.s0 - ψ*a.s1)
profile(a::Stokes,ψ) =  log((a.s0 + ψ*a.s1)/(a.s0 - ψ*a.s1)) # the activity profile of the polarization interneuron for Φmax = 0 or 90 degrees (from How and Marshall, 2013)

fv(r::Float64,f::Stokes,b::Stokes,c) = f*exp(-c*r) + b*(1. - exp(-c*r)) # modulate the stokes parameters for a signal that travels through r meters water with a specific background

unpolSightingDistance(f::Stokes,b::Stokes; disc = .02, c = .1) = begin # sighting distance of a fish against a background, taking into consideration intensity alone
	r = log(abs(f.s0 - b.s0)/b.s0/disc)/c
	r < 0 ? 0. : r # set sighting distance to zero if it's smaller than zero
end

unpolSightingDistance(f::Polar,b::Polar; disc = .02,  c = .1) = unpolSightingDistance(Stokes(f),Stokes(b),disc = disc,c = c)

function polMaxSightingDistance(f::Stokes,b::Stokes, disc, c, Sp) # find the sighting distance for a fish against a background. f and b are Polar types
# disc: discrimination threshold, Cmin
# c:    beam attenuation coefficient of the water
# Sp:   sensitivity
	function myfun(phi,grad)
		f2 = rotate(f,phi[1])
		b2 = rotate(b,phi[1])
		polUnmaxSightingDistance(f2,b2, disc, c, Sp)
	end
	opt = Opt(:LN_COBYLA, 1)
	lower_bounds!(opt, [-pi/4])
	upper_bounds!(opt, [pi/4])
	max_objective!(opt,myfun)
	(maxy,maxx,ret) = optimize(opt, [0.])
	return maxy
end

polSightingDistance(f::Stokes,b::Stokes;  disc = .1, c = .1, Sp = 5., max = false) = max ? polMaxSightingDistance(f,b,disc,c,Sp) : polUnmaxSightingDistance(f,b,disc,c,Sp)

polSightingDistance(f::Polar,b::Polar; disc = .1, c = .1, Sp = 5., max = false) = polSightingDistance(Stokes(f),Stokes(b),disc = disc, c = c,Sp = Sp,max = max)

end


text:
using LinearAlgebra
using Test
using ProximalOperators

@testset "LogisticLoss" for T in [Float32, Float64]

y = T[1.0, -1.0, 1.0, -1.0, 1.0]
mu = T(1.5)

f = LogisticLoss(y, mu)

x = T[-1.0, -2.0, 3.0, 2.0, 1.0]

f_x_1 = f(x)

@test typeof(f_x_1) == T

grad_f_x, f_x_2 = gradient(f, x)

f_x_ref = 5.893450123044199
grad_f_x_ref = [-1.0965878679450072, 0.17880438303317633, -0.07113880976635019, 1.3211956169668235, -0.4034121320549927]

@test f_x_1 ≈ f_x_ref
@test f_x_2 ≈ f_x_ref
@test all(grad_f_x .≈ grad_f_x_ref)

z1, f_z1 = prox(f, x)
grad_f_z1, = gradient(f, z1)

@test typeof(f_z1) == T
@test norm((x - z1)./1.0 - grad_f_z1, Inf)/norm(grad_f_z1, Inf) <= 1e-4

z2, f_z2 = prox(f, x, T(2.0))
grad_f_z2, = gradient(f, z2)

@test typeof(f_z2) == T
@test norm((x - z2)./2.0 - grad_f_z2, Inf)/norm(grad_f_z2, Inf) <= 1e-4

end


text:
# NOTE: Not using @enum because it craps out when displaying unknown values
const ETHERTYPE_IPV4 = UInt16(0x0800)
const ETHERTYPE_ARP  = UInt16(0x0806)

function ethertype_string(x::UInt16)
    x == ETHERTYPE_IPV4 && return @sprintf("IPv4(%04x)", x)
    x == ETHERTYPE_ARP && return @sprintf("ARP(%04x)", x)
    @sprintf("Unknown(%04x)", x)
end

struct EthernetHeader
    dst_mac::MACAddress
    src_mac::MACAddress
    ethertype::UInt16
end

function Base.show(io::IO, x::EthernetHeader)
    print(io, "($(x.src_mac) -> $(x.dst_mac) $(ethertype_string(x.ethertype)))")
end

struct EthernetPacket
    header::EthernetHeader
    payload::UnsafeArray{UInt8, 1}
end

function decode_ethernet(data::DenseVector{UInt8})
    p = Base.unsafe_convert(Ptr{UInt8}, data)
    GC.@preserve data begin
        h = unsafe_load(convert(Ptr{EthernetHeader}, p))
    end
    h = EthernetHeader(h.dst_mac, h.src_mac, bswap(h.ethertype))
    EthernetPacket(
        h,
        UnsafeArray{UInt8, 1}(
            p + sizeof(EthernetHeader),
            (length(data) - sizeof(EthernetHeader),)))
end

max_stars_repo_name: ancapdev/NetworkProtocols

max_issues_repo_name: ancapdev/NetworkProtocols


text:
# Defines the Row type and associated types and methods.
# Represents a row of Pascal's triangle in an efficient manner.
# Each Row presents a zero indexed array of values.

"""
    ZeroRange(max::Integer)

Represents the integer range 0:max.
"""
struct ZeroRange <: AbstractUnitRange{Integer}
    max::Int
    function ZeroRange(max)
        max ≥ 0 || throw(ArgumentError("end of range must be nonnegative"))
        new(max)
    end
end
Base.length(z::ZeroRange) = z.max + 1
Base.first(z::ZeroRange) = 0
Base.last(z::ZeroRange) = z.max
Base.iterate(z::ZeroRange, i = 0) = i > z.max ? nothing : (i, i+1)
function Base.getindex(z::ZeroRange, i::Integer)
    1 ≤ i ≤ z.max+1 || throw(BoundsError("index out of bounds"))
    return i-1
end
function Base.convert(::Type{AbstractUnitRange{T}}, z::ZeroRange) where {T}
    return 0:z.max
end
Base.show(io::IO, z::ZeroRange) = print(io, typeof(z).name, "(", z.max, ")")

"""
    numelements(rownum)

A utility function to return the number of elements that need to be
stored in order to represent row `rownum`. This is two less than half
the entries in the row so as to reduce redundancy.
"""
numelements(rownum) = rownum ≤ 3 ? 0 : (rownum-2)÷2

"""
    Row(rownum, data)
    Row(rownum)
    Row{V}(rownum, datasize)
    Row(r::Row)

Represents a single row of Pascal's triangle. Supplied `data` is not checked
for correctness, and since `Row`s are mutable storage can be pre-allocated to
ensure enough storage for up to row `datasize`. Constructing with just the
`rownum` will efficiently calculate the row entries. In all cases, `rownum`
must be nonnegative.

Note: Row uses an internal data structure that reduces redundant data storage.
Directly supplying a `data` argument is not recommended.

# Examples
```jldoctest
julia> Row(2)
3-element Row{Integer} with indices PascalsTriangle.ZeroRange(2):
 1
 2
 1

julia> Row{Float64}(2, 10)
3-element Row{Float64} with indices PascalsTriangle.ZeroRange(2):
 1.0
 2.0
 1.0
```
"""
mutable struct Row{V} <: AbstractVector{V}
    rownum::Int
    data::Vector{V}
    function Row(rownum, data)
        rownum ≥ 0 || throw(DomainError(rownum,"rownum must be nonnegative"))
        return new{eltype(data)}(rownum,data)
    end
end
Row(r::Row) = Row(r.rownum, copy(r.data))
Row(rownum) = Row{Int}(rownum, rownum)
Row{V}(rownum) where {V <: Real} = Row{V}(rownum, rownum)
Row(rownum, datasize::Integer) = Row{Int}(rownum, datasize)
function Row{V}(rownum, datasize::Integer) where {V <: Real}
    rownum ≥ 0 || throw(DomainError(rownum,"rownum must be nonnegative"))
    datasize ≥ rownum || throw(ArgumentError("datasize specified is not enough to store the row"))
    arr = Vector{V}(undef, numelements(datasize))
    datalength = numelements(rownum)
    if datalength ≥ 1
        entry = Entry(rownum,1,V(rownum))
        for i ∈ 1:datalength
            right!(entry)
            arr[i] = entry.val
        end
    end
    return Row(rownum, arr)
end

rownumber(r::Row) = r.rownum
function value(r::Row)
    arr = ones(eltype(r.data), r.rownum+1)
    for i ∈ 1:(r.rownum-1)
        arr[i+1] = r[i]
    end
    return arr
end
Base.values(r::Row) = value(r)

const THRESHOLD = 10
const HALF = 4
function tostring(r::Row)
    v = values(r)
    s = "<"
    if r.rownum < THRESHOLD
        s *= join(v, ", ")
    else
        s *= join(v[1:HALF], ", ")
        s *= ", ..., "
        s *= join(v[end-HALF+1:end], ", ")
    end
    s *= ">"
    return s
end
function Base.show(io::IO, ::MIME"text/plain", r::Row)
    print(io, "$(typeof(r).name)")
    print(io, tostring(r))
end
function Base.show(io::IO, r::Row)
    print(io, tostring(r))
end

function Base.sum(f, r::Row)
    if r.rownum == 0
        return f(1)
    elseif r.rownum == 1
        return 2f(1)
    elseif r.rownum == 2
        return 2f(1) + f(2)
    end
    unit = one(eltype(r.data))
    s = 2f(unit) + 2f(unit*r.rownum)
    datalength = numelements(r.rownum)
    if datalength > 0
        for i ∈ 1:(datalength-1)
            s += 2f(r.data[i])
        end
        if iseven(r.rownum)
            s += f(r.data[datalength])
        else
            s += 2f(r.data[datalength])
        end
    end
    return s
end
Base.sum(r::Row) = 2^r.rownum
Base.axes(r::Row) = (ZeroRange(r.rownum),)
Base.axes1(r::Row) = ZeroRange(r.rownum)
Base.LinearIndices(r::Row) = ZeroRange(r.rownum)
Base.size(r::Row) = (r.rownum + 1,)
Base.IndexStyle(::Type{<:Row}) = IndexLinear()
function Base.getindex(r::Row, i::Int)
    0 ≤ i ≤ r.rownum || throw(BoundsError(r, i))
    index = i > r.rownum÷2 ? r.rownum - i : i
    if index == 0
        return one(eltype(r.data))
    end
    if index == 1
        return eltype(r.data)(r.rownum)
    end
    return r.data[index-1]
end
Base.getindex(r::Row, ::Colon) = value(r)
Base.getindex(r::Row, I) = [r[i] for i ∈ I]
Base.firstindex(r::Row) = 0
Base.lastindex(r::Row) = r.rownum

Base.:(==)(a::Row, b::Row) = a.rownum == b.rownum &&
    a.data[1:numelements(a.rownum)] == b.data[1:numelements(b.rownum)]

isfirst(r::Row) = r.rownum == 0
isvalid(r::Row) = r.rownum ≥ 0 &&
    length(r.data) ≥ numelements(r.rownum) &&
    r.data[1:numelements(r.rownum)] == Row(r.rownum).data
toarray(r::Row) = Entry.(r.rownum,0:r.rownum,value(r))


text:
using FunctionalCollections
using Test

@testset "@Persistent constructor macro" begin

    @testset "Persistent Vectors" begin
        @test @Persistent([1, 2, 3]) == pvec([1, 2, 3])
    end

    @testset "Persistent Hash Maps" begin
        @test @Persistent(Dict("foo" => 1, "bar" => 2)) == phmap(("foo", 1), ("bar", 2))
    end

    @testset "Persistent Set" begin
        @test @Persistent(Set([1, 2, 3, 3])) == pset([1, 2, 3, 3])
    end

end


text:
using Dates, Gadfly

# set_default_plot_size(20cm, 15cm)
# simple Integrate and Fire Synapse Mode
type Synapse
    Ω::Real # membrane resistance [MΩ]
    τ::Real # membrane time constant [ms]
    rV::Real # resting membrane potential [mV]
    thV::Real # spike threshold [mV]
    sV::Real # spike voltage [mV]
    rsV::Real # reset voltage to after a spike [mV]
    dt::DateTime # time stamp of last update
    v::Real # tracks current voltage
    function Synapse(;Ω::Real=10.,  τ::Real=10.,  rV::Real=-70.,
                     thV::Real=-55, sV::Real=-20, rsV::Real=-75,
                     dt::DateTime=now())
        new(Ω, τ, rV, thV, sV, rsV, dt,rV)
    end
end

nextDt(dt::DateTime, addMs::Int64) = dt + Millisecond(addMs)

function update!(s::Synapse, iV::Real, dt::DateTime)
    Δdt = int(dt - s.dt)
    V = s.rV + iV * s.Ω # current input voltage
    V₁ = V + (s.v - V) * exp(-Δdt/s.τ)
    s.v = V₁ >= s.thV? s.rsV:V₁
    return s.v == s.rsV? s.sV : s.v
end

Δτ = 0 # in millesec
n = 1000
s = Synapse(Ω=10,τ=10)
data = zeros(n)
# V = copy(data)
<<<<<<< HEAD
V = max(randn(n) * 2 + 0.5-,0)
tm = ones(n)
t = 0
# V[:] = 1.61
=======
V = max(randn(n) * 1.5 + 0.5,0)
tm = ones(n)
t = 0
V[:] = 1.502
>>>>>>> origin/master
for i = 1:n
    Δτ = rand(1:1)
    v = update!(s, V[i], nextDt(s.dt, Δτ))
    data[i] = v
    tm[i] = i == 1? Δτ:tm[i-1] +  Δτ
end

<<<<<<< HEAD
vstack(plot(x=tm, y=data, Geom.line, Scale.y_continuous(minvalue=-80, maxvalue=10)),
       plot(x = tm,y=V, Geom.line))
=======
vstack(plot(x=tm, y=data, Geom.line, Scale.y_continuous(minvalue=-80, maxvalue=10)), plot(x = tm,y=V, Geom.bar))
>>>>>>> origin/master