text:
function cutensornetGetCudartVersion()
    ccall((:cutensornetGetCudartVersion, libcutensornet()), Csize_t, ())
end

@checked function cutensornetContraction(handle, plan, rawDataIn, rawDataOut, workspace, workspaceSize, sliceId, stream)
    initialize_context()
    ccall((:cutensornetContraction, libcutensornet()), cutensornetStatus_t, (cutensornetHandle_t, cutensornetContractionPlan_t, Ptr{CuPtr{Cvoid}}, CuPtr{Cvoid}, CuPtr{Cvoid}, UInt64, Int64, CUstream), handle, plan, rawDataIn, rawDataOut, workspace, workspaceSize, sliceId, stream)
end

@checked function cutensornetCreateContractionOptimizerConfig(handle, optimizerConfig)
    initialize_context()
    ccall((:cutensornetCreateContractionOptimizerConfig, libcutensornet()), cutensornetStatus_t, (cutensornetHandle_t, Ptr{cutensornetContractionOptimizerConfig_t}), handle, optimizerConfig)
end

@checked function cutensornetCreate(handle)
    initialize_context()
    ccall((:cutensornetCreate, libcutensornet()), cutensornetStatus_t, (Ptr{cutensornetHandle_t},), handle)
end

@checked function cutensornetContractionGetWorkspaceSize(handle, descNet, optimizerInfo, workspaceSize)
    initialize_context()
    ccall((:cutensornetContractionGetWorkspaceSize, libcutensornet()), cutensornetStatus_t, (cutensornetHandle_t, cutensornetNetworkDescriptor_t, cutensornetContractionOptimizerInfo_t, Ptr{UInt64}), handle, descNet, optimizerInfo, workspaceSize)
end

@checked function cutensornetDestroyContractionOptimizerInfo(optimizerInfo)
    initialize_context()
    ccall((:cutensornetDestroyContractionOptimizerInfo, libcutensornet()), cutensornetStatus_t, (cutensornetContractionOptimizerInfo_t,), optimizerInfo)
end

@checked function cutensornetLoggerOpenFile(logFile)
    ccall((:cutensornetLoggerOpenFile, libcutensornet()), cutensornetStatus_t, (Cstring,), logFile)
end

@checked function cutensornetContractionAutotunePreferenceSetAttribute(handle, autotunePreference, attr, buf, sizeInBytes)
    initialize_context()
    ccall((:cutensornetContractionAutotunePreferenceSetAttribute, libcutensornet()), cutensornetStatus_t, (cutensornetHandle_t, cutensornetContractionAutotunePreference_t, cutensornetContractionAutotunePreferenceAttributes_t, Ptr{Cvoid}, Csize_t), handle, autotunePreference, attr, buf, sizeInBytes)
end

@checked function cutensornetLoggerSetCallback(callback)
    ccall((:cutensornetLoggerSetCallback, libcutensornet()), cutensornetStatus_t, (cutensornetLoggerCallback_t,), callback)
end

@checked function cutensornetLoggerForceDisable()
    ccall((:cutensornetLoggerForceDisable, libcutensornet()), cutensornetStatus_t, ())
end

@checked function cutensornetLoggerSetFile(file)
    ccall((:cutensornetLoggerSetFile, libcutensornet()), cutensornetStatus_t, (Ptr{Cvoid},), file)
end

@checked function cutensornetContractionOptimize(handle, descNet, optimizerConfig, workspaceSizeConstraint, optimizerInfo)
    initialize_context()
    ccall((:cutensornetContractionOptimize, libcutensornet()), cutensornetStatus_t, (cutensornetHandle_t, cutensornetNetworkDescriptor_t, cutensornetContractionOptimizerConfig_t, UInt64, cutensornetContractionOptimizerInfo_t), handle, descNet, optimizerConfig, workspaceSizeConstraint, optimizerInfo)
end

@checked function cutensornetCreateContractionAutotunePreference(handle, autotunePreference)
    initialize_context()
    ccall((:cutensornetCreateContractionAutotunePreference, libcutensornet()), cutensornetStatus_t, (cutensornetHandle_t, Ptr{cutensornetContractionAutotunePreference_t}), handle, autotunePreference)
end

@checked function cutensornetCreateNetworkDescriptor(handle, numInputs, numModesIn, extentsIn, stridesIn, modesIn, alignmentRequirementsIn, numModesOut, extentsOut, stridesOut, modesOut, alignmentRequirementsOut, dataType, computeType, descNet)
    initialize_context()
    ccall((:cutensornetCreateNetworkDescriptor, libcutensornet()), cutensornetStatus_t, (cutensornetHandle_t, Int32, Ptr{Int32}, Ptr{Ptr{Int64}}, Ptr{Ptr{Int64}}, Ptr{Ptr{Int32}}, Ptr{UInt32}, Int32, Ptr{Int64}, Ptr{Int64}, Ptr{Int32}, UInt32, cudaDataType_t, cutensornetComputeType_t, Ptr{cutensornetNetworkDescriptor_t}), handle, numInputs, numModesIn, extentsIn, stridesIn, modesIn, alignmentRequirementsIn, numModesOut, extentsOut, stridesOut, modesOut, alignmentRequirementsOut, dataType, computeType, descNet)
end

@checked function cutensornetContractionOptimizerConfigGetAttribute(handle, optimizerConfig, attr, buf, sizeInBytes)
    initialize_context()
    ccall((:cutensornetContractionOptimizerConfigGetAttribute, libcutensornet()), cutensornetStatus_t, (cutensornetHandle_t, cutensornetContractionOptimizerConfig_t, cutensornetContractionOptimizerConfigAttributes_t, Ptr{Cvoid}, Csize_t), handle, optimizerConfig, attr, buf, sizeInBytes)
end

@checked function cutensornetContractionOptimizerInfoGetAttribute(handle, optimizerInfo, attr, buf, sizeInBytes)
    initialize_context()
    ccall((:cutensornetContractionOptimizerInfoGetAttribute, libcutensornet()), cutensornetStatus_t, (cutensornetHandle_t, cutensornetContractionOptimizerInfo_t, cutensornetContractionOptimizerInfoAttributes_t, Ptr{Cvoid}, Csize_t), handle, optimizerInfo, attr, buf, sizeInBytes)
end

@checked function cutensornetContractionOptimizerInfoSetAttribute(handle, optimizerInfo, attr, buf, sizeInBytes)
    initialize_context()
    ccall((:cutensornetContractionOptimizerInfoSetAttribute, libcutensornet()), cutensornetStatus_t, (cutensornetHandle_t, cutensornetContractionOptimizerInfo_t, cutensornetContractionOptimizerInfoAttributes_t, Ptr{Cvoid}, Csize_t), handle, optimizerInfo, attr, buf, sizeInBytes)
end

@checked function cutensornetDestroyContractionPlan(plan)
    initialize_context()
    ccall((:cutensornetDestroyContractionPlan, libcutensornet()), cutensornetStatus_t, (cutensornetContractionPlan_t,), plan)
end

@checked function cutensornetLoggerSetLevel(level)
    initialize_context()
    ccall((:cutensornetLoggerSetLevel, libcutensornet()), cutensornetStatus_t, (Int32,), level)
end

@checked function cutensornetDestroy(handle)
    initialize_context()
    ccall((:cutensornetDestroy, libcutensornet()), cutensornetStatus_t, (cutensornetHandle_t,), handle)
end

@checked function cutensornetDestroyNetworkDescriptor(desc)
    initialize_context()
    ccall((:cutensornetDestroyNetworkDescriptor, libcutensornet()), cutensornetStatus_t, (cutensornetNetworkDescriptor_t,), desc)
end

@checked function cutensornetContractionAutotune(handle, plan, rawDataIn, rawDataOut, workspace, workspaceSize, pref, stream)
    initialize_context()
    ccall((:cutensornetContractionAutotune, libcutensornet()), cutensornetStatus_t, (cutensornetHandle_t, cutensornetContractionPlan_t, Ptr{CuPtr{Cvoid}}, CuPtr{Cvoid}, CuPtr{Cvoid}, UInt64, cutensornetContractionAutotunePreference_t, CUstream), handle, plan, rawDataIn, rawDataOut, workspace, workspaceSize, pref, stream)
end

@checked function cutensornetDestroyContractionAutotunePreference(autotunePreference)
    initialize_context()
    ccall((:cutensornetDestroyContractionAutotunePreference, libcutensornet()), cutensornetStatus_t, (cutensornetContractionAutotunePreference_t,), autotunePreference)
end

@checked function cutensornetCreateContractionOptimizerInfo(handle, descNet, optimizerInfo)
    initialize_context()
    ccall((:cutensornetCreateContractionOptimizerInfo, libcutensornet()), cutensornetStatus_t, (cutensornetHandle_t, cutensornetNetworkDescriptor_t, Ptr{cutensornetContractionOptimizerInfo_t}), handle, descNet, optimizerInfo)
end

function cutensornetGetVersion()
    ccall((:cutensornetGetVersion, libcutensornet()), Csize_t, ())
end

function cutensornetGetErrorString(error)
    ccall((:cutensornetGetErrorString, libcutensornet()), Cstring, (cutensornetStatus_t,), error)
end

@checked function cutensornetDestroyContractionOptimizerConfig(optimizerConfig)
    initialize_context()
    ccall((:cutensornetDestroyContractionOptimizerConfig, libcutensornet()), cutensornetStatus_t, (cutensornetContractionOptimizerConfig_t,), optimizerConfig)
end

@checked function cutensornetContractionOptimizerConfigSetAttribute(handle, optimizerConfig, attr, buf, sizeInBytes)
    initialize_context()
    ccall((:cutensornetContractionOptimizerConfigSetAttribute, libcutensornet()), cutensornetStatus_t, (cutensornetHandle_t, cutensornetContractionOptimizerConfig_t, cutensornetContractionOptimizerConfigAttributes_t, Ptr{Cvoid}, Csize_t), handle, optimizerConfig, attr, buf, sizeInBytes)
end

@checked function cutensornetLoggerSetMask(mask)
    ccall((:cutensornetLoggerSetMask, libcutensornet()), cutensornetStatus_t, (Int32,), mask)
end

@checked function cutensornetContractionAutotunePreferenceGetAttribute(handle, autotunePreference, attr, buf, sizeInBytes)
    initialize_context()
    ccall((:cutensornetContractionAutotunePreferenceGetAttribute, libcutensornet()), cutensornetStatus_t, (cutensornetHandle_t, cutensornetContractionAutotunePreference_t, cutensornetContractionAutotunePreferenceAttributes_t, Ptr{Cvoid}, Csize_t), handle, autotunePreference, attr, buf, sizeInBytes)
end

@checked function cutensornetCreateContractionPlan(handle, descNet, optimizerInfo, workspaceSize, plan)
    initialize_context()
    ccall((:cutensornetCreateContractionPlan, libcutensornet()), cutensornetStatus_t, (cutensornetHandle_t, cutensornetNetworkDescriptor_t, cutensornetContractionOptimizerInfo_t, UInt64, Ptr{cutensornetContractionPlan_t}), handle, descNet, optimizerInfo, workspaceSize, plan)
end


text:
include("./ParticleSwarmAlignment.jl")
using .ParticleSwarmAlignment
using Combinatorics
using Printf

function load_fasta_file(fname)
    sequences = String[]
    line_counter = 0
    open(fname) do f
        seq = ""
        for line in eachline(f)
            if startswith(line, ">")
                if length(seq) > 0
                    push!(sequences, seq)
                end
                seq = ""
            else
                seq = string(seq, line)
            end
        end
        if length(seq) > 0
            push!(sequences, seq)
        end
    end
    return sequences
end

__precompile__()
function bigmain()
    # Load single-sequence FASTA files for different species
    files = [
        "california-sea-lion.fasta",
        "cattle.fasta",
        "chicken.fasta",
        "chimpanzee.fasta",
        #"fission-yeast.fasta",
        "human.fasta",
        "long-finned-pilot-whale.fasta",
        #"norway-rat.fasta",
        #"pacific-white-sided-dolphin.fasta",
        #"rhesus-monkey.fasta",
        #"tropical-clawed-frog.fasta",
        #"water-buffalo.fasta",
        #"white-tufted-ear-marmoset.fasta"
    ]
    for i in 1:length(files)
        files[i] = string("../fasta/HBA1/", files[i])
    end
    sequences = String[]

    for fname in files
        append!(sequences, load_fasta_file(fname))
    end

    iterations = 20
    num_particles = 10
    @time pso_score, pso_aligned = PSO_MSA(sequences, iterations, num_particles)

    println("Performing exhaustive search")
    @time exhaustive_score, exhaustive_aligned = exhaustive_search(sequences)
    @printf("BEST EXHAUSTIVE SEQUENCES (score=%d)\n", exhaustive_score)
    for seq in exhaustive_aligned
        println(seq)
    end

    @printf("PSO best score: %d, exhaustive best score: %d\n", pso_score, exhaustive_score)
end

function smallmain()
    filename = "../fasta/ENA-ebi.fasta"
    sequences = load_fasta_file(filename)
    iterations = 50
    score, aligned_sequences = PSO_MSA(sequences, iterations)

    println("Performing exhaustive search")
    best_score_exhaustive, best_aligned_exhaustive = exhaustive_search(sequences)
    @printf("BEST EXHAUSTIVE SEQUENCES (score=%d)\n", best_score_exhaustive)
    for seq in best_aligned_exhaustive
        println(seq)
    end

    @printf("PSO best score: %d, exhaustive best score: %d\n", score, best_score_exhaustive)

end

function exhaustive_search(sequences, weighted_progressive::Bool=false)
    perms = permutations(sequences)
    total_perms = length(perms)
    best_score = 0
    best_perm = String[]
    best_aligned = String[]
    i = 1
    for perm in perms
        @printf("Exhaustive Search step %d/%d\n", i, total_perms)
        p_edges = Array{Tuple{String,String,Int},1}(undef,length(perm)-1)
        for sidx in 2:length(perm)
            seqA_orig = perm[sidx-1]
            seqB_orig = perm[sidx]
            if weighted_progressive
                align_score, seqA_aligned, seqB_aligned = global_align(seqA_orig, seqB_orig)
                scoreAB = score_sequences([seqA_aligned, seqB_aligned])
            else
                # setting the edge weight to will just do the alignment inorder
                scoreAB = 0
            end
            p_edges[sidx-1] = (seqA_orig, seqB_orig, scoreAB)
        end
        aligned_sequences = progressive_alignment_inorder(perm, p_edges)
        score = score_sequences(aligned_sequences)
        if score > best_score
            best_score = score
            best_perm = copy(perm)
            best_aligned = copy(aligned_sequences)
        end
        i += 1
    end
    return best_score, best_aligned
end

function scoremain()
    sequences = [
        "-------AT-T----TAA-CT--CAGA---ACTGTC-GG---T--A-GACC----G-TG-A--AG--G-CGT--TCCC",
        "--------T-T----T---CC--CAGAG--AG-GTA-GGCTTT--ATGAGC----G--G-ATTAG--G--GTGAT---",
        "---T-ACAC-CTTAGTG--CT--CTCA---AT-GT--GG--TTG-A-GATCT---G-TT-A--A-----C-T------",
        "-AGTGA-AC-C---GTG--CG--C--A---AT--T------TTGTA-CATCT---G-TA-AG-AG--G-C-TG-T---",
        "-GGAGG-AG-C----AGA-CT--C------AC--TA-GG---T--G-TAT-----G----AG-AG--G-C-TG-T---",
        "---C-G-GTGT----TG-TCCGTC-GGC--AC-CTG-AG---TG-A---CTT---GATGCAT-------C-T--T---",
        "TGAC-G-GC-T----TGATCC--C-G----A---TG-GG--CTG-A--ACC----GATACAT-AG--G-C-C------",
        "-----A-AC-CC---AG---T--C-AA---AC-ATACGGA-ACC-A-CGCCTACAG-C--A--AG--G-C----C---",
        "-------AC------AGG-GT--CTAA---G--GTAC----TCC-T-TGTCCAC-G-C--A--TGACGTC-TA-C---",
        "-----ATGC-C-----GC-TT--C-GGTTTA--GTAC----TTG-A--GTCC-CAG-CG-A--AG-CG-C--G-----"
    ]
    score = score_sequences(sequences)
    println(score)
end

#scoremain()
bigmain()
#smallmain()

ext: jl


text:
#
println("Cj) Test of the GreenFunction module for a given list of bound-state configurations.")

@warn("\n\n !!! This example does not work properly at present !!! \n\n")
#
setDefaults("print summary: open", "zzz-GreenFunction.sum")
wa = Atomic.Computation("xx",  Nuclear.Model(26.); properties=[Green],
                        configs=[Configuration("[Ne] 3s^2 3p^6")],
                        greenSettings=GreenFunction.Settings(GreenFunction.SingleCSFwithoutCI(), Basics.DeExciteSingleElectron(),
                                                             5, [0, 1, 2], [LevelSymmetry(1//2,Basics.plus), LevelSymmetry(1//2,Basics.plus)],
                                                             true, false, Int64[]) )

wb = perform(wa)
setDefaults("print summary: close", "")


text:
#!/usr/local/bin/julia

using RocketBuilder
using DataFrames
using Gtk

db = opendb()

tanklist = GtkListStore(String)

for name in tanknames(db)
   push!(tanklist, (name,))
end

win = GtkWindow("Tank Editor", 500, 250)

toplayout = GtkBox(:h)  # :h makes a horizontal layout, :v a vertical layout
set_gtk_property!(toplayout, :margin_left, 10)
set_gtk_property!(toplayout, :margin_top, 10)
set_gtk_property!(toplayout,:spacing,10)
push!(win, toplayout)

# Master View Containing list of tanks
master_layout = GtkBox(:v)
set_gtk_property!(master_layout,:spacing,10)
push!(toplayout, master_layout)

model = GtkTreeModel(tanklist)
tree = treeview(model)

push!(master_layout, tree)

actions_layout = GtkBox(:h)
set_gtk_property!(actions_layout,:spacing,10)
push!(master_layout, actions_layout)

addbtn = GtkButton("Add")
removebtn = GtkButton("Remove")
reloadbtn = GtkButton("Reload")

push!(actions_layout, addbtn)
push!(actions_layout, removebtn)
push!(actions_layout, reloadbtn)

# Detail View with info about each selected tank
detail_layout = GtkGrid()

namelabel = GtkLabel("Name:")
totallabel = GtkLabel("Total mass:")
drylabel = GtkLabel("Dry mass:")

nameentry = GtkEntry()
totalentry = GtkEntry()
dryentry = GtkEntry()

detail_layout[1, 1] = namelabel
detail_layout[2, 1] = nameentry
detail_layout[1, 2] = drylabel
detail_layout[2, 2] = dryentry
detail_layout[1, 3] = totallabel
detail_layout[2, 3] = totalentry

set_gtk_property!(detail_layout, :column_spacing, 10)
set_gtk_property!(detail_layout, :row_spacing, 10)

push!(toplayout, detail_layout)

# Deal with selection and model update
selection = GAccessor.selection(tree)
chid = signal_connect(selection, "changed") do widget
    selection = GAccessor.selection(tree)
    if hasselection(selection)
        current = selected(selection)
        tankname = tanklist[current, 1]
        tank = findfirsttank(db, tankname)

        if !isnothing(tank)
            set_gtk_property!(nameentry, :text, tankname)
            set_gtk_property!(totalentry, :text, tank.total_mass)
            set_gtk_property!(dryentry, :text, tank.dry_mass)
        end
    end
end

# To disconnect this signal handler later
# signal_handler_disconnect(selection, chid)

# Adding row
addid = signal_connect(addbtn, "clicked") do widget
    name = get_gtk_property(nameentry, :text, String)

    # Cannot get text as numbers. Need to make that conversion ourselves
    drytxt = get_gtk_property(dryentry, :text, String)
    totaltxt = get_gtk_property(totalentry, :text, String)

    dry = parse(Float64, drytxt)
    total = parse(Float64, totaltxt)

    add_tank!(db, name, Tank(dry, total))
    push!(tanklist, (name,))
end

# Remove row
rmid = signal_connect(removebtn, "clicked") do widget
    selection = GAccessor.selection(tree)
    if hasselection(selection)
        current = selected(selection)
        tankname = tanklist[current, 1]
        tank = findfirsttank(db, tankname)

        if !isnothing(tank)
            # Put on this on main GUI task. I think.
            # GUI stuff cannot be run on other tasks
            Gtk.@sigatom begin
                deleteat!(tanklist, current)

                set_gtk_property!(nameentry, :text, "")
                set_gtk_property!(totalentry, :text, "")
                set_gtk_property!(dryentry, :text, "")
            end
        end
    end
end

# Reloading
reloadid = signal_connect(reloadbtn, "clicked") do widget
    Gtk.@sigatom begin
        empty!(tanklist)
        for name in tanknames(db)
           push!(tanklist, (name,))
        end
    end
end

# Close window
# Gtk.destroy(win)

if !isinteractive()
    cond = Condition()
    signal_connect(win, :destroy) do widget
        notify(cond)
        DBInterface.close!(db)
    end
    showall(win)
    @async Gtk.gtk_main()
    wait(cond)
else
    showall(win)
end


text:
# Use baremodule to shave off a few KB from the serialized `.ji` file
baremodule UserNSSandbox_jll
using Base
using Base: UUID
import JLLWrappers

JLLWrappers.@generate_main_file_header("UserNSSandbox")
JLLWrappers.@generate_main_file("UserNSSandbox", UUID("b88861f7-1d72-59dd-91e7-a8cc876a4984"))
end  # module UserNSSandbox_jll


text:
#abstract types
abstract AbstractOrderStatistic{F,S} <: Distribution{F,S}
typealias AbstractScalarOrderStatistic{S} AbstractOrderStatistic{Univariate,S}
typealias AbstractJointOrderStatistic{S} AbstractOrderStatistic{Multivariate,S}


text:
# --- Coupling Model Creation --- #

"""
    Coupling(::Peters, ::Section)

Coupling model for coupling an unsteady aerodynamic model based on Peters' finite state
theory (see [`Peters`](@ref)) and a two-degree of freedom typical section model (see
[`Section`](@ref)).  This model introduces the freestream velocity ``U_\\infty``,
air density ``\\rho_\\infty`` and air speed of sound ``c`` as additional parameters.
"""
function Coupling(aero::Peters{N}, ::Section) where N

    # state variable indices
    iλ = 1:N
    iq = N+1:N+4

    # coupling function
    g = (dx, x, p, t) -> peters_section_inputs(dx, x, p, t; iλ, iq, bbar = aero.b)

    # number of states, inputs, and parameters (use Val(N) to use inferrable dimensions)
    nx = Val(N+4)
    ny = Val(6)
    np = Val(14)

    # number of parameters introduced by the coupling (use Val(N) to use inferrable dimensions)
    npc = Val(3)

    # jacobian definitions
    ratejac = Nonlinear() # TODO: define rate jacobian function
    statejac = Nonlinear() # TODO: define state jacobian function
    paramjac = Nonlinear() # TODO: define parameter jacobian function
    tgrad = Zeros()

    # convenience function for setting coupling parameters
    setparam = peters_section_set_parameters!

    # convenience function for separating coupling parameters
    sepparam = peters_section_separate_parameters

    # return resulting coupling
    return Coupling{false}(g, nx, ny, np, npc;
        ratejac = ratejac,
        statejac = statejac,
        paramjac = paramjac,
        tgrad = tgrad,
        setparam = setparam,
        sepparam = sepparam)
end

# coupling function
function peters_section_inputs(dx, x, p, t; iλ, iq, bbar)
    # extract rate variables
    dλ = view(dx, iλ)
    dh, dθ, dhdot, dθdot = view(dx, iq)
    # extract state variables
    λ = view(x, iλ)
    h, θ, hdot, θdot = view(x, iq)
    # extract parameters
    a, b, a0, α0, cd0, cm0, kh, kθ, m, Sθ, Iθ, U, ρ, c = p
    # local freestream velocity components
    u, v, ω = section_velocities(U, θ, hdot, θdot)
    udot, vdot, ωdot = section_accelerations(dhdot, dθdot)
    # calculate loads
    N, A, M = peters_loads(a, b, ρ, c, a0, α0, cd0, cm0, bbar, u, v, ω, vdot, ωdot, λ)
    # lift is approximately equal to the normal force
    L = N
    # return inputs
    return SVector(u, ω, vdot, ωdot, L, M)
end

# convenience function for defining the coupling function parameters
function peters_section_set_parameters!(p; U, rho, c)
    p[1] = U
    p[2] = rho
    p[3] = c
    return p
end

# convenience function for separating the coupling function parameters
peters_section_separate_parameters(p) = (U = p[1], rho = p[2], c = p[3])


text:
using JAXTAM
using Test

const __testdir__  = abspath(@__DIR__, ".")
const __testconf__ = joinpath(__testdir__, "test_configs.jld2")
const __testmsn__  = joinpath(__testdir__, "heasarc/nicer/")

@testset "user_config.jl - Config function tests" begin
    @testset "Base config functions" begin
        @test JAXTAM._config_gen(__testconf__) == nothing
        @test JAXTAM._config_load(__testconf__) == Dict{Any,Any}(:_config_version => JAXTAM.__configver__)
        @test JAXTAM._config_edit(:test, "test", __testconf__) == nothing
        @test JAXTAM._config_rm(:test, __testconf__) == nothing
        @test JAXTAM._config_key_value(:_config_version, __testconf__) == JAXTAM.__configver__
    end

    @testset "User facing config functions" begin
        @test JAXTAM.config(config_path=__testconf__) == JAXTAM._config_load(__testconf__)
        @test JAXTAM.config(:test, "Stringie"; config_path=__testconf__) == Dict{Any,Any}(:_config_version => JAXTAM.__configver__, :test=>"Stringie")
        @test JAXTAM.config(:test; config_path=__testconf__) == "Stringie"
        @test JAXTAM.config_rm(:test; config_path=__testconf__) ==  Dict{Any,Any}(:_config_version => JAXTAM.__configver__)
    end

    @testset "User facing config default mission test" begin
        @test typeof(JAXTAM.config(:nicer, __testmsn__; config_path=__testconf__)[:nicer]) == JAXTAM.MissionDefinition
        @test JAXTAM.config(:nicer; config_path=__testconf__).path == __testmsn__
    end
end


text:
function makefile(file::String, n::Int)
    nams = open("test\\names.txt") do f
        readlines(f)
    end

    works = open("test\\works.txt") do f
        readlines(f)
    end

    open(file, "w") do f
        for i = 1:n
            l::String, w::String = rand(nams), rand(works);
            lat::Float64 = -rand(15.499326:.00001:16.051805);
            lon::Float64 = -rand(47.421716:.00001:48.276477);
            avl::Bool = rand(Bool);
            write(f, l, ";","$(lat),$(lon)" ,";",w,";$(avl)\n")
        end
    end
end


text:
using LinearAlgebra

function classical_gram_schmidt(A)
    m, n = size(A)
    R = zeros(n, n)
    Q = zeros(m, n)
    for j in 1:n
        v_j = A[:, j]
        for i in 1:(j-1)
            R[i, j] = dot(Q[:, i], A[:, j])
            v_j = v_j - R[i, j] * Q[:, i]
        end
        R[j, j] = norm(v_j)
        Q[:, j] = v_j / R[j, j]
    end
    return Q, R
end

function modified_gram_schmidt(A)
    m, n = size(A)
    R = zeros(Float64, n, n)
    Q = zeros(Float64, m, n)

    V = zeros(Float64, n, n)
    for i in 1:n
        V[:, i] = A[:, i]
    end

    for i in 1:n
        R[i, i] = norm(V[:, i])
        Q[:, i] = V[:, i] / R[i, i]
        for j in (i+1):n
            R[i, j] = dot(Q[:, i], V[:, j])
            V[:, j] = V[:, j] - R[i, j] * Q[:, i]
        end
    end
    return Q, R
end

function check_stability(Q)
    m, n = size(Q)
    total_dot_error = 0
    for i in 1:m
        for j in 1:n
            if i != j
                total_dot_error += abs(dot(Q[:, i], Q[:, j]))
            end
        end
    end
    return total_dot_error
end

max_stars_repo_name: CornellDataScience/interpret-ml

max_issues_repo_name: CornellDataScience/interpret-ml

max_forks_repo_name: CornellDataScience/interpret-ml


text:
using Test, LinearAlgebra, HssMatrices

# generate Cauchy matrix
K(x,y) = (x-y) > 0 ? 0.001/(x-y) : 2.
A = [ K(x,y) for x=-1:0.001:1, y=-1:0.001:1];
m, n = size(A)
U = randn(n,3); V = randn(n,3)
# "safety" factor
c = 1000.0

@testset "options" begin
    HssMatrices.setopts(atol=1e-6)
    @test HssOptions().atol == 1e-6
    HssMatrices.setopts(rtol=1e-6)
    @test HssOptions().rtol == 1e-6
    HssMatrices.setopts(leafsize=50)
    @test HssOptions().leafsize == 50
    HssMatrices.setopts(noversampling=5)
    @test HssOptions().noversampling == 5
    HssMatrices.setopts(stepsize=10)
    @test HssOptions().stepsize == 10
end

rcl = bisection_cluster(1:m)
ccl = bisection_cluster(1:n)

@testset "compression" begin
    hssA = compress(A, rcl, ccl);
    @test norm(A - full(hssA))/norm(A) ≤ c*HssOptions().rtol || norm(A - full(hssA)) ≤ c*HssOptions().atol
    hssB = randcompress_adaptive(A, rcl, ccl); rk = hssrank(hssB)
    @test norm(A - full(hssB))/norm(A) ≤ c*HssOptions().rtol || norm(A - full(hssB)) ≤ c*HssOptions().atol
    hssB = recompress!(hssB)
    @test norm(A - full(hssB))/norm(A) ≤ c*HssOptions().rtol || norm(A - full(hssB)) ≤ c*HssOptions().atol
    @test hssrank(hssB) ≤ rk
    hssC = lowrank2hss(U, V, ccl, ccl)
    @test norm(U*V' - full(hssC))/norm(U*V') ≤ c*eps()
    @test hssrank(hssC) == 3
end;

@testset "arithmetic" begin
    hssA = compress(A, rcl, ccl);
    hssC = lowrank2hss(U, V, ccl, ccl)
    @test norm(A' - full(hssA'))/norm(A) ≤ c*HssOptions().rtol || norm(A' - full(hssA')) ≤ c*HssOptions().atol
    x = randn(n, 5);
    @test norm(A*x - hssA*x)/norm(A*x) ≤ c*HssOptions().rtol || norm(A*x - hssA*x) ≤ c*HssOptions().atol
    @test norm(full(hssA*hssC) - (A*U)*V')/norm((A*U)*V') ≤ c*HssOptions().rtol || norm(A*x - hssA*x) ≤ c*HssOptions().atol
    rhs = randn(n, 5); x = hssA\rhs; x0 = A\rhs;
    @test norm(x0 - x)/norm(x0) ≤ c*HssOptions().rtol || norm(x0 - x) ≤ c*HssOptions().atol
    Id(i,j) = Matrix{Float64}(i.*ones(length(j))' .== ones(length(i)).*j')
    IdOp = LinearMap{Float64}(n, n, (y,_,x) -> x, (y,_,x) -> x, (i,j) -> Id(i,j))
    hssI = randcompress(IdOp, ccl, ccl, 0)
    @test norm(full(hssA*hssI) - full(hssA))/norm(full(hssA)) ≤ c*eps()
    Ainv = inv(A)
    @test norm(Ainv - full(hssA\hssI))/norm(Ainv) ≤ c*HssOptions().rtol || norm(Ainv - full(hssA\hssI)) ≤ c*HssOptions().atol
    @test norm(Ainv - full(hssI/hssA))/norm(Ainv) ≤ c*HssOptions().rtol || norm(Ainv - full(hssI/hssA)) ≤ c*HssOptions().atol
    hssA.A11 = prune_leaves!(hssA.A11)
    hssI.A11 = prune_leaves!(hssI.A11)
    @test norm(Ainv - full(hssA\hssI))/norm(Ainv) ≤ c*HssOptions().rtol || norm(Ainv - full(hssA\hssI)) ≤ c*HssOptions().atol
    @test norm(Ainv - full(hssI/hssA))/norm(Ainv) ≤ c*HssOptions().rtol || norm(Ainv - full(hssI/hssA)) ≤ c*HssOptions().atol
end


text:
using Dates
using TimeZones

function run_and_rollback(tx, args, kwargs)
    result = run(tx, args[1]; kwargs...)
    v = value(single(result))
    tx.success = false
    return v
end

@testset "CoreTypeOutputTestCase" begin
    tc = setup()

    @testset "test_null" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN null")
            @test value(single(result)) == nothing
        end
    end

    @testset "test_boolean" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN true")
            @test value(single(result)) == true
        end
    end

    @testset "test_integer" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN 123456789")
            @test value(single(result)) == 123456789
        end
    end

    @testset "test_float" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN 3.1415926")
            @test value(single(result)) == 3.1415926
        end
    end

    @testset "test_float_nan" begin
        session(tc.driver) do sess
            result = run(sess, "WITH \$x AS x RETURN x", x=NaN)
            @test isnan(value(single(result)))
        end
    end

    @testset "test_float_positive_infinity" begin
        session(tc.driver) do sess
            result = run(sess, "WITH \$x AS x RETURN x", x=Inf)
            @test value(single(result)) == Inf
        end
    end

    @testset "test_float_negative_infinity" begin
        session(tc.driver) do sess
            result = run(sess, "WITH \$x AS x RETURN x", x=-Inf)
            @test value(single(result)) == -Inf
        end
    end

    @testset "test_string" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN 'hello, world'")
            @test value(single(result)) == "hello, world"
        end
    end

    @testset "test_bytes" begin
        data = UInt8[0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF]
        session(tc.driver) do sess
            v = write_transaction(sess, run_and_rollback, "CREATE (a {x:\$x}) RETURN a.x", x=data)
            @test v == data
        end
    end

    @testset "test_list" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN ['one', 'two', 'three']")
            @test value(single(result)) == ["one", "two", "three"]
        end
    end

    @testset "test_map" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN {one: 'eins', two: 'zwei', three: 'drei'}")
            @test value(single(result)) == Dict("one"=>"eins", "two"=>"zwei", "three"=>"drei")
        end
    end

    @testset "test_non_string_map_keys" begin
        session(tc.driver) do sess
            @test_throws ErrorException run(sess, "RETURN \$x", x=Dict(1=>"eins", 2=>"zwei", 3=>"drei"))
        end
    end

    teardown(tc.driver)
end

@testset "GraphTypeOutputTestCase" begin
    tc = setup()

    @testset "test_node" begin
        session(tc.driver) do sess
            a = write_transaction(sess, run_and_rollback, "CREATE (a:Person {name:'Alice'}) RETURN a")
            @test isa(a, Node)
            @test a.labels == Set(["Person"])
            @test a.properties == Dict("name"=>"Alice")
        end
    end

    @testset "test_relationship" begin
        session(tc.driver) do sess
            a, b, r = write_transaction(sess, run_and_rollback, "CREATE (a)-[r:KNOWS {since:1999}]->(b) RETURN [a, b, r]")
            @test isa(r, Relationship)
            @test r.type == "KNOWS"
            @test r.properties == Dict("since"=>1999)
            @test r.start_node == a
            @test r.end_node == b
        end
    end

    @testset "test_path" begin
        session(tc.driver) do sess
            a, b, c, ab, bc, p = write_transaction(sess, run_and_rollback, "CREATE p=(a)-[ab:X]->(b)-[bc:X]->(c) RETURN [a, b, c, ab, bc, p]")
            @test isa(p, Path)
            @test length(p) == 2
            @test p.nodes == [a,b,c]
            @test start_node(p) == a
            @test end_node(p) == c
        end
    end

    teardown(tc.driver)
end

@testset "SpatialTypeInputTestCase" begin
    tc = setup()

    @testset "test_cartesian_point" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$point AS point RETURN point.x, point.y", point=CartesianPoint((1.23, 4.56)))
            x, y = values(single(result))
            @test x == 1.23
            @test y == 4.56
        end
    end

    @testset "test_cartesian_3d_point" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$point AS point RETURN point.x, point.y, point.z", point=CartesianPoint((1.23, 4.56, 7.89)))
            x, y, z = values(single(result))
            @test x == 1.23
            @test y == 4.56
            @test z == 7.89
        end
    end

    @testset "test_wgs84_point" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$point AS point RETURN point.latitude, point.longitude", point=WGS84Point((1.23, 4.56)))
            latitude, longitude = values(single(result))
            @test longitude == 1.23
            @test latitude == 4.56
        end
    end

    @testset "test_wgs84_3d_point" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$point AS point RETURN point.latitude, point.longitude, point.height", point=WGS84Point((1.23, 4.56, 7.89)))
            latitude, longitude, height = values(single(result))
            @test longitude == 1.23
            @test latitude == 4.56
            @test height == 7.89
        end
    end

    @testset "test_point_array" begin
        session(tc.driver) do sess
            data = [WGS84Point((1.23, 4.56)), WGS84Point((9.87, 6.54))]
            v = write_transaction(sess, run_and_rollback, "CREATE (a {x:\$x}) RETURN a.x", x=data)
            @test v == data
        end
    end

    teardown(tc.driver)
end

@testset "SpatialTypeOutputTestCase" begin
    tc = setup()

    @testset "test_cartesian_point" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN point({x:3, y:4})")
            v = value(single(result))
            @test isa(v, CartesianPoint)
            @test v.x == 3.0
            @test v.y == 4.0
            @test_throws ErrorException _ = v.z
        end
    end

    @testset "test_cartesian_3d_point" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN point({x:3, y:4, z:5})")
            v = value(single(result))
            @test isa(v, CartesianPoint)
            @test v.x == 3.0
            @test v.y == 4.0
            @test v.z == 5.0
        end
    end

    @testset "test_wgs84_point" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN point({latitude:3, longitude:4})")
            v = value(single(result))
            @test isa(v, WGS84Point)
            @test v.latitude == 3.0
            @test v.longitude == 4.0
            @test v.y == 3.0
            @test v.x == 4.0
            @test_throws ErrorException _ = v.height
            @test_throws ErrorException _ = v.z
        end
    end

    @testset "test_wgs84_3d_point" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN point({latitude:3, longitude:4, height:5})")
            v = value(single(result))
            @test isa(v, WGS84Point)
            @test v.latitude == 3.0
            @test v.longitude == 4.0
            @test v.height == 5.0
            @test v.y == 3.0
            @test v.x == 4.0
            @test v.z == 5.0
        end
    end

    teardown(tc.driver)
end

@testset "TemporalTypeInputTestCase" begin
    tc = setup()

    @testset "test_native_date" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$x AS x RETURN x.year, x.month, x.day", x=Date(1976, 6, 13))
            year, month, day = values(single(result))
            @test year == 1976
            @test month == 6
            @test day == 13
        end
    end

    @testset "test_date_wrapper" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$x AS x RETURN x.year, x.month, x.day", x=DateWrapper(1976, 6, 13))
            year, month, day = values(single(result))
            @test year == 1976
            @test month == 6
            @test day == 13
        end
    end

    @testset "test_date_array" begin
        session(tc.driver) do sess
            data = [today(), Date(1976, 6, 13)]
            v = write_transaction(sess, run_and_rollback, "CREATE (a {x:\$x}) RETURN a.x", x=data)
            @test data == v
        end
    end

    @testset "test_native_time" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$x AS x RETURN x.hour, x.minute, x.second, x.nanosecond", x=Time(12, 34, 56, 789, 012))
            hour, minute, second, nanosecond = values(single(result))
            @test hour == 12
            @test minute == 34
            @test second == 56
            @test nanosecond == 789012000
        end
    end

    @testset "test_time_wrapper" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$x AS x RETURN x.hour, x.minute, x.second, x.nanosecond", x=TimeWrapper(12, 34, 56, 789012000))
            hour, minute, second, nanosecond = values(single(result))
            @test hour == 12
            @test minute == 34
            @test second == 56
            @test nanosecond == 789012000
        end
    end

    @testset "test_whole_second_time" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$x AS x RETURN x.hour, x.minute, x.second", x=Time(12, 34, 56))
            hour, minute, second = values(single(result))
            @test hour == 12
            @test minute == 34
            @test second == 56
        end
    end

    @testset "test_nanosecond_resolution_time" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$x AS x RETURN x.hour, x.minute, x.second, x.nanosecond", x=Time(12, 34, 56, 789, 012, 345))
            hour, minute, second, nanosecond = values(single(result))
            @test hour == 12
            @test minute == 34
            @test nanosecond == 789012345
        end
    end

    @testset "test_time_with_numeric_time_offset" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$x AS x RETURN x.hour, x.minute, x.second, x.nanosecond, x.offset", x=TimeWrapper(12, 34, 56, 789012345, timezone=90))
            hour, minute, second, nanosecond, offset = values(single(result))
            @test hour == 12
            @test minute == 34
            @test nanosecond == 789012345
            @test offset == "+01:30"
        end
    end

    @testset "test_time_array" begin
        session(tc.driver) do sess
            data = [Time(12, 34, 56), Time(10, 0, 0)]
            v = write_transaction(sess, run_and_rollback, "CREATE (a {x:\$x}) RETURN a.x", x=data)
            @test v == data
        end
    end

    @testset "test_native_datetime" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$x AS x " *
                                 "RETURN x.year, x.month, x.day, " *
                                 "x.hour, x.minute, x.second, x.nanosecond", x=DateTime(1976, 6, 13, 12, 34, 56, 789))
            year, month, day, hour, minute, second, nanosecond = values(single(result))
            @test year == 1976
            @test month == 6
            @test day == 13
            @test hour == 12
            @test minute == 34
            @test second == 56
            @test nanosecond == 789000000
        end
    end

    @testset "test_datetime_wrapper" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$x AS x " *
                                 "RETURN x.year, x.month, x.day, " *
                                 "x.hour, x.minute, x.second, x.nanosecond", x=DateTimeWrapper(1976, 6, 13, 12, 34, 56, 789012000))
            year, month, day, hour, minute, second, nanosecond = values(single(result))
            @test year == 1976
            @test month == 6
            @test day == 13
            @test hour == 12
            @test minute == 34
            @test second == 56
            @test nanosecond == 789012000
        end
    end

    @testset "test_whole_second_datetime" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$x AS x " *
                                 "RETURN x.year, x.month, x.day, " *
                                 "x.hour, x.minute, x.second", x=DateTime(1976, 6, 13, 12, 34, 56))
            year, month, day, hour, minute, second = values(single(result))
            @test year == 1976
            @test month == 6
            @test day == 13
            @test hour == 12
            @test minute == 34
            @test second == 56
        end
    end

    @testset "test_nanosecond_resolution_datetime" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$x AS x " *
                                 "RETURN x.year, x.month, x.day, " *
                                 "x.hour, x.minute, x.second, x.nanosecond", x=DateTimeWrapper(1976, 6, 13, 12, 34, 56, 789012345))
            year, month, day, hour, minute, second, nanosecond = values(single(result))
            @test year == 1976
            @test month == 6
            @test day == 13
            @test hour == 12
            @test minute == 34
            @test second == 56
            @test nanosecond == 789012345
        end
    end

    @testset "test_zoneddatetime_with_numeric_time_offset" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$x AS x " *
                                 "RETURN x.year, x.month, x.day, " *
                                 "x.hour, x.minute, x.second, x.nanosecond, x.offset", x=ZonedDateTime(DateTime(1976, 6, 13, 12, 34, 56, 789), FixedTimeZone("TZ", 90 * 60)))
            year, month, day, hour, minute, second, nanosecond, offset = values(single(result))
            @test year == 1976
            @test month == 6
            @test day == 13
            @test hour == 12
            @test minute == 34
            @test second == 56
            @test nanosecond == 789000000
            @test offset == "+01:30"
        end
    end

    @testset "test_datetime_wrapper_with_numeric_time_offset" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$x AS x " *
                                 "RETURN x.year, x.month, x.day, " *
                                 "x.hour, x.minute, x.second, x.nanosecond, x.offset", x=DateTimeWrapper(1976, 6, 13, 12, 34, 56, 789012345, timezone=90))
            year, month, day, hour, minute, second, nanosecond, offset = values(single(result))
            @test year == 1976
            @test month == 6
            @test day == 13
            @test hour == 12
            @test minute == 34
            @test second == 56
            @test nanosecond == 789012345
            @test offset == "+01:30"
        end
    end

    @testset "test_zoneddatetime_with_named_time_zone" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$x AS x " *
                                 "RETURN x.year, x.month, x.day, " *
                                 "x.hour, x.minute, x.second, x.nanosecond, x.timezone", x=ZonedDateTime(DateTime(1976, 6, 13, 12, 34, 56, 789), tz"America/Los_Angeles"))
            year, month, day, hour, minute, second, nanosecond, tz = values(single(result))
            @test year == 1976
            @test month == 6
            @test day == 13
            @test hour == 12
            @test minute == 34
            @test second == 56
            @test nanosecond == 789000000
            @test tz == "America/Los_Angeles"
        end
    end

    @testset "test_datetimewrapper_with_named_time_zone" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$x AS x " *
                                 "RETURN x.year, x.month, x.day, " *
                                 "x.hour, x.minute, x.second, x.nanosecond, x.timezone", x=DateTimeWrapper(1976, 6, 13, 12, 34, 56, 789012345, timezone="US/Pacific"))
            year, month, day, hour, minute, second, nanosecond, tz = values(single(result))
            @test year == 1976
            @test month == 6
            @test day == 13
            @test hour == 12
            @test minute == 34
            @test second == 56
            @test nanosecond == 789012345
            @test tz == "US/Pacific"
        end
    end

    @testset "test_duration" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$x AS x " *
                                 "RETURN x.months, x.days, x.seconds, x.microsecondsOfSecond", x=(Year(1) + Month(2) + Day(3) + Hour(4) + Minute(5) + Second(6) + Microsecond(789012)))
            months, days, seconds, microseconds = values(single(result))
            @test months == 14
            @test days == 3
            @test seconds == 14706
            @test microseconds == 789012
        end
    end

    @testset "test_duration_wrapper" begin
        session(tc.driver) do sess
            result = run(sess, "CYPHER runtime=interpreted WITH \$x AS x " *
                                 "RETURN x.months, x.days, x.seconds, x.microsecondsOfSecond", x=DurationWrapper(years=1, months=2, days=3, hours=4, minutes=5, seconds=6, nanoseconds=789012000))
            months, days, seconds, microseconds = values(single(result))
            @test months == 14
            @test days == 3
            @test seconds == 14706
            @test microseconds == 789012
        end
    end

    @testset "test_duration_array" begin
        session(tc.driver) do sess
            data = [(Year(1) + Month(2) + Day(3) + Hour(4) + Minute(5) + Second(6)), (Year(9) + Month(8) + Day(7) + Hour(6) + Minute(5) + Second(4))]
            v = write_transaction(sess, run_and_rollback, "CREATE (a {x:\$x}) RETURN a.x", x=data)
            @test v == data
        end
    end

    @testset "test_mixed_array" begin
        session(tc.driver) do sess
            data = [Date(1976, 6, 13), (Year(9) + Month(8) + Day(7) + Hour(6) + Minute(5) + Second(4))]
            @test_throws Neo4jBolt.JuliaBolt.CypherTypeError write_transaction(sess, run_and_rollback, "CREATE (a {x:\$x}) RETURN a.x", x=data)
        end
    end

    teardown(tc.driver)
end

@testset "TemporalTypeOutputTestCase" begin
    tc = setup()

    @testset "test_date" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN date('1976-06-13')")
            v = value(single(result))
            @test isa(v, Date)
            @test v == Date(1976, 6, 13)
        end
    end

    @testset "test_date_wrapper" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN date('1976-06-13')", use_julia_dates=false)
            v = value(single(result))
            @test isa(v, DateWrapper)
            @test v == DateWrapper(1976, 6, 13)
        end
    end

    @testset "test_whole_second_time" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN time('12:34:56')")
            v = value(single(result))
            @test isa(v, Time)
            @test v == Time(12, 34, 56)
        end
    end

    @testset "test_nanosecond_resolution_time" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN time('12:34:56.789012345')")
            v = value(single(result))
            @test isa(v, Time)
            @test v == Time(12, 34, 56, 789, 012, 345)
        end
    end

    @testset "test_time_wrapper_with_numeric_time_offset" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN time('12:34:56.789012345+0130')", use_julia_dates=false)
            v = value(single(result))
            @test isa(v, TimeWrapper)
            @test v == TimeWrapper(12, 34, 56, 789012345, timezone=90)
        end
    end

    @testset "test_whole_second_time_wrapper" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN localtime('12:34:56')", use_julia_dates=false)
            v = value(single(result))
            @test isa(v, TimeWrapper)
            @test v == TimeWrapper(12, 34, 56)
        end
    end

    @testset "test_whole_second_datetime" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN datetime('1976-06-13T12:34:56')")
            v = value(single(result))
            @test isa(v, ZonedDateTime)
            @test v == ZonedDateTime(DateTime(1976, 6, 13, 12, 34, 56), tz"UTC")
        end
    end

    @testset "test_nanosecond_resolution_datetime" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN datetime('1976-06-13T12:34:56.789012345')", use_julia_dates=false)
            v = value(single(result))
            @test isa(v, DateTimeWrapper)
            @test v == DateTimeWrapper(1976, 6, 13, 12, 34, 56, 789012345, timezone=0)
        end
    end

    @testset "test_datetime_wrapper_with_numeric_time_offset" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN datetime('1976-06-13T12:34:56.789012345+01:30')", use_julia_dates=false)
            v = value(single(result))
            @test isa(v, DateTimeWrapper)
            @test v == DateTimeWrapper(1976, 6, 13, 12, 34, 56, 789012345, timezone=90)
        end
    end

    @testset "test_zoned_datetime_with_numeric_time_offset" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN datetime('1976-06-13T12:34:56.789+01:30')")
            v = value(single(result))
            @test isa(v, ZonedDateTime)
            @test v == ZonedDateTime(DateTime(1976, 6, 13, 12, 34, 56, 789), FixedTimeZone("TZ", 90*60))
        end
    end

    @testset "test_zoned_datetime_with_named_time_zone" begin
        session(tc.driver) do sess
            result = run(sess,"RETURN datetime('1976-06-13T12:34:56.789012345[Europe/London]')")
            v = value(single(result))
            @test isa(v, ZonedDateTime)
            @test v == ZonedDateTime(DateTime(1976, 6, 13, 12, 34, 56, 789), tz"Europe/London")
        end
    end

    @testset "test_datetime_wrapper_with_named_time_zone" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN datetime('1976-06-13T12:34:56.789012345[Europe/London]')", use_julia_dates=false)
            v = value(single(result))
            @test isa(v, DateTimeWrapper)
            @test v == DateTimeWrapper(1976, 6, 13, 12, 34, 56, 789012345, timezone="Europe/London")
        end
    end

    @testset "test_whole_second_localdatetime" begin
        session(tc.driver) do sess
            result = run(sess,"RETURN localdatetime('1976-06-13T12:34:56')")
            v = value(single(result))
            @test isa(v, DateTime)
            @test v == DateTime(1976, 6, 13, 12, 34, 56)
        end
    end

    @testset "test_nanosecond_resolution_localdatetime_wrapper" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN localdatetime('1976-06-13T12:34:56.789012345')", use_julia_dates=false)
            v = value(single(result))
            @test isa(v, DateTimeWrapper)
            @test v == DateTimeWrapper(1976, 6, 13, 12, 34, 56, 789012345)
        end
    end

    @testset "test_duration_compound_period" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN duration('P1Y2M3DT4H5M6.789S')")
            v = value(single(result))
            @test isa(v, Dates.CompoundPeriod)
            @test v == Year(1) + Month(2) + Day(3) + Hour(4) + Minute(5) + Second(6) + Millisecond(789)
        end
    end

     @testset "test_duration_wrapper" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN duration('P1Y2M3DT4H5M6.789S')", use_julia_dates=false)
            v = value(single(result))
            @test isa(v, DurationWrapper)
            @test v == DurationWrapper(1,2,3,4,5,6,789000000)
        end
    end

    @testset "test_nanosecond_resolution_duration_compound_period" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN duration('P1Y2M3DT4H5M6.789123456S')")
            v = value(single(result))
            @test isa(v, Dates.CompoundPeriod)
            @test v == Year(1) + Month(2) + Day(3) + Hour(4) + Minute(5) + Second(6) + Nanosecond(789123456)
        end
    end

     @testset "test_nanosecond_resolution_duration_wrapper" begin
        session(tc.driver) do sess
            result = run(sess, "RETURN duration('P1Y2M3DT4H5M6.789123456S')", use_julia_dates=false)
            v = value(single(result))
            @test isa(v, DurationWrapper)
            @test v == DurationWrapper(1,2,3,4,5,6,789123456)
        end
    end

    teardown(tc.driver)
end


text:
# using HOODESolver
include("../test/henon_heiles.jl")
include("../src/preparephi.jl")
using Printf

function _printnumstr( num::BigFloat)
    str = @sprintf("%1.200e", num)
    println("parse(")
    println("    BigFloat," )
    println("    \"$(str[1:70])\" *")
    println("    \"$(str[71:140])\" *")
    println("    \"$(str[141:end])\"")
    print(") ")
end

function print_for_test(
    order,
    u0,
    tab_eps,
    n_tau,
    matrix_A::Matrix,
    fct::Function
)
    prec=precision(BigFloat)
    setprecision(1024)
    println("# PrepareU0 order=$order n_tau =$n_tau")

    println("# tab_u0 i prepared data for each order from 2 to order")
    println(" u0=$u0")
    println("# this file is generated by gendataprep_u0.jl file")
    println("function get_prepare_u0_for_test()")
    size_eps=size(tab_eps,1)
    println("    tab_u0 = zeros(Complex{BigFloat}, $(size(u0,1)), $n_tau, $order, $size_eps)")
    for i_eps=1:size_eps
        epsilon = big(1)/big(2)^tab_eps[i_eps]
        par = PreparePhi(epsilon, n_tau, matrix_A, fct)
        for ord=2:order
            pu0= PrepareU0(par, ord, BigFloat.(u0), 4096)
            println("    tab_u0[ :, :, $ord, $i_eps] .= [")
            for i=1:par.size_vect
                for i_ell=1:n_tau
                    print("    ")
                    _printnumstr(real(pu0.ut0[i, i_ell]))
                end
                println("")
            end
            println("]")
        end
    end

    println("    tab_eps = [")
    for i_eps=1:size_eps
        println("    $(big(1)/big(2)^tab_eps[i_eps]),")
    end
    println("]")

    println("    return tab_u0, tab_eps")
    println("end")

    setprecision(prec)
end

print_for_test(
    15,
    BigFloat.([0.125, 0.140625, 0.15625, 0.171875]),
    [8, 16, 32],
    32,
    [0 0 1 0; 0 0 0 0; -1 0 0 0; 0 0 0 0],
    henon_heiles,
)


text:
using Documenter, StructuralCausalModels

DOC_ROOT = scm_path("..", "docs")
DocDir =  joinpath(DOC_ROOT, "src")

page_list = Array{Pair{String, Any}, 1}();
append!(page_list, [Pair("Introduction", "introduction.md")]);
append!(page_list, [Pair("Walkthrough", "walkthrough.md")]);
append!(page_list, [Pair("Versions", "versions.md")]);
append!(page_list, [Pair("Acknowledgements", "acknowledgements.md")]);
append!(page_list, [Pair("References", "references.md")]);
append!(page_list, [Pair("StructuralCausalModels API", "index.md")]);

makedocs(
    modules = [StructuralCausalModels],
    format = Documenter.HTML(; prettyurls = get(ENV, "CI", nothing) == "true"),
    authors = "Rob J Goedman",
    sitename = "StructuralCausalModels.jl",
    pages = page_list
    # strict = true,
    # clean = true,
    # checkdocs = :exports,
)

deploydocs(
    repo = "github.com/StatisticalRethinkingJulia/StructuralCausalModels.jl.git",
    push_preview = true
)


text:
mutable struct ProxALGeneratorModel{TD} <: AbstractGeneratorModel
    ngen::Int
    gen_start::Int
    pgmin::TD
    pgmax::TD
    qgmin::TD
    qgmax::TD
    c2::TD
    c1::TD
    c0::TD

    t_curr::Int      # current time period
    T::Int           # size of time horizon
    tau::Float64     # penalty for proximal term
    rho::Float64     # penalty for ramping equality
    pg_ref::TD       # proximal term
    pg_next::TD      # primal value for (t+1) time period
    l_next::TD       # dual (for ramping) value for (t-1) time period
    pg_prev::TD      # primal value for (t+1) time period
    l_prev::TD       # dual (for ramping) value for (t-1) time period
    s_curr::TD       # slack for ramping
    smin::TD         # slack's lower bound
    smax::TD         # slack's upper bound

    Q_ref::TD
    c_ref::TD

    Q::TD
    c::TD
end
function ProxALGeneratorModel(modelgen::GeneratorModel{TD}, t::Int, T::Int) where TD
    pg_ref  = TD(undef, modelgen.ngen)  ; fill!(pg_ref, 0.0)
    pg_next = TD(undef, modelgen.ngen)  ; fill!(pg_next, 0.0)
    l_next  = TD(undef, modelgen.ngen)  ; fill!(l_next, 0.0)
    pg_prev = TD(undef, modelgen.ngen)  ; fill!(pg_prev, 0.0)
    l_prev  = TD(undef, modelgen.ngen)  ; fill!(l_prev, 0.0)
    s_curr  = TD(undef, modelgen.ngen)  ; fill!(s_curr, 0.0)
    s_min   = TD(undef, modelgen.ngen)  ; fill!(s_min, 0.0)
    s_max   = TD(undef, modelgen.ngen)  ; fill!(s_max, 0.0)
    Q       = TD(undef, modelgen.ngen*4); fill!(Q, 0.0)
    c       = TD(undef, modelgen.ngen*2); fill!(c, 0.0)
    Q_ref   = TD(undef, modelgen.ngen*4); fill!(Q_ref, 0.0)
    c_ref   = TD(undef, modelgen.ngen*2); fill!(c_ref, 0.0)
    return ProxALGeneratorModel{TD}(
        modelgen.ngen, modelgen.gen_start,
        modelgen.pgmin, modelgen.pgmax, modelgen.qgmin, modelgen.qgmax, modelgen.c2, modelgen.c1, modelgen.c0,
        t, T, 0.1, 0.1, pg_ref, pg_next, l_next, pg_prev, l_prev, s_curr, s_min, s_max, Q_ref, c_ref, Q, c
    )
end

function ProxALAdmmEnv(opfdata::OPFData, use_gpu::Bool, t, T, rho_pq, rho_va; options...)
    env = AdmmEnv(opfdata, use_gpu, rho_pq, rho_va; options...)
    model = env.model
    # Replace generator's model by ProxAL model
    env.model.gen_mod = ProxALGeneratorModel(env.model.gen_mod, t, T)
    return env
end

# GETTERS
slack_values(env::AdmmEnv) = env.model.gen_mod.s_curr

# SETTERS
macro define_setter_array(function_name, attribute)
    fname = Symbol(function_name)
    quote
        function $(esc(fname))(env::AdmmEnv, values::AbstractVector)
            model = env.model
            @assert isa(model.gen_mod, ProxALGeneratorModel)
            copyto!(model.gen_mod.$attribute, values)
            return
        end
    end
end

macro define_setter_value(function_name, attribute)
    fname = Symbol(function_name)
    quote
        function $(esc(fname))(env::AdmmEnv, value::AbstractFloat)
            model = env.model
            @assert isa(model.gen_mod, ProxALGeneratorModel)
            model.gen_mod.$attribute = value
            return
        end
    end
end

@define_setter_array set_lower_bound_slack! smin
@define_setter_array set_upper_bound_slack! smax
@define_setter_array set_slack! s_curr
@define_setter_array set_multiplier_last! l_prev
@define_setter_array set_multiplier_next! l_next
@define_setter_array set_proximal_last! pg_prev
@define_setter_array set_proximal_next! pg_next
@define_setter_array set_proximal_ref! pg_ref

@define_setter_value set_proximal_term! tau
@define_setter_value set_penalty! rho


text:
using DataFrames, Dash, DashHtmlComponents, DashCoreComponents, UrlDownload, PlotlyJS, JSON3
using Statistics
using LinearAlgebra
using CSV
using RCall

app = dash()

#calling R libraries

    R"""
    source("RScripts/preamble.R")
    """

#dataframes for R analysis
genon = DataFrame(CSV.File("RScripts/GO_final.txt"))
cellNew = DataFrame(CSV.File("RScripts/cell_new_final.txt"))

Yte=Matrix(CSV.read("PCA_matrix_log2.txt",DataFrame))
PCM = DataFrame(CSV.File("data/Kidney_Q3Norm_TargetCountMatrix.txt"))
print(PCM[2,2])
foreach(n -> PCM[!, n] = log2.(PCM[!, n]), names(PCM)[2:end])
print(PCM[2,2])
features = DataFrame(CSV.File("data/Kidney_Sample_Annotations.txt"))
structuresDict = Dict("abnormal"=>"Glom (Abnormal)","healthy"=>"Glom (Healthy)"," PanCK" => "Tub. Distal", " neg" => "Tub. Proximal")
comprehensiveStates = [structuresDict[ismissing(row.pathology) ? split(row["SegmentDisplayName"],"|")[3] : row.pathology] for row in eachrow(features)]
genes = PCM.TargetName
diseaseStatusMarkers = replace(features[:,"disease_status"], "DKD" => "triangle-up", "normal" => "circle")
# diseaseStatusMarkers .= relpace.(diseaseStatusMarkers, "DKD", "square")
insertcols!(features,"states"=>comprehensiveStates)
insertcols!(features, "barID" =>["$(row[1]) | $(row[2])" for row in eachrow( features[!,["ROILabel","states"]]) ])

CellTypes = DataFrame(CSV.File("data/Cell_Types_for_Spatial_Decon.txt"))
GO = DataFrame(CSV.File("data/Kidney_ssGSEA.txt"))
rename!(GO, names(GO)[2:end] .=> features.Sample_ID)
#group immune together
CellTypes[end-15:end,9].="Immune"
CDC = DataFrame(CSV.File("data/Kidney_Spatial_Decon.txt"))
rename!(CDC, names(CDC)[2:end] .=> features.Sample_ID)
insertcols!(CDC,  "cellGroup" => [CellTypes[ CellTypes.Alias .== row[1],9][1] for row in eachrow(CDC)])
to_group = names(CDC[!, Not(["Alias", "cellGroup"])])
newCDC = combine(groupby(CDC,"cellGroup"), to_group .=> sum .=> to_group)
cells = CDC.Alias
cellGroups = newCDC.cellGroup

diseaseOptions = [
    Dict("label" => "Normal", "value" => "normal"),
    Dict("label" => "DKD", "value" => "DKD"),
]

function generate_table(dataframe, max_rows = 10)
    html_table([
        html_thead(html_tr([html_th(col) for col in names(dataframe)])),
        html_tbody([
            html_tr([html_td(dataframe[r, c]) for c in names(dataframe)]) for r = 1:min(nrow(dataframe), max_rows)
        ]),
    ])
end

app = dash()

#available_indicators = ["disease_status","region","pathology"]]

patients = unique(features.SlideName)
patientsNormal = patients[ occursin.("normal", patients) ]
patientsDKD = patients[ occursin.("disease", patients) ]

app.layout = html_div() do
    html_div(
        children = [

    	    html_h1(
				"Data Visualization App",
        		style = Dict("color" => "#0066cc", "textAlign" => "left"),
    		),
		    dcc_markdown("## Data selection"),
            html_div("Select data to plot:"),
        	html_div(
        		children = [
        		html_div(
		            dcc_dropdown(
		                id = "crossfilter-roi-type",
		                options = [
		                    (label = i, value = i)
		                    for i in values(structuresDict)
		                ],
		                multi = true,
		                # value = first(values(structuresDict)),
		                placeholder = "Select type of structure",
		                style = (width = "70%", display = "block", marginBottom = "5px")
		            ),
	            	# style = (width = "100%")
	            ),

	            ##Sync to patients in crossfilter-patient
	            html_div(
		            dcc_dropdown(
		                id = "crossfilter-patient",
		                options = [
		                    (label = i, value = i)
		                    for i in patients
		                ],
		                multi = true,
		                # value = [patients[1]],
		                placeholder = "Select patient",
		                style = (width = "70%", display = "block", marginBottom = "5px")
		            ),
	            ),

	            ##Add checkbox for healthy vs DKD
	            html_button(id = "buttonAll", children = "All", n_clicks = 0),
	            html_button(id = "buttonDKD", children = "▲ - DKD", n_clicks = 0),
	            html_button(id = "buttonNormal", children = "● - Normal", n_clicks = 0),
	            html_button(id = "buttonClear", children = "Clear", n_clicks = 0),
	            ],
	            style = (borderBottom = "thin lightgrey solid", backgroundColor = "rgb(250, 250, 250)", padding = "10px 5px",),
            ),

        	html_div(
        		children = [
		            dcc_graph(
		                id = "graph-1",
		            ),
	            ],
                style = ( width = "49%", display = "inline-block"),
            ),

        	html_div(
        		children = [
		            dcc_graph(
		                id = "graph-2",
		            ),
	            ],
                style = ( width = "49%", display = "inline-block"),
            ),

            dcc_markdown("## Group selection"),
            dcc_markdown("Select a region of interest from any of the plots above and store the information in a group."),
            dcc_dropdown(
                id = "stage",
                options = [
                    (label = i, value = i)
                    for i in unique(features.SegmentDisplayName)
                ],
                multi = true,
                value =features[1,"SegmentDisplayName"],
            ),
            html_button(id = "g1", children = "Store in group 1", n_clicks = 0),
            html_button(id = "g2", children = "Store in group 2", n_clicks = 0),
            html_div(
                children = [
                    dcc_markdown("
                    **Group 1**
                    "),
                    html_pre(id = "g1-header"),
                ],
            ),
            dcc_dropdown(
                id = "group1",
                options = [
                    (label = i, value = i)
                    for i in unique(features.SegmentDisplayName)
                ],
                multi = true,
                value =features[1:2,"SegmentDisplayName"],
            ),
            html_div(
                children = [
                    dcc_markdown("
                    **Group 2**
                    "),
                    html_pre(id = "g2-header"),
                ],
            ),
            dcc_dropdown(
                id = "group2",
                options = [
                    (label = i, value = i)
                    for i in unique(features.SegmentDisplayName)
                ],
                multi = true,
                value =features[3:4,"SegmentDisplayName"],
            ),
            html_div(
                children = [
                    dcc_markdown("
                    **R - Analysis**
                    Use the data from the selected groups (Gene expression, Cell Deconvolution, GESA)
                    "),
                    html_pre(id = "aaaa"),
                ],
            ),
            html_div(id = "dummy", children = "e"),

            html_button(id = "RRun", children = "Execute R Analysis", n_clicks = 0),

            #Group analysis
            html_div(
                children = [
                    dcc_markdown("
                    **BubblePlot**
                    "),
                    html_pre(id = "bubble-header"),
                ],
            ),
            #restrict to patients present in group1 intersection group2
            dcc_dropdown(
                id = "patientsBubble",
                options = [
                    (label = i, value = i)
                    for i in patients
                ],
                value =patients[1],
            ),
            dcc_dropdown(
                id = "geneBubble",
                options = [
                    (label = i, value = i)
                    for i in genes
                ],
                value = genes[1],
            ),

            dcc_graph(
                id = "bubblePlot1",
            ),
            dcc_dropdown(
                id = "cellBubble",
                options = [
                    (label = i, value = i)
                    for i in cellGroups
                ],
                value = cellGroups[1],
            ),

            dcc_graph(
                id = "bubblePlot2",
            ),

        	html_div(
        		children = [
                    dcc_graph(
                        id = "bar1",
                    ),
	            ],
                style = ( width = "49%", display = "inline-block"),
            ),

        	html_div(
        		children = [
                    dcc_graph(
                        id = "bar2",
                    ),
	            ],
                style = ( width = "49%", display = "inline-block"),
            ),
        ],
        style = (
            borderBottom = "thin lightgrey solid",
            backgroundColor = "rgb(250, 250, 250)",
            padding = "10px 5px",
        ),
    )
end

callback!(
    app,
    Output("crossfilter-patient", "value"),
    Input("buttonNormal", "n_clicks"),
    Input("buttonDKD", "n_clicks"),
    Input("buttonAll", "n_clicks"),
    Input("buttonClear", "n_clicks"),
    State("crossfilter-patient", "value"),
) do clickNormal, clickDKD, clickAll, clickClear, patientList

    ctx = callback_context()
    if isempty(ctx.triggered)
    	return patientList
    end

    trigger = ctx.triggered[1]
    button_id = split(trigger.prop_id, ".")[1]

    if button_id == "buttonAll"
    	return patients
    end
    if button_id == "buttonClear"
    	return []
    end
    if button_id == "buttonDKD"
    	#patientList = union(patientList,patientsDKD)
    	 patientList = patientsDKD
    end
    if button_id == "buttonNormal"
    	#patientList = union(patientList,patientsNormal)
    	 patientList = patientsNormal
    end

    return patientList

end

callback!(
    app,
    Output("graph-1", "figure"),
    Input("crossfilter-roi-type", "value"),
    # Input("crossfilter-disease-status", "value"),
    Input("crossfilter-patient", "value"),
) do roiList, patientList

	# if no selection return empty plot
	if roiList == nothing
        return (data = [], layout = (title = "By Structure", xaxis_title = "", yaxis_title = "", clickmode = "event+select",))
    end

    # diseaseFilter = true
    # if !isempty(diseaseStatus)
    # 	for ds in diseaseStatus
    # 		diseaseFilter = (features[!,"disease_status"] .== ds) .| diseaseFilter
    # 	end
    # end

    patientFilter = false
    if patientList != nothing
    	patientFilter = [slide in patientList for slide in features.SlideName]
    end

    accumFilter = patientFilter # .& diseaseFilter

    plotData = [    ( x = Yte[1, (comprehensiveStates .== status) .& accumFilter], y = Yte[2, (comprehensiveStates .== status) .& accumFilter],  type = "scatter", name = status, mode = "markers", marker = (size = 8, symbol = diseaseStatusMarkers[ (comprehensiveStates .== status) .& accumFilter ], ), text = features[(comprehensiveStates .== status) .& accumFilter,"SlideName" ], customdata = features[(comprehensiveStates .== status) .& accumFilter,"SegmentDisplayName" ]) for status in roiList]

    return (
        data = plotData,
        layout = (
            title = "By Structure",
            xaxis = (title = "pca_1",),
            yaxis = (title = "pca_2",),
            clickmode = "event+select",
        ),
    )

end

callback!(
    app,
    Output("graph-2", "figure"),
    Input("crossfilter-patient", "value"),
    Input("stage", "value"),
    Input("crossfilter-roi-type", "value"),
) do patientList, selected_data, roiList

	# if no selection return empty plot
	if patientList == nothing
        return ( data = [], layout =  "title" => "By Patient"  )
    end

    selectedFilter = true
    # if selected_data != nothing
    # 	selectedFilter = [x in selected_data for x in features[!,"SegmentDisplayName"]]
    # end

	roiFilter = false
	if roiList != nothing
    	roiFilter = [x in roiList for x in comprehensiveStates]
    end

    accumFilter = selectedFilter .& roiFilter
    # accumFilter = true

    selector = "SlideName"

    plotData = [    ( x = Yte[1, (features[!,selector] .== status ) .& accumFilter ], y = Yte[2, (features[!,selector] .== status) .& accumFilter],  type = "scatter", name = status, mode = "markers", text = comprehensiveStates[(features[!,selector] .== status) .& accumFilter]	) for status in patientList]

    return (
        data = plotData,
        layout = (
            title = "By Patient",
            xaxis = (title = "pca_1",),
            yaxis = (title = "pca_2",),
        ),
    )
end

callback!(
    app,
    Output("stage", "value"),
    Input("graph-1", "selectedData"),
) do selected_data
    selectedpoints = 1:2
    if selected_data != nothing
        selectedpoints = [p[:customdata] for p in selected_data.points]
        #print(selectedpoints)
    end
    #print(features[selectedpoints, "SegmentDisplayName"])
    #return features[selectedpoints, "SegmentDisplayName"]
    return selectedpoints
end

#buttons
callback!(
    app,
    Output("group1", "value"),
    Input("g1", "n_clicks"),
    State("stage", "value"),
) do clicks, input_1
    return input_1
end

callback!(
    app,
    Output("group2", "value"),
    Input("g2", "n_clicks"),
    State("stage", "value"),
) do clicks, input_1
    return input_1
end

callback!(
    app,
    Output("dummy", "children"),
    Input("RRun", "n_clicks"),
    State("group1", "value"),
    State("group2", "value"),
) do clicks, input_1, input_2
    clicks == 0 && return " "
    CSV.write("matrix_group2_group1.txt",rename(PCM,names(PCM)[1] => "gene")[!,vcat(["gene"], input_1, input_2)], delim='\t')
    n1 = length(input_1)
    n2 = length(input_2)
    @rput n1
    @rput n2
    CSV.write("matrix_Design_final.txt", DataFrame("sample" => vcat(input_1, input_2), "group1" => convert(Vector{UInt8},vcat(trues(n1),falses(n2))), "group2" => convert(Vector{UInt8},vcat(falses(n1),trues(n2)))), delim = '\t')
groupListsInPatients= [
    [ any(x .== input_1) for x in features[!,"SegmentDisplayName"]],
    [ any(x .== input_2) for x in features[!,"SegmentDisplayName"]]
    ]

    cnf1 = DataFrame((newCDC.cellGroup .=> [Vector(row) for row in eachrow( newCDC[!,features[groupListsInPatients[1],"Sample_ID"]])])... , "Group" => "Group1")
    cnf2 = DataFrame((newCDC.cellGroup .=> [Vector(row) for row in eachrow( newCDC[!,features[groupListsInPatients[2],"Sample_ID"]])])... , "Group" => "Group2")
    CSV.write("cell_new_final.txt", vcat(cnf1,cnf2), delim = '\t')

    gf1 = DataFrame((GO.Column1 .=> [Vector(row) for row in eachrow( GO[!,features[groupListsInPatients[1],"Sample_ID"]])])... , "Group" => "Group1")
    gf2 = DataFrame((GO.Column1 .=> [Vector(row) for row in eachrow( GO[!,features[groupListsInPatients[2],"Sample_ID"]])])... , "Group" => "Group2")
    CSV.write("GO_final.txt", vcat(gf1,gf2), delim = '\t')

    R"""
    source("RScripts/de.R")
    """

    return "DE and all"
end

callback!(
    app,
    Output("bubblePlot1", "figure"),
    Input("patientsBubble", "value"),
    Input("geneBubble", "value"),
    Input("group1", "value"),
    Input("group2", "value"),
) do patient, selectedGene, group1,group2
patientRegions= features[!,"SlideName"].==patient
points = features[patientRegions,["SlideName", "SegmentDisplayName", "RoiReportX", "RoiReportY", "states"]]
groupListsInPatients= [
    [ any(x .== group1) for x in points[!,"SegmentDisplayName"]],
    [ any(x .== group2) for x in points[!,"SegmentDisplayName"]]
    ]
#print(any(any.(groupListsInPatients)))
normalizedCounts =Any[ ]

maxCounts = mean(Vector(PCM[PCM[!,"TargetName" ] .== selectedGene,points[!,:].SegmentDisplayName][1,:]))
for group in groupListsInPatients
    if any(group)
        tmp = Vector(PCM[PCM[!,"TargetName" ] .== selectedGene,points[group,:].SegmentDisplayName][1,:])
        #print(tmp)
        push!(normalizedCounts,50 .* tmp./maxCounts)
    end
end
#Plots.scatter(points.ROICoordinateX,points.ROICoordinateY,color=1,label="Tubules")
#Plots.title!(patient)
#Plots.scatter!(points[gloms,:].ROICoordinateX,points[gloms,:].ROICoordinateY,color=2,label="Gloms")
#print(normalizedCounts)

####PENDING#####
#text = structuresDict
    plotData = [    ( x =points[group,:].RoiReportX, y = points[group,:].RoiReportY,  type = "scatter", name = string(i), mode = "markers", marker = (size=normalizedCounts[i], symbol = "circle", ), text = points[group,:].states, customdata = points[group,:].SegmentDisplayName )  for(i,  group) in enumerate( groupListsInPatients) if any(group)]

    return ( data = plotData, layout = ( title = "Gene Expression in Slide", xaxis_title = "x", yaxis_title = "y",),)

end

callback!(
    app,
    Output("bubblePlot2", "figure"),
    Input("patientsBubble", "value"),
    Input("cellBubble", "value"),
    Input("group1", "value"),
    Input("group2", "value"),
) do patient, selectedCell, group1,group2
patientRegions= features[!,"SlideName"].==patient
points = features[patientRegions,["SlideName", "SegmentDisplayName", "RoiReportX", "RoiReportY", "states","Sample_ID"]]
groupListsInPatients= [
    [ any(x .== group1) for x in points[!,"SegmentDisplayName"]],
    [ any(x .== group2) for x in points[!,"SegmentDisplayName"]]
    ]
#print(any(any.(groupListsInPatients)))
normalizedCounts =Any[ ]

maxCounts = maximum(Vector(newCDC[newCDC[!,"cellGroup" ] .== selectedCell,points[!,:].Sample_ID][1,:]))
for group in groupListsInPatients
    if any(group)
        tmp = Vector(newCDC[newCDC[!,"cellGroup" ] .== selectedCell,points[group,:].Sample_ID][1,:])
        #print(tmp)
        push!(normalizedCounts,50 .* tmp./maxCounts)
    end
end

####PENDING#####
#text = structuresDict
    plotData = [    ( x =points[group,:].RoiReportX, y = points[group,:].RoiReportY,  type = "scatter", name = string(i), mode = "markers", marker = (size=normalizedCounts[i], symbol = "circle", ), text = points[group,:].states, customdata = points[group,:].SegmentDisplayName )  for(i,  group) in enumerate( groupListsInPatients) if any(group)]

    return ( data = plotData, layout = ( title = "Cell Fraction in Slide", xaxis_title = "x", yaxis_title = "y",),)

end

callback!(
    app,
    Output("bar1", "figure"),
    Input("patientsBubble", "value"),
    #Input("cellBubble", "value"),
    Input("group1", "value"),
    #Input("group2", "value"),
) do patient,  group1
#patientRegions= features[!,"SlideName"].==patient
points = features[!,["SlideName", "SegmentDisplayName", "RoiReportX", "RoiReportY", "states","barID","Sample_ID"]]
group=  [ any(x .== group1) for x in points[!,"SegmentDisplayName"]]

#print(groupListsInPatients)

    plotData = [    ( x =points[group,:].SegmentDisplayName, y = Vector(newCDC[newCDC[!,"cellGroup" ] .== cell,points[group,:].Sample_ID][1,:]),  type = "bar", name = cell, text = cell, customdata = cell ) for cell in cellGroups  ]

    return ( data = plotData, layout = ( title = "Group 1 Cell Composition",barmode = "stack",
            #xaxis = (title = "ROIs",),
            yaxis = (title = "CD Cell Fraction",),
    )
    )

end

callback!(
    app,
    Output("bar2", "figure"),
    Input("patientsBubble", "value"),
    #Input("cellBubble", "value"),
    Input("group2", "value"),
) do patient,  group1
#patientRegions= features[!,"SlideName"].==patient
points = features[!,["SlideName", "SegmentDisplayName", "RoiReportX", "RoiReportY", "states","barID","Sample_ID"]]
group=  [ any(x .== group1) for x in points[!,"SegmentDisplayName"]]

#print(groupListsInPatients)

    plotData = [    ( x =points[group,:].SegmentDisplayName, y = Vector(newCDC[newCDC[!,"cellGroup" ] .== cell,points[group,:].Sample_ID][1,:]),  type = "bar", name = cell, text = cell, customdata = cell ) for cell in cellGroups  ]

    return ( data = plotData, layout = ( title = "Group 2 Cell Composition",barmode = "stack",
            #xaxis = (title = "ROIs",),
            yaxis = (title = "CD Cell Fraction",),
    showlegend = false),)

end

run_server(app, "0.0.0.0", debug=true)


text:
@testset "Sugar" begin

    struct ScaleByTwo
        f
    end
    (s::ScaleByTwo)(x...) = 2s.f(x...)

    @testset "Create input" begin
        @test issame(inputvertex("input", 5), InputSizeVertex("input", 5))
    end

    @testset "Create immutable" begin
        v = immutablevertex(MatMul(3, 2), inputvertex("in", 3))
        @test nin(v) == [3]
        @test nout(v) == 2
        @test v(1:3) == [22, 28]
        v = immutablevertex(identity, inputvertex("in", 1); traitdecoration = named("v"))
        @test name(v) == "v"
    end

    @testset "Create absorbing" begin
        v = absorbvertex(MatMul(3, 2), inputvertex("in", 3))
        @test nin(v) == [3]
        @test nout(v) == 2
        @test v(1:3) == [22, 28]
        v = absorbvertex(identity, inputvertex("in", 1), traitdecoration = named("v"))
        @test name(v) == "v"
    end

    @testset "Create invariant" begin
        v = invariantvertex(x -> 2 .* x, inputvertex("in", 2))
        @test nin(v) == [2]
        @test nout(v) == 2
        @test v([1 2]) == [2 4]
        v = invariantvertex(identity, inputvertex("in", 1); traitdecoration = named("v"))
        @test name(v) == "v"
    end

    @testset "Create stacking" begin
        v = conc(inputvertex.(("in1", "in2"), (1,2))..., dims=1, traitdecoration = named("v"), outwrap = ScaleByTwo)
        @test nin(v) == [1 ,2]
        @test nout(v) == 3
        @test v(1, [2, 3]) == [2,4,6] # Due to outwrap = ScaleByTwo
        @test name(v) == "v"
        @test typeof(computation(v)) == ScaleByTwo
    end

    @testset "$vfun with name" for vfun in (absorbvertex, invariantvertex, immutablevertex)
        @testset "Normal" begin
            v = vfun("v", identity, inputvertex("in", 3))
            @test name(v) == "v"

            @test_logs((:warn, "Attach name vv to vertex which already has name trait v!"),
                        vfun("vv", identity, inputvertex(in, 3); traitdecoration=named("v")))
        end
        @testset "Do-block" begin
            v = vfun("v", inputvertex("in", 3)) do x
                x
            end
            @test name(v) == "v"

            @test_logs((:warn, "Attach name vv to vertex which already has name trait v!"),
                         vfun("vv", inputvertex("in", 3); traitdecoration=named("v")) do x
                            x
                        end)
        end
    end

    @testset "conc with name" begin
        v = conc("v", inputvertex("in", 3); dims=2)
        @test name(v) == "v"

        @test_logs((:warn, "Attach name vv to vertex which already has name trait v!"),
                    conc("vv", inputvertex("in", 3); dims=2, traitdecoration=named("v")))
    end

    @testset "Create element wise" begin

        conf = traitconf(named("v"))

        @testset "Create elemwise addition" begin
            v = conf >> inputvertex("in1", 2) + inputvertex("in2", 2) + inputvertex("in3" ,2)

            @test nin(v) == [2, 2, 2]
            @test nout(v) == 2
            @test v([1 2], [3 4], [5 6]) == [9 12]
            @test v([1, 2], [3, 4], [5, 6]) == [9, 12]
            @test v([2], [3, 4], [5, 6]) == [10, 12]
            @test name.(inputs(v)) == ["in1", "in2", "in3"]

            @test_throws DimensionMismatch inputvertex("in1", 2) + inputvertex("in2", 3)

            v = inputvertex("in1", 2) + inputvertex("in2", 2)
            @test v([1, 2], [3, 4]) == [4, 6]

            v = outwrapconf(f -> (x...) -> 2f((x...))) >> inputvertex("in1", 2) + inputvertex("in2", 2)
            @test v([1, 2], [3, 4]) == [8, 12]
        end

        @testset "Create elemwise multiplication" begin
            v = conf >> inputvertex("in1", 2) * inputvertex("in2", 2) * inputvertex("in3" ,2)

            @test nin(v) == [2, 2, 2]
            @test nout(v) == 2
            @test v([1 2], [3 4], [5 6]) == [15 48]
            @test v([1, 2], [3, 4], [5, 6]) == [15, 48]
            @test v([2], [3,4], [5,6]) == [30, 48]
            @test name.(inputs(v)) == ["in1", "in2", "in3"]

            @test_throws DimensionMismatch inputvertex("in1", 2) * inputvertex("in2", 3)

            v = inputvertex("in1", 2) * inputvertex("in2", 2)
            @test v([1, 2], [3, 4]) == [3, 8]
        end
        @testset "Create elemwise subtraction" begin
            v = conf >> inputvertex("in1", 2) - inputvertex("in2", 2)

            @test nin(v) == [2, 2]
            @test nout(v) == 2
            @test v([1 2], [3 4]) == [-2 -2]
            @test v([1, 2], [3, 4]) == [-2, -2]
            @test v([2], [3,4]) == [-1, -2]
            @test name.(inputs(v)) == ["in1", "in2"]

            @test_throws DimensionMismatch inputvertex("in1", 2) - inputvertex("in2", 3)

            v = inputvertex("in1", 2) - inputvertex("in2", 2)
            @test v([1, 2], [3, 4]) == [-2, -2]
        end

        @testset "Create unary subtraction" begin
            v = -(conf >> inputvertex("in1", 2))

            @test nin(v) == [nout(v)] == [2]
            @test v([1 2]) == [-1 -2]
            @test v([1, 2]) == [-1, -2]
            @test name.(inputs(v)) == ["in1"]

            v = -inputvertex("in1", 2)
            @test v([1, 2]) == [-1, -2]
        end

        @testset "Create elemwise division" begin
            v = conf >> inputvertex("in1", 2) / inputvertex("in2", 2)

            @test nin(v) == [2, 2]
            @test nout(v) == 2
            @test v([6 8], [2 4]) == [3 2]
            @test v([6, 8], [2, 4]) == [3, 2]
            @test v([12], [3, 4]) == [4, 3]
            @test name.(inputs(v)) == ["in1", "in2"]

            @test_throws DimensionMismatch inputvertex("in1", 2) / inputvertex("in2", 3)

            v = inputvertex("in1", 2) / inputvertex("in2", 2)
            @test v([6, 8], [2, 4]) == [3, 2]
        end

        @testset "Named elementwise" begin
            v = "eladd" >> inputvertex("in1", 2) + inputvertex("in2", 2)

            @test name(v) == "eladd"
            @test nin(v) == [2, 2]
            @test nout(v) == 2

            v = -("unsub" >> inputvertex("in1", 2))
            @test name(v) == "unsub"
            @test nin(v) == [2]
            @test nout(v) == 2
        end

        @testset "Outwrap shortcut" begin
            scale(f) = ScaleByTwo(f)
            v = scale >> inputvertex("in1", 2) + inputvertex("in2", 2)

            @test nin(v) == [2, 2]
            @test nout(v) == 2

            @test v([1, 2], [3, 4]) == [8, 12]
            @test typeof(computation(v)) == ScaleByTwo
        end
    end

    @testset "Trait functions" begin
        @test named("test")(SizeAbsorb()) == NamedTrait("test", SizeAbsorb(),)
        @test validated()(SizeAbsorb()) == AfterΔSizeTrait(validateafterΔsize(), SizeAbsorb())
        @test logged()(SizeAbsorb()) == AfterΔSizeTrait(logafterΔsize(), SizeAbsorb())
    end
end


text:
module TestDistributions

using Test
using MLJBase
using CategoricalArrays
import Distributions:pdf, support
import Distributions
import Random.seed!
seed!(1234)

v = categorical(collect("asqfasqffqsaaaa"), ordered=true)
V = categorical(collect("asqfasqffqsaaaa"))
a, s, q, f = v[1], v[2], v[3], v[4]
A, S, Q, F = V[1], V[2], V[3], V[4]

@testset "classes" begin
    p = a.pool
    @test classes(p) == [a, f, q, s]
    levels!(v, reverse(levels(v)))
    @test classes(p) == reverse([a, f, q, s])
    levels!(v, reverse(levels(v)))

    p = A.pool
    @test classes(p) == [A, F, Q, S]
    levels!(V, reverse(levels(V)))
    @test classes(p) == reverse([A, F, Q, S])
    levels!(V, reverse(levels(V)))
end

@testset "UnivariateFinite constructor" begin
    dic=Dict(s=>0.1, q=> 0.2, f=> 0.7)
    d = UnivariateFinite(dic)
    @test classes(d) == [a, f, q, s]
    @test support(d) == [f, q, s]
    # levels!(v, reverse(levels(v)))
    # @test classes(d) == [s, q, f, a]
    # @test support(d) == [s, q, f]

    @test pdf(d, s) ≈ 0.1
    @test pdf(d, 's') ≈ 0.1
    @test mode(d) == f
    @test Set(unique(rand(d, 100))) == Set(support(d))

    UnivariateFinite(support(d), [0.7, 0.2, 0.1]) ≈ d
    @test_throws(ArgumentError,
                 UnivariateFinite(['f', 'q', 's'],  [0.7, 0.2, 0.1]))
    @test_throws(ArgumentError,
                 UnivariateFinite(Dict('f'=>0.7, 'q'=>0.2, 's'=>0.1)))

    dic=Dict(S=>0.1, Q=> 0.2, F=> 0.7)
    d = UnivariateFinite(dic)
    @test classes(d) == [A, F, Q, S]
    @test support(d) == [F, Q, S]
    # levels!(v, reverse(levels(v)))
    # @test classes(d) == [s, q, f, a]
    # @test support(d) == [s, q, f]

    @test pdf(d, S) ≈ 0.1
    @test pdf(d, 's') ≈ 0.1
    @test mode(d) == F
    @test Set(unique(rand(d, 100))) == Set(support(d))

    UnivariateFinite(support(d), [0.7, 0.2, 0.1]) ≈ d
    @test_throws(ArgumentError,
                 UnivariateFinite(['F', 'Q', 'S'],  [0.7, 0.2, 0.1]))
    @test_throws(ArgumentError,
                 UnivariateFinite(Dict('F'=>0.7, 'Q'=>0.2, 'S'=>0.1)))
end

@testset "Univariate mode" begin
    v = categorical(1:101)
    p = rand(101)
    s = sum(p) - p[42]
    p[42] = 0.5
    p = p/2/s
    p[42] = 0.5
    d = UnivariateFinite(v, p)
    @test mode(d) == 42
end

@testset "UnivariateFinite methods" begin

    y = categorical(["yes", "no", "yes", "yes", "maybe"])
    yes = y[1]
    no = y[2]
    maybe = y[end]
    prob_given_class = Dict(yes=>0.7, no=>0.3)
    d =UnivariateFinite(prob_given_class)
    @test pdf(d, yes) ≈ 0.7
    @test pdf(d, no) ≈ 0.3
    @test pdf(d, maybe) ≈ 0

    v = categorical(collect("abcd"))
    d = UnivariateFinite(v, [0.2, 0.3, 0.1, 0.4])
    sample = rand(d, 10^4)
    freq_given_class = Distributions.countmap(sample)
    pairs  = collect(freq_given_class)
    sort!(pairs, by=pair->pair[2], alg=QuickSort)
    sorted_classes = first.(pairs)
    @test sorted_classes == ['c', 'a', 'b', 'd']

    junk = categorical(['j',])
    j = junk[1]
    v = categorical(['a', 'b', 'a', 'b', 'c', 'b', 'a', 'a', 'f'])
    a = v[1]
    f = v[end]
    # remove f from sample:
    v = v[1 : end - 1]
    d = Distributions.fit(UnivariateFinite, v)
    @test pdf(d, a) ≈ 0.5
    @test pdf(d, 'a') ≈ 0.5
    @test pdf(d, 'b') ≈ 0.375
    @test pdf(d, 'c') ≈ 0.125
    @test pdf(d, 'f') == 0
    @test pdf(d, f) == 0
    @test_throws ArgumentError pdf(d, 'j')

    # with weights:
    w = [2, 3, 2, 3, 5, 3, 2, 2]
    d = Distributions.fit(UnivariateFinite, v, w)
    @test pdf(d, a) ≈ 8/22
    @test pdf(d, 'a') ≈ 8/22
    @test pdf(d, 'b') ≈ 9/22
    @test pdf(d, 'c') ≈ 5/22
    @test pdf(d, 'f') == 0
    @test pdf(d, f) == 0
    @test_throws ArgumentError pdf(d, 'j')

end

@testset "approx for UnivariateFinite" begin
    y = categorical(["yes", "no", "maybe"])
    yes = y[1]
    no = y[2]
    maybe = y[3]
    @test(UnivariateFinite([yes, no, maybe], [0.1, 0.2, 0.7]) ≈
          UnivariateFinite([maybe, yes, no], [0.7, 0.1, 0.2]))
    @test(!(UnivariateFinite([yes, no, maybe], [0.1, 0.2, 0.7]) ≈
          UnivariateFinite([maybe, yes, no], [0.7, 0.2, 0.1])))
end

@testset "UnivariateFinite arithmetic" begin
    v = categorical(collect("abc"))
    a , b, c = v[1], v[2], v[3]
    d1  = UnivariateFinite([a, b], [0.2, 0.8])
    d2  = UnivariateFinite([b, c], [0.3, 0.7])
    dvec = [d1, d2]
    d = average(dvec)
    @test pdf(d, 'a') ≈ 0.1
    @test pdf(d, 'b') ≈ 0.55
    @test pdf(d, 'c') ≈ 0.35
    w = [4, 6]
    d = average(dvec, weights=w)
    @test pdf(d, 'a') ≈ 0.4*0.2
    @test pdf(d, 'b') ≈ 0.4*0.8 + 0.6*0.3
    @test pdf(d, 'c') ≈ 0.6*0.7
end # module

end

true


text:
### A Pluto.jl notebook ###
# v0.14.8

using Markdown
using InteractiveUtils

# This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error).
macro bind(def, element)
    quote
        local el = $(esc(element))
        global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : missing
        el
    end
end

# ╔═╡ 688ea582-aed8-11eb-1da6-5f19687aaac8
using Plots, SpectralVis, PlutoUI, Colors

# ╔═╡ 2f81fae3-ab8f-4be3-b023-1ed12e393592
html"""<style> main {max-width: 950px;}"""

# ╔═╡ 7fe6b71d-f7ee-4cab-b83a-5c198f1be670
gr()

# ╔═╡ 17bbdfe4-b5bd-4e40-88b6-163b10873b5f
env = SPECENV

# ╔═╡ d5909d18-85ad-4caa-9ea5-fce116ecca09
md"Wratten filter number"

# ╔═╡ d96d3c21-a402-42df-ab10-d1948d9337f4
@bind FILT Slider(1:131)

# ╔═╡ 6cddd9cb-530c-4487-a340-cb123823a993
FILT

# ╔═╡ 55e846b9-2123-448d-bbc6-83ee4c5109a7
@bind MB Slider(1:127, default = 1)

# ╔═╡ df067659-c5b7-47f6-a881-1cc202cecbf6
md"Use metameric black from $MB:"

# ╔═╡ 1f39485f-fc8e-4d8a-9178-0bca54f8bbf1
@bind FACT Slider(-5.0:0.1:5.0, default = 0.0)

# ╔═╡ f1d48cce-a989-429b-9ec0-f3406dddf9bc
md"Factor for metameric black: $FACT"

# ╔═╡ a8b2389f-45f0-4080-a00a-5491f36d3c16
begin
	T = 6504 # D65 CCT
	#illum = normalize_spec(D_series_illuminant(T),1.0)
	illum = normalize_spec(blackbody_illuminant(SPECENV,T),1.0)
	#illum = LSpec(collect(390:830),ones(830-389))
	wrat10 = wratten_filter(FILT,1.0)
	wrat20 = wratten_filter(MB, 1.0)

	wc = tristimulus(illum, wrat10)./100
	wb = tristimulus(illum, wrat20)./100

	plot(ylimits=(-0.1,1.21), size = (900,500),legend=:outertopright, title = "Filter and metameric filter", xaxis = "wavelength [nm]", yaxis = "transmittance")

	# fundamental metamer colorization:
	funda = XYZ(wc[1],wc[2],wc[3])
	# alternative fund. met. colorization:
	altblack = XYZ(wb[1],wb[2],wb[3])

	plot!(wrat10.λ,wrat10.t, color = funda, linewidth = 4.0, label = "wratten filter")

	# fundamental metamer of filter 1
	meta = fundamental_metamer(illum, wrat10)

	# original metameric black of filter 1
	bla = metameric_black(illum, wrat10)
	#alternative metameric black of filter 2
	mbla = metameric_black(illum,wrat20)

	#plot!(meta.λ,meta.l, color = funda, linewidth = 2.0, style = :dash, label = "fund. met.")
	#plot!(bla.λ,bla.l, color = :black, label = "metameric black")
	#plot!(mbla.λ,mbla.l, color = altblack, linewidth = 2, label = "altern. metameric black")
	plot!(meta.λ,wrat10.t.+mbla.l.*FACT, linewidth = 4.0, color = altblack ,style = :dash, label = "wratten filt. + black * $(round(FACT, digits=1))")
end

# ╔═╡ 465b2e9b-d551-4413-a803-7e5b8358b13d
XYZ(wc[1],wc[2],wc[3])

# ╔═╡ d3275197-f1bb-4427-98b1-c2fd9ccaa267
illum * wrat20 * wrat20

# ╔═╡ Cell order:
# ╠═2f81fae3-ab8f-4be3-b023-1ed12e393592
# ╠═688ea582-aed8-11eb-1da6-5f19687aaac8
# ╠═7fe6b71d-f7ee-4cab-b83a-5c198f1be670
# ╠═17bbdfe4-b5bd-4e40-88b6-163b10873b5f
# ╟─d5909d18-85ad-4caa-9ea5-fce116ecca09
# ╟─6cddd9cb-530c-4487-a340-cb123823a993
# ╟─d96d3c21-a402-42df-ab10-d1948d9337f4
# ╟─df067659-c5b7-47f6-a881-1cc202cecbf6
# ╟─55e846b9-2123-448d-bbc6-83ee4c5109a7
# ╟─f1d48cce-a989-429b-9ec0-f3406dddf9bc
# ╟─1f39485f-fc8e-4d8a-9178-0bca54f8bbf1
# ╟─465b2e9b-d551-4413-a803-7e5b8358b13d
# ╠═a8b2389f-45f0-4080-a00a-5491f36d3c16
# ╠═d3275197-f1bb-4427-98b1-c2fd9ccaa267


text:
module SimpleHMM

# exposed interface
export
HMM, Gaussian_HMM, emit, baum_welch, viterbi, log_likelihood,
get_param, get_config, init_random_HMM,
HMM_from_json, HMM_to_json

# include the io utilities
# n.b. Base.jl is alreaded included by IO.jl
include("IO.jl")

end    # end of module


text:
module ApproxBayes

using Distributions
using ProgressMeter
using StatsBase
using RecipesBase
using Printf
using Distances
using DelimitedFiles
using Random
using Statistics
using Base.Threads

import Base.show

export
  # types
  ABCtype,
  Prior,
  Particle,
  abctype,
  ParticleRejection,
  ABCRejection,
  ABCSMC,
  ABCRejectionModel,
  ABCSMCModel,
  Kernel,
  gaussiankernel,
  uniformkernel,

  #functions
  ksdist,
  runabc,
  writeoutput

### source files
include("kernels.jl")
include("types.jl")
include("util.jl")
include("ABCalgorithm.jl")
include("sampling.jl")
include("calculateweights.jl")
include("plots.jl")

end


text:
# Load distributed base_script
include(joinpath(dirname(@__DIR__), "src", "distributed_script.jl"))

@info "Using $(Distributed.nworkers()) workers"

if isempty(ARGS)
    compositions_benchmark(; clear_results=false)
elseif (ARGS[1] == "true")
    compositions_benchmark(; clear_results=true)
end


text:
# Bubble Sort is the simplest sorting algorithm that works by
# repeatedly swapping the adjacent elements if they are in wrong order.

function swap!{T}(x::AbstractArray{T}, a::T, b::T)

  tmp = x[a]
  x[a] = x[b]
  x[b] = tmp
  return x

end

function bubblesort!{T}(x::AbstractArray{T})

  for i in 2:length(x)
    for j in 1:length(x)-1
      if x[j] > x[j+1]
        swap!(x, j, j+1)
      end
    end
  end

  return x
end

x = [10,2,5,1,3,0]

println(bubblesort!(x))

max_stars_repo_name: gggrafff/Algorithms

max_issues_repo_name: gggrafff/Algorithms

max_forks_repo_name: gggrafff/Algorithms


text:
using CircuitscapeUI
using Circuitscape
using Distributed
w = run_ui()
oldpwd = pwd()
cd(CircuitscapeUI.TESTPATH)
Circuitscape.runtests()
cd(oldpwd)


text:
module CorpusLoaders
using DataDeps
using WordTokenizers
using MultiResolutionIterators
using InternedStrings
using Glob
using StringEncodings
using CSV

export Document, TaggedWord, SenseAnnotatedWord, PosTaggedWord
export title, sensekey, word, named_entity, part_of_speech
export load

export WikiCorpus, SemCor, Senseval3, CoNLL, IMDB, Twitter, StanfordSentimentTreebank, WikiGold, CoNLL2000

include("types.jl")
include("apply_subparsers.jl")
include("WikiCorpus.jl")
include("SemCor.jl")
include("SemEval2007Task7.jl")
include("Senseval3.jl")
include("CoNLL.jl")
include("IMDB.jl")
include("Twitter.jl")
include("StanfordSentimentTreebank.jl")
include("WikiGold.jl")
include("CoNLL2000.jl")

function __init__()
    init_datadeps(WikiCorpus)
    init_datadeps(SemCor)
    init_datadeps(Senseval3)
    init_datadeps(CoNLL)
    init_datadeps(IMDB)
    init_datadeps(Twitter)
    init_datadeps(StanfordSentimentTreebank)
    init_datadeps(WikiGold)
    init_datadeps(CoNLL2000)
    init_datadeps_SemEval2007Task7()
end

end