text:
import XLSX
using Base.Test, Missings

data_directory = joinpath(dirname(@__FILE__), "..", "data")

ef_blank_ptbr_1904 = XLSX.readxlsx(joinpath(data_directory, "blank_ptbr_1904.xlsx"))
ef_Book1 = XLSX.readxlsx(joinpath(data_directory, "Book1.xlsx"))
ef_Book_1904 = XLSX.readxlsx(joinpath(data_directory, "Book_1904.xlsx"))
ef_book_1904_ptbr = XLSX.readxlsx(joinpath(data_directory, "book_1904_ptbr.xlsx"))
ef_book_sparse = XLSX.readxlsx(joinpath(data_directory, "book_sparse.xlsx"))
ef_book_sparse_2 = XLSX.readxlsx(joinpath(data_directory, "book_sparse_2.xlsx"))

@test ef_Book1.filepath == joinpath(data_directory, "Book1.xlsx")
@test length(keys(ef_Book1.data)) > 0

@test ef_Book_1904.filepath == joinpath(data_directory, "Book_1904.xlsx")
@test length(keys(ef_Book_1904.data)) > 0

@test !XLSX.isdate1904(ef_Book1)
@test XLSX.isdate1904(ef_Book_1904)
@test XLSX.isdate1904(ef_blank_ptbr_1904)
@test XLSX.isdate1904(ef_book_1904_ptbr)

@test XLSX.sheetnames(ef_Book1) == [ "Sheet1", "Sheet2" ]
@test XLSX.sheetcount(ef_Book1) == 2
@test ef_Book1["Sheet1"].name == "Sheet1"
@test ef_Book1[1].name == "Sheet1"

@test XLSX.sst_unformatted_string(ef_Book1.workbook, 0) == "B2" # index is 0-based
@test XLSX.sst_unformatted_string(ef_Book1, 0) == "B2"
@test XLSX.sst_unformatted_string(ef_Book1, "0") == "B2"

@test_throws ErrorException XLSX.get_relationship_target_by_id(ef_Book1.workbook, "indalid_id")
@test_throws ErrorException XLSX.get_relationship_target_by_type(ef_Book1.workbook, "indalid_type")
@test !XLSX.has_relationship_by_type(ef_Book1.workbook, "invalid_type")

# Cell names
@test !XLSX.is_valid_cellname("A0")
@test XLSX.is_valid_cellname("A1")
@test !XLSX.is_valid_cellname("A")
@test !XLSX.is_valid_cellname("1")
@test XLSX.is_valid_cellname("XFD1048576")
@test !XLSX.is_valid_cellname("XFD1048577")
@test XLSX.is_valid_cellname("XFD1")
@test !XLSX.is_valid_cellname("ZFD1")
@test XLSX.is_valid_column_name("A")
@test XLSX.is_valid_column_name("AZ")
@test XLSX.is_valid_column_name("AAZ")
@test !XLSX.is_valid_column_name("AAAZ")
@test !XLSX.is_valid_column_name(":")
@test !XLSX.is_valid_column_name("É")

@test XLSX.is_valid_sheet_cellname("Sheet1!A2")
@test !XLSX.is_valid_sheet_cellname("Sheet1!A2:B3")
@test !XLSX.is_valid_sheet_cellname("Sheet1!A0")
@test !XLSX.is_valid_sheet_cellname("A1")
@test !XLSX.is_valid_sheet_cellname("Sheet1!")
@test !XLSX.is_valid_sheet_cellname("Sheet1")
@test !XLSX.is_valid_sheet_cellname("Sheet1!A")
@test !XLSX.is_valid_sheet_cellname("Sheet1!1")

@test XLSX.is_valid_sheet_cellrange("Sheet1!A1:B4")
@test !XLSX.is_valid_sheet_cellrange("Sheet1!:B4")
@test !XLSX.is_valid_sheet_cellrange("Sheet1!A1:")
@test !XLSX.is_valid_sheet_cellrange("Sheet1!:")
@test !XLSX.is_valid_sheet_cellrange("A1:B4")
@test !XLSX.is_valid_sheet_cellrange("Sheet1!")
@test !XLSX.is_valid_sheet_cellrange("Sheet1")
@test !XLSX.is_valid_sheet_cellrange("mysheet!A1")
@test XLSX.is_valid_sheet_cellrange("mysheet!A1:A4")

@test XLSX.is_valid_sheet_column_range("Sheet1!A:B")
@test XLSX.is_valid_sheet_column_range("Sheet1!AB:BC")
@test !XLSX.is_valid_sheet_column_range("A:B")
@test !XLSX.is_valid_sheet_column_range("Sheet1!")
@test !XLSX.is_valid_sheet_column_range("Sheet1")

cn = XLSX.CellRef("A1")
@test string(cn) == "A1"
@test XLSX.column_name(cn) == "A"
@test XLSX.row_number(cn) == 1
@test XLSX.column_number(cn) == 1

cn = XLSX.CellRef("AB1")
@test string(cn) == "AB1"
@test XLSX.column_name(cn) == "AB"
@test XLSX.row_number(cn) == 1
@test XLSX.column_number(cn) == 28

cn = XLSX.CellRef("AMI1")
@test string(cn) == "AMI1"
@test XLSX.column_name(cn) == "AMI"
@test XLSX.row_number(cn) == 1
@test XLSX.column_number(cn) == 1023

cn = XLSX.CellRef("XFD1048576")
@test string(cn) == "XFD1048576"
@test XLSX.column_name(cn) == "XFD"
@test XLSX.row_number(cn) == 1048576
@test XLSX.column_number(cn) == 16384

v_column_numbers = [1
,    15
,    22
,    23
,    24
,    25
,    26
,    27
,    28
,    29
,    30
,    38
,    39
,    40
,    41
,    42
,    43
,    44
,    45
,    46
,    47
,    48
,    49
,    50
,    51
,    52
,    53
,    54
,    55
,    56
,    57
,    58
,    59
,    60
,    61
,    74
,    75
,    76
,    77
,    78
,    79
,    80
,    81
,    82
,    83
,    84
,    85
,    86
,   284
,   285
,   286
,   287
,   288
,   289
,   296
,   297
,   299
,   300
,   301
,   700
,   701
,   702
,   703
,   704
,   705
,   706
,   727
,   728
,   729
,   730
,   731
,  1008
,  1013
,  1014
,  1015
,  1016
,  1017
,  1018
,  1023
,  1024
,  1376
,  1377
,  1378
,  1379
,  1380
,  1381
,  3379
,  3380
,  3381
,  3382
,  3383
,  3403
,  3404
,  3405
,  3406
,  3407
, 16250
, 16251
, 16354
, 16355
, 16384]

v_column_names = [  "A"
, "O"
, "V"
, "W"
, "X"
, "Y"
, "Z"
, "AA"
, "AB"
, "AC"
, "AD"
, "AL"
, "AM"
, "AN"
, "AO"
, "AP"
, "AQ"
, "AR"
, "AS"
, "AT"
, "AU"
, "AV"
, "AW"
, "AX"
, "AY"
, "AZ"
, "BA"
, "BB"
, "BC"
, "BD"
, "BE"
, "BF"
, "BG"
, "BH"
, "BI"
, "BV"
, "BW"
, "BX"
, "BY"
, "BZ"
, "CA"
, "CB"
, "CC"
, "CD"
, "CE"
, "CF"
, "CG"
, "CH"
, "JX"
, "JY"
, "JZ"
, "KA"
, "KB"
, "KC"
, "KJ"
, "KK"
, "KM"
, "KN"
, "KO"
, "ZX"
, "ZY"
, "ZZ"
, "AAA"
, "AAB"
, "AAC"
, "AAD"
, "AAY"
, "AAZ"
, "ABA"
, "ABB"
, "ABC"
, "ALT"
, "ALY"
, "ALZ"
, "AMA"
, "AMB"
, "AMC"
, "AMD"
, "AMI"
, "AMJ"
, "AZX"
, "AZY"
, "AZZ"
, "BAA"
, "BAB"
, "BAC"
, "DYY"
, "DYZ"
, "DZA"
, "DZB"
, "DZC"
, "DZW"
, "DZX"
, "DZY"
, "DZZ"
, "EAA"
, "WZZ"
, "XAA"
, "XDZ"
, "XEA"
, "XFD"]

@assert length(v_column_names) == length(v_column_numbers) "Test script is wrong."

for i in 1:length(v_column_names)
    @test XLSX.encode_column_number(v_column_numbers[i]) == v_column_names[i]
    @test XLSX.decode_column_number(v_column_names[i]) == v_column_numbers[i]
end

@test XLSX.CellRef(12, 2).name == "B12"

cr = XLSX.range"A1:C4"
@test string(cr) == "A1:C4"
@test XLSX.row_number(cr.start) == 1
@test XLSX.column_number(cr.start) == 1
@test XLSX.row_number(cr.stop) == 4
@test XLSX.column_number(cr.stop) == 3
@test size(cr) == (4, 3)

cr = XLSX.range"B2:C8"
@test XLSX.ref"B2" ∈ cr
@test XLSX.ref"B3" ∈ cr
@test XLSX.ref"C2" ∈ cr
@test XLSX.ref"C3" ∈ cr
@test XLSX.ref"C8" ∈ cr
@test XLSX.ref"A1" ∉ cr
@test XLSX.ref"C9" ∉ cr
@test XLSX.ref"D4" ∉ cr
@test size(cr) == (7, 2)

fullrng = XLSX.range"B2:E5"
@test fullrng ⊆ fullrng
@test XLSX.range"B3:D4" ⊆ fullrng
@test !issubset(XLSX.range"A1:E5", fullrng)

@test XLSX.is_valid_cellrange("B2:C8")
@test !XLSX.is_valid_cellrange("A:B")
@test_throws AssertionError XLSX.CellRange("Z10:A1")
@test_throws AssertionError XLSX.CellRange("Z1:A1")

# hashing and equality
@test XLSX.CellRef("AMI1") == XLSX.CellRef("AMI1")
@test hash(XLSX.CellRef("AMI1")) == hash(XLSX.CellRef("AMI1"))
@test XLSX.CellRange("A1:C4") == XLSX.CellRange("A1:C4")
@test hash(XLSX.CellRange("A1:C4")) == hash(XLSX.CellRange("A1:C4"))

# worksheet for book1
@test XLSX.get_dimension(ef_Book1["Sheet1"]) == XLSX.range"B2:C8"
@test XLSX.isdate1904(ef_Book1["Sheet1"]) == false

# relative cell position
rng = XLSX.range"B2:D4"
@test XLSX.relative_cell_position(XLSX.ref"C3", rng) == (2, 2)
@test XLSX.relative_cell_position(XLSX.ref"B2", rng) == (1, 1)
@test XLSX.relative_cell_position(XLSX.ref"C4", rng) == (3, 2)
@test XLSX.relative_cell_position(XLSX.ref"D4", rng) == (3, 3)
@test XLSX.relative_cell_position(XLSX.EmptyCell(XLSX.ref"D4"), rng) == (3, 3)

# SheetCellRef, SheetCellRange, SheetColumnRange
ref = XLSX.SheetCellRef("Sheet1!A2")
@test string(ref) == "Sheet1!A2"
@test ref.sheet == "Sheet1"
@test ref.cellref == XLSX.CellRef("A2")
@test XLSX.SheetCellRef("Sheet1!A2") == XLSX.SheetCellRef("Sheet1!A2")
@test hash(XLSX.SheetCellRef("Sheet1!A2")) == hash(XLSX.SheetCellRef("Sheet1!A2"))

ref = XLSX.SheetCellRange("Sheet1!A1:B4")
@test ref.sheet == "Sheet1"
@test ref.rng == XLSX.CellRange("A1:B4")
@test_throws AssertionError XLSX.SheetCellRange("Sheet1!B4:A1")
@test XLSX.SheetCellRange("Sheet1!A1:B4") == XLSX.SheetCellRange("Sheet1!A1:B4")
@test hash(XLSX.SheetCellRange("Sheet1!A1:B4")) == hash(XLSX.SheetCellRange("Sheet1!A1:B4"))

ref = XLSX.SheetColumnRange("Sheet1!A:B")
@test string(ref) == "Sheet1!A:B"
@test ref.sheet == "Sheet1"
@test ref.colrng == XLSX.ColumnRange("A:B")
@test XLSX.SheetColumnRange("Sheet1!A:B") == XLSX.SheetColumnRange("Sheet1!A:B")
@test hash(XLSX.SheetColumnRange("Sheet1!A:B")) == hash(XLSX.SheetColumnRange("Sheet1!A:B"))

# getindex
f = XLSX.readxlsx(joinpath(data_directory, "Book1.xlsx"))
sheet1 = f["Sheet1"]
@test sheet1["B2"] == "B2"
@test isapprox(sheet1["C3"], 21.2)
@test sheet1["B5"] == Date(2018, 3, 21)
@test sheet1["B8"] == "palavra1"

@test XLSX.getcell(sheet1, "B2") == XLSX.Cell(XLSX.CellRef("B2"), "s", "", "0", "")
XLSX.getcellrange(sheet1, "B2:C3")
XLSX.getcellrange(f, "Sheet1!B2:C3")
@test_throws ErrorException XLSX.getcellrange(f, "B2:C3")

# a cell can be put in a dict
c = XLSX.getcell(sheet1, "B2")
dct = Dict("a" => c)
@test dct["a"] == XLSX.Cell(XLSX.CellRef("B2"), "s", "", "0", "")

# equality and hash
@test XLSX.Cell(XLSX.CellRef("B2"), "s", "", "0", "") == XLSX.Cell(XLSX.CellRef("B2"), "s", "", "0", "")
@test hash(dct["a"]) == hash(XLSX.Cell(XLSX.CellRef("B2"), "s", "", "0", ""))

sheet2 = f[2]
sheet2_data = [ 1 2 3 ; 4 5 6 ; 7 8 9 ]
@test sheet2_data == sheet2["A1:C3"]
@test sheet2_data == sheet2[:]
@test sheet2[:] == XLSX.getdata(sheet2)

# Time and DateTime
@test XLSX.excel_value_to_time(0.82291666666666663) == Dates.Time(Dates.Hour(19), Dates.Minute(45))
@test XLSX.time_to_excel_value( XLSX.excel_value_to_time(0.2) ) == 0.2
@test XLSX.excel_value_to_datetime(43206.805447106482, false) == Date(2018, 4, 16) + Dates.Time(Dates.Hour(19), Dates.Minute(19), Dates.Second(51))
@test XLSX.excel_value_to_datetime(XLSX.datetime_to_excel_value(Date(2018, 4, 16) + Dates.Time(Dates.Hour(19), Dates.Minute(19), Dates.Second(51)),false ), false ) == Date(2018, 4, 16) + Dates.Time(Dates.Hour(19), Dates.Minute(19), Dates.Second(51))

dt = Date(2018,4,1)
@test XLSX.excel_value_to_date(XLSX.date_to_excel_value( dt, false), false) == dt
@test XLSX.excel_value_to_date(XLSX.date_to_excel_value( dt, true), true) == dt

# General number formats
f = XLSX.openxlsx(joinpath(data_directory, "general.xlsx"))
sheet = f["general"]
@test sheet["A1"] == "text"
@test sheet["B1"] == "regular text"
@test sheet["A2"] == "integer"
@test sheet["B2"] == 102
@test sheet["A3"] == "float"
@test isapprox(sheet["B3"], 102.2)
@test sheet["A4"] == "date"
@test sheet["B4"] == Date(1983, 4, 16)
@test sheet["A5"] == "hour"
@test sheet["B5"] == Dates.Time(Dates.Hour(19), Dates.Minute(45))
@test sheet["A6"] == "datetime"
@test sheet["B6"] == Date(2018, 4, 16) + Dates.Time(Dates.Hour(19), Dates.Minute(19), Dates.Second(51))
@test f["general!B7"] == -220.0
@test f["general!B8"] == -2000
@test f["general!B9"] == 100000000000000
@test f["general!B10"] == -100000000000000

# Defined Names
@test XLSX.is_defined_name_value_a_reference(XLSX.SheetCellRef("Sheet1!A1"))
@test XLSX.is_defined_name_value_a_reference(XLSX.SheetCellRange("Sheet1!A1:B2"))
@test !XLSX.is_defined_name_value_a_reference(1)
@test !XLSX.is_defined_name_value_a_reference(1.2)
@test !XLSX.is_defined_name_value_a_reference("Hey")
@test !XLSX.is_defined_name_value_a_reference(Missings.missing)

@test f["SINGLE_CELL"] == "single cell A2"
@test f["RANGE_B4C5"] == Any["range B4:C5" "range B4:C5"; "range B4:C5" "range B4:C5"]
@test f["CONST_DATE"] == 43383
@test isapprox(f["CONST_FLOAT"], 10.2)
@test f["CONST_INT"] == 100
@test f["LOCAL_INT"] == 2000
@test f["named_ranges_2"]["LOCAL_INT"] == 2000
@test f["named_ranges"]["LOCAL_INT"] == 1000
@test f["named_ranges"]["LOCAL_NAME"] == "Hey You"
@test f["named_ranges_2"]["LOCAL_NAME"] == "out there in the cold"
@test f["named_ranges"]["SINGLE_CELL"] == "single cell A2"

@test_throws ErrorException f["header_error"]["LOCAL_REF"]
@test f["named_ranges"]["LOCAL_REF"][1] == 10
@test f["named_ranges"]["LOCAL_REF"][2] == 20
@test f["named_ranges_2"]["LOCAL_REF"][1] == "local"
@test f["named_ranges_2"]["LOCAL_REF"][2] == "reference"

close(f)

@test XLSX.readdata(joinpath(data_directory, "general.xlsx"), "SINGLE_CELL") == "single cell A2"
@test XLSX.readdata(joinpath(data_directory, "general.xlsx"), "RANGE_B4C5") == Any["range B4:C5" "range B4:C5"; "range B4:C5" "range B4:C5"]

# Book1.xlsx
f = XLSX.readxlsx(joinpath(data_directory, "Book1.xlsx"))
sheet = f["Sheet1"]
@test ismissing(sheet["A1"])
@test sheet["B2"] == "B2"
@test sheet["C2"] == "C2"
@test isapprox(sheet["B3"], 10.5)
@test isapprox(sheet["C3"], 21.2)
@test sheet["B4"] == Date(2018, 3, 21)
@test sheet["C4"] == Date(2018, 3, 22)
@test sheet["B5"] == Date(2018, 3, 21)
@test sheet["C5"] == Date(2018, 3, 22)
@test sheet["B6"] == true
@test sheet["C6"] == false
@test sheet["B7"] == 1
@test sheet["C7"] == 2
@test sheet["B8"] == "palavra1"
@test sheet["C8"] == "palavra2"

@test XLSX.getdata(f, XLSX.SheetCellRef("Sheet1!B2")) == "B2"
@test XLSX.getdata(f, XLSX.SheetCellRange("Sheet1!B2:B3"))[1] == "B2"
@test XLSX.getdata(f, XLSX.SheetCellRange("Sheet1!B2:B3"))[2] == 10.5
@test f["Sheet1!B2"] == "B2"
@test f["Sheet1!B2:B3"][1] == "B2"
@test f["Sheet1!B2:B3"][2] == 10.5
@test string(XLSX.SheetCellRange("Sheet1!B2:B3")) == "Sheet1!B2:B3"

# book_1904_ptbr.xlsx
f = XLSX.readxlsx(joinpath(data_directory, "book_1904_ptbr.xlsx"))

@test f["Plan1"][:] == Any[ "Coluna A" "Coluna B" "Coluna C" "Coluna D";
                            10 10.5 Date(2018, 3, 22) "linha 2";
                            20 20.5 Date(2017, 12, 31) "linha 3";
                            30 30.5 Date(2018, 1, 1) "linha 4" ]

@test f["Plan2"]["A1"] == "Merge de A1:D1"
@test ismissing(f["Plan2"]["B1"])
@test f["Plan2"]["C2"] == "C2"
@test f["Plan2"]["D3"] == "D3"

# numbers.xlsx
f = XLSX.readxlsx(joinpath(data_directory, "numbers.xlsx"))
floats = f["float"][:]
for n in floats
    if !ismissing(n)
        @test isa(n, Float64)
    end
end

ints = f["int"][:]
for n in ints
    if !ismissing(n)
        @test isa(n, Int)
    end
end

error_sheet = f["error"]
@test error_sheet["A1"] == "errors"
@test !XLSX.iserror(XLSX.getcell(error_sheet, "A1"))
@test XLSX.iserror(XLSX.getcell(error_sheet, "A2"))
@test XLSX.iserror(XLSX.getcell(f, "error!A2"))
@test ismissing(error_sheet["A2"])
@test ismissing(error_sheet["A3"])
@test ismissing(error_sheet["A4"])
emptycell = XLSX.getcell(error_sheet, "B1")
@test !XLSX.iserror(emptycell)
@test ismissing(XLSX.getdata(error_sheet, emptycell))
@test XLSX.row_number(emptycell) == 1
@test XLSX.column_number(emptycell) == 2

# Column Range

cr = XLSX.ColumnRange("B:D")
@test string(cr) == "B:D"
@test cr.start == 2
@test cr.stop == 4
@test length(cr) == 3
@test_throws AssertionError XLSX.ColumnRange("B1:D3")
@test_throws AssertionError XLSX.ColumnRange("D:A")
@test collect(cr) == [ "B", "C", "D" ]
@test XLSX.ColumnRange("B:D") == XLSX.ColumnRange("B:D")
@test hash(XLSX.ColumnRange("B:D")) == hash(XLSX.ColumnRange("B:D"))

# CellRange iterator
rng = XLSX.CellRange("A2:C4")
@test collect(rng) == [ XLSX.CellRef("A2"), XLSX.CellRef("B2"), XLSX.CellRef("C2"), XLSX.CellRef("A3"), XLSX.CellRef("B3"), XLSX.CellRef("C3"), XLSX.CellRef("A4"), XLSX.CellRef("B4"), XLSX.CellRef("C4") ]

# Table

f = XLSX.readxlsx(joinpath(data_directory, "book_sparse.xlsx"))
s = f["Sheet1"]

report = Vector{String}()
for r in XLSX.eachrow(s)
    if !isempty(r)
        push!(report, string(XLSX.row_number(r), " - ", XLSX.column_bounds(r)))

        if XLSX.row_number(r) == 2
            @test XLSX.last_column_index(r, 2) == 2
        elseif XLSX.row_number(r) == 3
            @test XLSX.last_column_index(r, 3) == 4
        elseif XLSX.row_number(r) == 6
            @test XLSX.last_column_index(r, 1) == 4
            @test XLSX.last_column_index(r, 2) == 4
            @test XLSX.last_column_index(r, 3) == 4
            @test XLSX.last_column_index(r, 4) == 4
            @test_throws AssertionError XLSX.last_column_index(r, 5)
        elseif XLSX.row_number(r) == 9
            @test XLSX.last_column_index(r, 2) == 3
            @test XLSX.last_column_index(r, 3) == 3
            @test XLSX.last_column_index(r, 5) == 5
        end
    end
end
@test report == [ "2 - (2, 2)", "3 - (3, 4)", "6 - (1, 4)", "9 - (2, 5)"]

f = XLSX.openxlsx(joinpath(data_directory, "general.xlsx"))
f["general"][:];
close(f)

f = XLSX.readxlsx(joinpath(data_directory, "general.xlsx"))
s = f["table"]
s[:];
data, col_names = XLSX.gettable(s)
@test col_names == [ Symbol("Column B"), Symbol("Column C"), Symbol("Column D"), Symbol("Column E"), Symbol("Column F"), Symbol("Column G")]

test_data = Vector{Any}(6)
test_data[1] = collect(1:8)
test_data[2] = [ "Str1", missing, "Str1", "Str1", "Str2", "Str2", "Str2", "Str2" ]
test_data[3] = [ Date(2018, 4, 21) + Dates.Day(i) for i in 0:7 ]
test_data[4] = [ missing, missing, missing, missing, missing, "a", "b", missing ]
test_data[5] = [ 0.2001132319, 0.2793987377, 0.0950591677, 0.0744023067, 0.8242278091, 0.6205883578, 0.9174151018, 0.6749604883 ]
test_data[6] = [ missing for i in 1:8 ]

function check_test_data(data::Vector{Any}, test_data::Vector{Any})

    @test length(data) == length(test_data)

    function size_of_data(d::Vector{Any})
        isempty(d) && return (0, 0)
        return length(d[1]), length(d)
    end

    rows, cols = size_of_data(test_data)

    for col in 1:cols
        @test length(data[col]) == length(test_data[col])
    end

    for row in 1:rows, col in 1:cols
        test_value = test_data[col][row]
        value = data[col][row]
        if ismissing(test_value)
            @test ismissing(value)
        else
            if isa(test_value, Float64)
                @test isapprox(value, test_value)
            else
                @test value == test_value
            end
        end
    end

    nothing
end

check_test_data(data, test_data)

@test XLSX.infer_eltype(data[1]) == Int
@test XLSX.infer_eltype(data[2]) == Union{Missing, String}
@test XLSX.infer_eltype(data[3]) == Date
@test XLSX.infer_eltype(data[4]) == Union{Missing, String}
@test XLSX.infer_eltype(data[5]) == Float64
@test XLSX.infer_eltype(data[6]) == Any
@test XLSX.infer_eltype([1, "1", 10.2]) == Any
@test XLSX.infer_eltype(Vector{Int}()) == Int

data_inferred, col_names = XLSX.gettable(s, infer_eltypes=true)
@test eltype(data_inferred[1]) == Int
@test eltype(data_inferred[2]) == Union{Missing, String}
@test eltype(data_inferred[3]) == Date
@test eltype(data_inferred[4]) == Union{Missing, String}
@test eltype(data_inferred[5]) == Float64
@test eltype(data_inferred[6]) == Any

function stop_function(r::XLSX.TableRow)
    v = r[Symbol("Column C")]
    return !Missings.ismissing(v) && v == "Str2"
end

function never_reaches_stop(r::XLSX.TableRow)
    v = r[Symbol("Column C")]
    return !Missings.ismissing(v) && v == "never was found"
end

data, col_names = XLSX.gettable(s, stop_in_row_function=never_reaches_stop)
check_test_data(data, test_data)

data, col_names = XLSX.gettable(s, stop_in_row_function=stop_function)
@test col_names == [ Symbol("Column B"), Symbol("Column C"), Symbol("Column D"), Symbol("Column E"), Symbol("Column F"), Symbol("Column G")]

test_data = Vector{Any}(6)
test_data[1] = collect(1:4)
test_data[2] = [ "Str1", missing, "Str1", "Str1" ]
test_data[3] = [ Date(2018, 4, 21) + Dates.Day(i) for i in 0:3 ]
test_data[4] = [ missing, missing, missing, missing ]
test_data[5] = [ 0.2001132319, 0.2793987377, 0.0950591677, 0.0744023067 ]
test_data[6] = [ missing for i in 1:4 ]

check_test_data(data, test_data)

data, col_names = XLSX.gettable(s, stop_in_empty_row=false)
@test col_names == [ Symbol("Column B"), Symbol("Column C"), Symbol("Column D"), Symbol("Column E"), Symbol("Column F"), Symbol("Column G")]

test_data = Vector{Any}(6)
test_data[1] = [1, 2, 3, 4, 5, 6, 7, 8, "trash" ]
test_data[2] = [ "Str1", missing, "Str1", "Str1", "Str2", "Str2", "Str2", "Str2", missing ]
test_data[3] = Any[ Date(2018, 4, 21) + Dates.Day(i) for i in 0:7 ]
push!(test_data[3], "trash")
test_data[4] = [ missing, missing, missing, missing, missing, "a", "b", missing, missing ]
test_data[5] = [ 0.2001132319, 0.2793987377, 0.0950591677, 0.0744023067, 0.8242278091, 0.6205883578, 0.9174151018, 0.6749604883, "trash" ]
test_data[6] = Any[ missing for i in 1:8 ]
push!(test_data[6], "trash")

check_test_data(data, test_data)

# queries based on ColumnRange
x = XLSX.getcellrange(s, XLSX.ColumnRange("B:D"))
@test size(x) == (11, 3)
y = XLSX.getcellrange(s, "B:D")
@test size(y) == (11, 3)
@test x == y
@test_throws AssertionError XLSX.getcellrange(s, "D:B")
@test_throws ErrorException XLSX.getcellrange(s, "A:C1")

d = XLSX.getdata(s, "B:D")
@test size(d) == (11, 3)
@test_throws ErrorException XLSX.getdata(s, "A:C1")
@test d[1, 1] == "Column B"
@test d[1, 2] == "Column C"
@test d[1, 3] == "Column D"
@test d[9, 1] == 8
@test d[9, 2] == "Str2"
@test d[9, 3] == Date(2018, 4, 28)
@test d[10, 1] == "trash"
@test ismissing(d[10, 2])
@test d[10, 3] == "trash"
@test ismissing(d[11, 1])
@test ismissing(d[11, 2])
@test ismissing(d[11, 3])

d2 = f["table!B:D"]
@test size(d) == size(d2)
@test all(d .=== d2)

@test_throws ErrorException f["table!B1:D"]
@test_throws AssertionError f["table!D:B"]

s = f["table2"]
test_data = Vector{Any}(3)
test_data[1] = [ "A1", "A2", "A3", missing ]
test_data[2] = [ "B1", "B2", missing, "B4"]
test_data[3] = [ missing, missing, missing, missing ]

data, col_names = XLSX.gettable(s)

@test col_names == [:HA, :HB, :HC]
check_test_data(data, test_data)

for (ri, rowdata) in enumerate(XLSX.eachtablerow(s))
    if ismissing(test_data[1][ri])
        @test ismissing(rowdata[:HA])
    else
        @test rowdata[:HA] == test_data[1][ri]
    end

    @test XLSX.table_columns_count(rowdata) == 3
    @test XLSX.row_number(rowdata) == ri
    @test XLSX.get_column_labels(rowdata) == col_names
    @test XLSX.get_column_label(rowdata, 1) == :HA
    @test XLSX.get_column_label(rowdata, 2) == :HB
    @test XLSX.get_column_label(rowdata, 3) == :HC

    @test_throws ErrorException XLSX.getdata(rowdata, :INVALID_COLUMN)
end

override_col_names = [:ColumnA, :ColumnB, :ColumnC]
data, col_names = XLSX.gettable(s, column_labels=override_col_names)

@test col_names == override_col_names
check_test_data(data, test_data)

data, col_names = XLSX.gettable(s, "A:B", first_row=1)
test_data_AB_cols = Vector{Any}(2)
test_data_AB_cols[1] = test_data[1]
test_data_AB_cols[2] = test_data[2]
@test col_names == [:HA, :HB]
check_test_data(data, test_data_AB_cols)

data, col_names = XLSX.gettable(s, "A:B")
test_data_AB_cols = Vector{Any}(2)
test_data_AB_cols[1] = test_data[1]
test_data_AB_cols[2] = test_data[2]
@test col_names == [:HA, :HB]
check_test_data(data, test_data_AB_cols)

data, col_names = XLSX.gettable(s, "B:B", first_row=2)
@test col_names == [:B1]
@test length(data) == 1
@test length(data[1]) == 1
@test data[1][1] == "B2"

data, col_names = XLSX.gettable(s, "B:C")
@test col_names == [ :HB, :HC ]
test_data_BC_cols = Vector{Any}(2)
test_data_BC_cols[1] = ["B1", "B2"]
test_data_BC_cols[2] = [ missing, missing]
check_test_data(data, test_data_BC_cols)

data, col_names = XLSX.gettable(s, "B:C", first_row=2, header=false)
@test col_names == [ :B, :C ]
check_test_data(data, test_data_BC_cols)

s = f["table3"]
test_data = Vector{Any}(3)
test_data[1] = [ missing, missing, "B5" ]
test_data[2] = [ "C3", missing, missing ]
test_data[3] = [ missing, "D4", missing ]
data, col_names = XLSX.gettable(s)
@test col_names == [:H1, :H2, :H3]
check_test_data(data, test_data)
@test_throws ErrorException XLSX.find_row(XLSX.eachrow(s), 20)

for r in XLSX.eachrow(s)
    @test isempty(XLSX.getcell(r, "A"))
    @test XLSX.getdata(s, XLSX.getcell(r, "B")) == "H1"
    @test r[2] == "H1"
    @test r["B"] == "H1"
    break
end

@test XLSX._find_first_row_with_data(s, 5) == 5
@test_throws ErrorException XLSX._find_first_row_with_data(s, 7)

s = f["table4"]
data, col_names = XLSX.gettable(s)
@test col_names == [:H1, :H2, :H3]
check_test_data(data, test_data)

xf = XLSX.openxlsx(joinpath(data_directory, "general.xlsx"))
empty_sheet = XLSX.getsheet(xf, "empty")
@test_throws ErrorException XLSX.gettable(empty_sheet)
itr = XLSX.eachrow(empty_sheet)
@test_throws ErrorException XLSX.find_row(itr, 1)
@test_throws ErrorException XLSX.getsheet(xf, "invalid_sheet")
close(xf)

f = XLSX.readxlsx(joinpath(data_directory,"general.xlsx"))
tb5 = f["table5"]
test_data = Vector{Any}(1)
test_data[1] = [1, 2, 3, 4, 5]
data, col_names = XLSX.gettable(tb5)
@test col_names == [ :HEADER ]
check_test_data(data, test_data)
tb6 = f["table6"]
data, col_names = XLSX.gettable(tb6, first_row=3)
@test col_names == [ :HEADER ]
check_test_data(data, test_data)
tb7 = f["table7"]
data, col_names = XLSX.gettable(tb7, first_row=3)
@test col_names == [ :HEADER ]
check_test_data(data, test_data)

sheet_lookup = f["lookup"]
test_data = Vector{Any}(3)
test_data[1] = [ 10, 20, 30]
test_data[2] = [ "name1", "name2", "name3" ]
test_data[3] = [ 100, 200, 300 ]
data, col_names = XLSX.gettable(sheet_lookup)
@test col_names == [:ID, :NAME, :VALUE]
check_test_data(data, test_data)

header_error_sheet = f["header_error"]
@test_throws AssertionError XLSX.gettable(header_error_sheet)

@test XLSX.is_valid_fixed_sheet_cellname("named_ranges!\$A\$2")
@test XLSX.is_valid_fixed_sheet_cellrange("named_ranges!\$B\$4:\$C\$5")
@test !XLSX.is_valid_fixed_sheet_cellname("named_ranges!A2")
@test !XLSX.is_valid_fixed_sheet_cellrange("named_ranges!B4:C5")
@test XLSX.SheetCellRef("named_ranges!\$A\$2") == XLSX.SheetCellRef("named_ranges!A2")
@test XLSX.SheetCellRange("named_ranges!\$B\$4:\$C\$5") == XLSX.SheetCellRange("named_ranges!B4:C5")

# Consecutive passes should yield the same results
f = XLSX.openxlsx(joinpath(data_directory, "general.xlsx"))
sl = f["lookup"]
data, col_names = XLSX.gettable(sl)
@test col_names == [:ID, :NAME, :VALUE]
check_test_data(data, test_data)

data, col_names = XLSX.gettable(sl)
@test col_names == [:ID, :NAME, :VALUE]
check_test_data(data, test_data)

#
# Helper functions
#

test_data = Vector{Any}(3)
test_data[1] = [ missing, missing, "B5" ]
test_data[2] = [ "C3", missing, missing ]
test_data[3] = [ missing, "D4", missing ]

data, col_names = XLSX.readtable(joinpath(data_directory, "general.xlsx"), "table4")
@test col_names == [:H1, :H2, :H3]
check_test_data(data, test_data)

@test XLSX.readdata(joinpath(data_directory, "general.xlsx"), "table4", "E12") == "H1"
test_data = Array{Any, 2}(2, 1)
test_data[1, 1] = "H2"
test_data[2, 1] = "C3"

@test XLSX.readdata(joinpath(data_directory, "general.xlsx"), "table4", "F12:F13") == test_data

#
# Write
#

f = XLSX.openxlsxtemplate(joinpath(data_directory, "general.xlsx"))
filename_copy = "general_copy.xlsx"
XLSX.writexlsx(filename_copy, f)
@test isfile(filename_copy)

f_copy = XLSX.readxlsx(filename_copy)

s = f_copy["table"]
s[:];
data, col_names = XLSX.gettable(s)
@test col_names == [ Symbol("Column B"), Symbol("Column C"), Symbol("Column D"), Symbol("Column E"), Symbol("Column F"), Symbol("Column G")]

test_data = Vector{Any}(6)
test_data[1] = collect(1:8)
test_data[2] = [ "Str1", missing, "Str1", "Str1", "Str2", "Str2", "Str2", "Str2" ]
test_data[3] = [ Date(2018, 4, 21) + Dates.Day(i) for i in 0:7 ]
test_data[4] = [ missing, missing, missing, missing, missing, "a", "b", missing ]
test_data[5] = [ 0.2001132319, 0.2793987377, 0.0950591677, 0.0744023067, 0.8242278091, 0.6205883578, 0.9174151018, 0.6749604883 ]
test_data[6] = [ missing for i in 1:8 ]
check_test_data(data, test_data)
rm(filename_copy)

# Edit cells
f = XLSX.openxlsxtemplate(joinpath(data_directory, "general.xlsx"))
s = f["general"]
@test_throws ErrorException s["A1"] = :sym
XLSX.rename!(s, "renamed_sheet")
s["A1"] = "Hey You!"
s["B1"] = "Out there in the cold..."
s["A2"] = "Getting lonely getting old..."
s["B2"] = "Can you feel me?"
s["A3"] = 1000
s["B3"] = 99.99

# create a new sheet
s = XLSX.addsheet!(f, "my_new_sheet_1")
s = XLSX.addsheet!(f, "my_new_sheet_2")
s["B1"] = "This is a new sheet"
s["B2"] = "This is a new sheet"
s = XLSX.addsheet!(f)
s["B1"] = "unnamed sheet"

XLSX.writexlsx("general_copy_2.xlsx", f, rewrite=true)
@test isfile("general_copy_2.xlsx")

f = XLSX.openxlsx("general_copy_2.xlsx")
s = f["renamed_sheet"]
@test s["A1"] == "Hey You!"
@test s["B1"] == "Out there in the cold..."
@test s["A2"] == "Getting lonely getting old..."
@test s["B2"] == "Can you feel me?"
@test s["A3"] == 1000
@test s["B3"] == 99.99
f["my_new_sheet_1"];
@test f["my_new_sheet_2"]["B1"] == "This is a new sheet"
@test f["my_new_sheet_2"]["B2"] == "This is a new sheet"
@test f["Sheet1"]["B1"] == "unnamed sheet"
close(f)
rm("general_copy_2.xlsx")

# export table from template
col_names = ["Integers", "Strings", "Floats", "Booleans", "Dates", "Times", "DateTimes"]
data = Vector{Any}(7)
data[1] = [1, 2, Missings.missing, 4]
data[2] = ["Hey", "You", "Out", "There"]
data[3] = [101.5, 102.5, Missings.missing, 104.5]
data[4] = [ true, false, Missings.missing, true]
data[5] = [ Date(2018, 2, 1), Date(2018, 3, 1), Date(2018,5,20), Date(2018, 6, 2)]
data[6] = [ Dates.Time(19, 10), Dates.Time(19, 20), Dates.Time(19, 30), Dates.Time(19, 40) ]
data[7] = [ Dates.DateTime(2018, 5, 20, 19, 10), Dates.DateTime(2018, 5, 20, 19, 20), Dates.DateTime(2018, 5, 20, 19, 30), Dates.DateTime(2018, 5, 20, 19, 40)]

XLSX.writetable("output_table.xlsx", data, col_names, rewrite=true, sheetname="report", anchor_cell="B2")
@test isfile("output_table.xlsx")

read_data, read_column_names = XLSX.readtable("output_table.xlsx", "report")
@test length(read_column_names) == length(col_names)
for c in 1:length(col_names)
    @test Symbol(col_names[c]) == read_column_names[c]
end
check_test_data(read_data, data)
rm("output_table.xlsx")

report_1_column_names = ["HEADER_A", "HEADER_B"]
report_1_data = Vector{Any}(2)
report_1_data[1] = [1, 2, 3]
report_1_data[2] = ["A", "B", "C"]

report_2_column_names = ["COLUMN_A", "COLUMN_B"]
report_2_data = Vector{Any}(2)
report_2_data[1] = [Date(2017,2,1), Date(2018,2,1)]
report_2_data[2] = [10.2, 10.3]

XLSX.writetable("output_tables.xlsx", rewrite=true, REPORT_A=(report_1_data, report_1_column_names), REPORT_B=(report_2_data, report_2_column_names))
@test isfile("output_tables.xlsx")

data, labels = XLSX.readtable("output_tables.xlsx", "REPORT_A")
@test labels[1] == :HEADER_A
@test labels[2] == :HEADER_B
check_test_data(data, report_1_data)

data, labels = XLSX.readtable("output_tables.xlsx", "REPORT_B")
@test labels[1] == :COLUMN_A
@test labels[2] == :COLUMN_B
check_test_data(data, report_2_data)

rm("output_tables.xlsx")


text:
module App
  include("../src/CodeManager.jl")
  using .CodeManager

  #delete_old() = Core.eval(@__MODULE__, :(module TEST end))

  function run()
    println("Create module Game...")
    loaded = false
    loaded = CodeManager.include_module(@__MODULE__, joinpath(@__DIR__,"game.jl"))[1]

    if loaded
      println("Invoke Game.run()...")
      CodeManager.safe_invoke(@__MODULE__, :(Game.run))
      println("Invoke Game.reload()...")
      CodeManager.safe_invoke(@__MODULE__, :(Game.reload))
      println("Invoke Game.cleanUp()...")
      CodeManager.safe_invoke(@__MODULE__, :(Game.cleanUp))
    end

    println("Clean module Game in 5 Seconds...")
    sleep(5)
    CodeManager.safe_clean!(@__MODULE__, :Game)
    println("Done.")
  end

end

App.run()

ext: jl

max_stars_repo_name: Gilga/JLGLAssets

max_issues_repo_name: Gilga/JLGLAssets

max_forks_repo_name: Gilga/JLGLAssets


text:
"""
simulate(StateSpaceModel)

Simulate a stochastic volatility model. Volatility is NOT currently implemented as a random walk, but rather given by Σ.
"""

function simulate!(ssm::StateSpaceModel)
    y, F, G, m, P, S, β, δ, Δ, ν, n, k = ssm.y, ssm.F, ssm.G, ssm.m, ssm.P, ssm.S, ssm.β, ssm.δ, ssm.Δ, ssm.ν, ssm.n, ssm.k

    T, p = size(y)
    d = size(m, 1)

    # Priors (t = 0)
    Σ = rand(InverseWishart(n + 2p, S))
    Φ = rand(MatrixNormal(m, P, Σ))

    for t = 1:T
        # Sigma
        Σ = rand(InverseWishart(n + 2p, S))

        # State equation
        Φ = G * Φ + rand(MatrixNormal(zeros(d, p), P, Σ))

        # Measurement (observation) equation
        y[t, :] = F' * Φ + Σ
    end
end


text:
# Alternative test process where the package provides a `test/Project.toml`
# project that Pkg activates and instantiate before running the test script.
#
# The code in this file would be internal to Pkg, and packages would provide
# what's in `tests.jl`.

append!(empty!(LOAD_PATH), Base.DEFAULT_LOAD_PATH)
using Pkg

mktempdir() do tmp
    test_project = joinpath(@__DIR__, "Project.toml")
    test_manifest = joinpath(@__DIR__, "Manifest.toml")
    package_project = joinpath(@__DIR__, "..", "Project.toml")
    testfile = joinpath(@__DIR__, "tests.jl")

    tmp_test_project = joinpath(tmp, "Project.toml")
    tmp_test_manifest = joinpath(tmp, "Manifest.toml")

    # Copy test project to tmp directory
    cp(test_project, tmp_test_project)
    if isfile(test_manifest) # ??
        cp(test_manifest, tmp_test_manifest)
    end
    # Activate and instantiate
    Pkg.activate(tmp_test_project)
    Pkg.instantiate()
    Pkg.develop(PackageSpec(path = dirname(package_project)))
    # Run tests
    withenv("JULIA_LOAD_PATH" => tmp_test_project) do
        run(`$(Base.julia_cmd()) --startup-file=no $(testfile)`)
    end
end


text:
#=
This snippet is a simple get-to-learn-RNNs implementation that trains a single-layer RNN
to take a list of numbers of arbitrary length and output it's sum.

This was chosen because:
* It is easy to generate data
* It is easy to test
* It (should be) easy to train
* It is easy to evaluate visually
=#

using Flux: @epochs

num_samples = 1000
num_epochs = 50

function generate_data(num_samples)
	# we just generate data of variable length from 2 to 7 elements with each element being
	# a float between 1 and 10, to keep it simple!
	train_data = [rand(1.0:10.0, rand(2:7)) for i in 1:num_samples]
	train_labels = (v -> sum(v)).(train_data)

	# why bother generating new data when you can just multiply your
	# test data! No really, in real models you never want to do this
	# because that means you're evaluating on your training data which
	# is a big no-no. For learning purposes, it works great!
	test_data = 2 .* train_data
	test_labels = 2 .* train_labels

	train_data, train_labels, test_data, test_labels
end

train_data, train_labels, test_data, test_labels = generate_data(num_samples)
# we use no activation because tanh limits to the range -1,1 which is NOT
# what you want out of a summation function
simple_rnn = Flux.RNN(1, 1, (x -> x))

function eval_model(x)
	out = simple_rnn.(x)[end]
	Flux.reset!(simple_rnn)
	out
end

loss(x, y) = abs(sum((eval_model(x) .- y)))

ps = Flux.params(simple_rnn)

opt = Flux.ADAM()

println("Training loss before = ", sum(loss.(train_data, train_labels)))
println("Test loss before = ", sum(loss.(test_data, test_labels)))

# callback function during training
evalcb() = @show(sum(loss.(test_data, test_labels)))

@epochs num_epochs Flux.train!(loss, ps, zip(train_data, train_labels), opt, cb = Flux.throttle(evalcb, 1))

# after training, evaluate the loss
println("Test loss after = ", sum(loss.(test_data, test_labels)))


text:
facts("Auth token generation is successful")  do
    include(joinpath(dirname(@__FILE__),"../src/Quandl.jl"))

    context("created an empty token file after importing module") do
        context("created token file") do
            @fact isfile(joinpath(dirname(@__FILE__),"../token/auth_token")) --> true
        end

        context("token file is empty") do
            @fact open(readall, joinpath(dirname(@__FILE__),"../token/auth_token")) --> ""
        end
    end

    context("invalid tokens detected") do
        context("detects short token") do
            @fact_throws Quandl.set_auth_token("a")
        end

        context("detects long token") do
            @fact_throws Quandl.set_auth_token("a"^21)
        end
    end
end


text:
using Test
using LogicCircuits
using ProbabilisticCircuits

include("helper/plain_logic_circuits.jl")

@testset "probabilistic circuit nodes" begin

    c1 = little_3var()

    @test isdisjoint(linearize(ProbCircuit(c1)), linearize(ProbCircuit(c1)))

    p1 = ProbCircuit(c1)
    lit3 = children(children(p1)[1])[1]

    # traits
    @test p1 isa ProbCircuit
    @test p1 isa PlainSumNode
    @test children(p1)[1] isa PlainMulNode
    @test lit3 isa PlainProbLiteralNode
    @test issum(p1)
    @test ismul(children(p1)[1])
    @test GateType(lit3) isa LiteralGate
    @test length(mul_nodes(p1)) == 4

    # methods
    @test num_parameters(p1) == 10

    # extension methods
    @test literal(lit3) === literal(children(children(c1)[1])[1])
    @test variable(left_most_descendent(p1)) == Var(3)
    @test ispositive(left_most_descendent(p1))
    @test !isnegative(left_most_descendent(p1))
    @test num_nodes(p1) == 15
    @test num_edges(p1) == 18
    @test num_parameters_node(p1) == 2

    r1 = fully_factorized_circuit(ProbCircuit,10)
    @test num_parameters(r1) == 2*10+1

    @test length(mul_nodes(r1)) == 1

    # compilation tests
    @test_throws Exception compile(ProbCircuit, true)
    v1, v2, v3 = literals(ProbCircuit, 3)
    r = v1[1] * 0.3 + 0.7 * v1[2]
    @test r isa PlainSumNode
    @test all(children(r) .== [v1[1], v1[2]])
    @test all(ProbabilisticCircuits.params(r) .≈ log.([0.3, 0.7]))
    @test r * v2[1] isa PlainMulNode
    @test num_children(v1[1] * v2[1] * v3[1]) == 3
    @test num_children(v1[1] + v2[1] + v3[1]) == 3
end


text:
include("../lib/quantum_utils.jl")
using DifferentialEquations

#######################################################################################
#
# define Schrodinger equation problem with dispalcement operator
#   T: final time
#   ψ0_qo: initial ket  (currently only vaccum state is allowed)
#   A,B1,B2,C,D: tensors for Hamiltonian  (B= )
#
#
function Schrodinger_com(T::Float64,ψ0::Ket,μ₁0::Array{Float64},A::Array{Float64},B1::Array{Float64},B2::Array{Float64},C::Array{Float64},D::Array{Float64})

    Nfocks = ψ0.basis.shape .-1
    N = length(Nfocks)
    as = a_vectors(Nfocks)
    adags = dagger.(as);
    z = vcat((as+adags),(as-adags)/im)/√2;

    Ω_uu = Omega_uu(N)
    Ω_dd = Omega_dd(N)
    μ₁ = zeros(Float64,2N)
    dμ₁ = zeros(Float64,2N)
    ϕ = ground_state(Nfocks)
    ψ = ground_state(Nfocks)

    state_vec0 = vcat(μ₁0,real.(ψ0.data),imag.(ψ0.data))

    function time_evol_det(d_state_vec,state_vec,p,t)

        μ₁ = state_vec[1:2N]
        ϕ.data = state_vec[2N+1:2N+length(ϕ.data)] + im * state_vec[2N+1+length(ϕ.data):2N+length(ϕ.data)*2]

        B = B1 + B2 * t/T

        μ₂ = get_μ(ϕ,z,2)
        μ₃ = get_μ(ϕ,z,3)
        μ₂_raw = get_2nd_raw_moment(μ₁,μ₂)
        μ₃_raw = get_3rd_raw_moment(μ₁,μ₂,μ₃)

        @tensor begin
            dμ₁[i]       = -1. * A[j]       * Ω_dd[j,i]
            dμ₁[i]      += -2. * B[j,k]     * Ω_dd[j,i] * μ₁[k] #
            dμ₁[i]      += -3. * C[j,k,l]   * Ω_dd[j,i] * μ₂_raw[k,l]
            dμ₁[i]      += -4. * D[j,k,l,m] * Ω_dd[j,i] * μ₃_raw[k,l,m]
        end

        @tensor f_dis[k] := -Ω_uu[i,k]*dμ₁[i]
        F_dis = get_operator(f_dis,z)

        z_prime = z + μ₁ .* [identityoperator(Nfocks) for i in 1:2N]
        Ht = (get_operator(A,z_prime) + get_operator(B,z_prime) + get_operator(C,z_prime) + get_operator(D,z_prime)) - F_dis

        dϕ = -im*Ht * ϕ

        d_state_vec .= vcat(dμ₁,real.(dϕ.data),imag.(dϕ.data))
    end

    return ODEProblem(time_evol_det,state_vec0,(0.0,T))

end

#######################################################################################
#
# define Belavkin equation problem with dispalcement operator
#   T: final time
#   ψ0_qo: initial ket  (currently only vaccum state is allowed)
#   A,B1,B2,C,D: tensors for Hamiltonian  (B= )
#
#
function Belavkin_com(T::Float64,ψ0::Ket,μ₁0::Array{Float64},A::Array{Float64},B1::Array{Float64},B2::Array{Float64},C::Array{Float64},D::Array{Float64},vec_EF::Array{Array{Complex{Float64}},2};seed_input=0)

    Nfocks = ψ0.basis.shape .-1
    N = length(Nfocks)
    as = a_vectors(Nfocks)
    adags = dagger.(as);
    z = vcat((as+adags),(as-adags)/im)/√2;

    Ω_uu = Omega_uu(N)
    Ω_dd = Omega_dd(N)
    μ₁ = zeros(Float64,2N)
    dμ₁ = zeros(Float64,2N)
    ϕ = ground_state(Nfocks)
    dϕ = ground_state(Nfocks)
    ψ = ground_state(Nfocks)

    A′= Array{Complex{Float64}}(undef,2N);
    B′= Array{Complex{Float64}}(undef,2N,2N);
    C′= Array{Complex{Float64}}(undef,2N,2N,2N);
    D′= Array{Complex{Float64}}(undef,2N,2N,2N,2N);

    state_vec0 = vcat(μ₁0,real.(ψ0.data),imag.(ψ0.data))

    function time_evol_det(d_state_vec,state_vec,p,t)

        μ₁ = state_vec[1:2N]
        ϕ.data = state_vec[2N+1:2N+length(ϕ.data)] + im * state_vec[2N+1+length(ϕ.data):2N+length(ϕ.data)*2]

        B = B1 + B2 * t/T

        μ₂ = get_μ(ϕ,z,2)
        μ₂_raw = get_2nd_raw_moment(μ₁,μ₂)
        get_effective_Hamiltonian_tensors!(A′,B′,C′,D′,A,B,C,D,vec_EF,μ₁,μ₂_raw)
        z_prime = z + μ₁ .* [identityoperator(Nfocks) for i in 1:2N]
        H = get_operator([A′,B′,C′,D′],z_prime)

        mul!(dϕ.data,-im*H.data,ϕ.data)
        dif_norm = real(dagger(ϕ) * dϕ)
        dϕ.data -= dif_norm*ϕ.data

        dμ₁ = [2*real(dagger(ϕ) * z_prime_i * dϕ) for z_prime_i in z_prime ]
        @tensor f_dis[k] := -Ω_uu[i,k]*dμ₁[i]
        dϕ += im * get_operator(f_dis,z) * ϕ # -F_dis

        d_state_vec .= vcat(dμ₁,real.(dϕ.data),imag.(dϕ.data))
    end

    #########################################################################
    #
    # stochastic part
    #
    function time_evol_sto(d_state_vec,state_vec,p,t)

        μ₁ = state_vec[1:2N]
        ϕ.data = state_vec[2N+1:2N+length(ϕ.data)] + im * state_vec[2N+1+length(ϕ.data):2N+length(ϕ.data)*2]

        for i in 1:size(vec_EF)[1]

            z_prime = z + μ₁ .* [identityoperator(Nfocks) for i in 1:2N]
            L = get_operator(vec_EF[i,1],z_prime) + get_operator(vec_EF[i,2],z_prime)

            mul!(dϕ.data,L.data,ϕ.data)
            dif_norm = real(dagger(ϕ) * dϕ)
            dϕ.data -= dif_norm*ϕ.data

            dμ₁ = [2*real(dagger(ϕ) * z_prime_i * dϕ) for z_prime_i in z_prime ]

            @tensor f_dis[k] := -Ω_uu[i,k]*dμ₁[i]
            dϕ += im * get_operator(f_dis,z) * ϕ # -F_dis

            d_state_vec[:,i] .= vcat(dμ₁,real.(dϕ.data),imag.(dϕ.data))

        end
    end

    if seed_input == 0
        return SDEProblem(time_evol_det,time_evol_sto,state_vec0,(0.0,T),noise_rate_prototype=zeros(length(state_vec0),size(vec_EF)[1]))
    else
        return SDEProblem(time_evol_det,time_evol_sto,state_vec0,(0.0,T),noise_rate_prototype=zeros(length(state_vec0),size(vec_EF)[1]),seed=seed_input)
    end

end

function get_hist_μ₁ϕ(sol::Any,Nfocks::Array{Int64,1},Nsave::Int,T::Float64)
    N = length(Nfocks)

    μ₁_hist = Array{Vector{Float64}}(undef,Nsave)
    ϕ_hist = Array{Any}(undef,Nsave)

    for i in 1:Nsave
        μ₁_hist[i] = Vector{Float64}(undef,2N)
        ϕ_hist[i] = ground_state(Nfocks)
        state_vec = sol(T*i/Nsave)
        μ₁_hist[i] = state_vec[1:2N]
        ϕ_hist[i].data[:] .= state_vec[2N+1:2N+length(ϕ_hist[i].data)] + im * state_vec[2N+1+length(ϕ_hist[i].data):2N+length(ϕ_hist[i].data)*2]

    end
    return μ₁_hist,ϕ_hist
end

max_stars_repo_name: ash-y/QuantumCOMFrame

max_issues_repo_name: ash-y/QuantumCOMFrame

max_forks_repo_name: ash-y/QuantumCOMFrame


text:
#==============================================================================#
# MarketplaceMetering.jl
#
# This file is generated from:
# https://github.com/aws/aws-sdk-js/blob/master/apis/meteringmarketplace-2016-01-14.normal.json
#==============================================================================#

__precompile__()

module MarketplaceMetering

using AWSCore

"""
    using AWSSDK.MarketplaceMetering.batch_meter_usage
    batch_meter_usage([::AWSConfig], arguments::Dict)
    batch_meter_usage([::AWSConfig]; UsageRecords=, ProductCode=)

    using AWSCore.Services.meteringmarketplace
    meteringmarketplace([::AWSConfig], "BatchMeterUsage", arguments::Dict)
    meteringmarketplace([::AWSConfig], "BatchMeterUsage", UsageRecords=, ProductCode=)

# BatchMeterUsage Operation

BatchMeterUsage is called from a SaaS application listed on the AWS Marketplace to post metering records for a set of customers.

For identical requests, the API is idempotent; requests can be retried with the same records or a subset of the input records.

Every request to BatchMeterUsage is for one product. If you need to meter usage for multiple products, you must make multiple calls to BatchMeterUsage.

BatchMeterUsage can process up to 25 UsageRecords at a time.

# Arguments

## `UsageRecords = [[ ... ], ...]` -- *Required*
The set of UsageRecords to submit. BatchMeterUsage accepts up to 25 UsageRecords at a time.
```
 UsageRecords = [[
        "Timestamp" => <required> timestamp,
        "CustomerIdentifier" => <required> ::String,
        "Dimension" => <required> ::String,
        "Quantity" => <required> ::Int
    ], ...]
```

## `ProductCode = ::String` -- *Required*
Product code is used to uniquely identify a product in AWS Marketplace. The product code should be the same as the one used during the publishing of a new product.

# Returns

`BatchMeterUsageResult`

# Exceptions

`InternalServiceErrorException`, `InvalidProductCodeException`, `InvalidUsageDimensionException`, `InvalidCustomerIdentifierException`, `TimestampOutOfBoundsException` or `ThrottlingException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/meteringmarketplace-2016-01-14/BatchMeterUsage)
"""
@inline batch_meter_usage(aws::AWSConfig=default_aws_config(); args...) = batch_meter_usage(aws, args)

@inline batch_meter_usage(aws::AWSConfig, args) = AWSCore.Services.meteringmarketplace(aws, "BatchMeterUsage", args)

@inline batch_meter_usage(args) = batch_meter_usage(default_aws_config(), args)

"""
    using AWSSDK.MarketplaceMetering.meter_usage
    meter_usage([::AWSConfig], arguments::Dict)
    meter_usage([::AWSConfig]; ProductCode=, Timestamp=, UsageDimension=, UsageQuantity=, DryRun=)

    using AWSCore.Services.meteringmarketplace
    meteringmarketplace([::AWSConfig], "MeterUsage", arguments::Dict)
    meteringmarketplace([::AWSConfig], "MeterUsage", ProductCode=, Timestamp=, UsageDimension=, UsageQuantity=, DryRun=)

# MeterUsage Operation

API to emit metering records. For identical requests, the API is idempotent. It simply returns the metering record ID.

MeterUsage is authenticated on the buyer's AWS account, generally when running from an EC2 instance on the AWS Marketplace.

# Arguments

## `ProductCode = ::String` -- *Required*
Product code is used to uniquely identify a product in AWS Marketplace. The product code should be the same as the one used during the publishing of a new product.

## `Timestamp = timestamp` -- *Required*
Timestamp of the hour, recorded in UTC. The seconds and milliseconds portions of the timestamp will be ignored.

## `UsageDimension = ::String` -- *Required*
It will be one of the fcp dimension name provided during the publishing of the product.

## `UsageQuantity = ::Int` -- *Required*
Consumption value for the hour.

## `DryRun = ::Bool` -- *Required*
Checks whether you have the permissions required for the action, but does not make the request. If you have the permissions, the request returns DryRunOperation; otherwise, it returns UnauthorizedException.

# Returns

`MeterUsageResult`

# Exceptions

`InternalServiceErrorException`, `InvalidProductCodeException`, `InvalidUsageDimensionException`, `InvalidEndpointRegionException`, `TimestampOutOfBoundsException`, `DuplicateRequestException` or `ThrottlingException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/meteringmarketplace-2016-01-14/MeterUsage)
"""
@inline meter_usage(aws::AWSConfig=default_aws_config(); args...) = meter_usage(aws, args)

@inline meter_usage(aws::AWSConfig, args) = AWSCore.Services.meteringmarketplace(aws, "MeterUsage", args)

@inline meter_usage(args) = meter_usage(default_aws_config(), args)

"""
    using AWSSDK.MarketplaceMetering.resolve_customer
    resolve_customer([::AWSConfig], arguments::Dict)
    resolve_customer([::AWSConfig]; RegistrationToken=)

    using AWSCore.Services.meteringmarketplace
    meteringmarketplace([::AWSConfig], "ResolveCustomer", arguments::Dict)
    meteringmarketplace([::AWSConfig], "ResolveCustomer", RegistrationToken=)

# ResolveCustomer Operation

ResolveCustomer is called by a SaaS application during the registration process. When a buyer visits your website during the registration process, the buyer submits a registration token through their browser. The registration token is resolved through this API to obtain a CustomerIdentifier and product code.

# Arguments

## `RegistrationToken = ::String` -- *Required*
When a buyer visits your website during the registration process, the buyer submits a registration token through the browser. The registration token is resolved to obtain a CustomerIdentifier and product code.

# Returns

`ResolveCustomerResult`

# Exceptions

`InvalidTokenException`, `ExpiredTokenException`, `ThrottlingException` or `InternalServiceErrorException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/meteringmarketplace-2016-01-14/ResolveCustomer)
"""
@inline resolve_customer(aws::AWSConfig=default_aws_config(); args...) = resolve_customer(aws, args)

@inline resolve_customer(aws::AWSConfig, args) = AWSCore.Services.meteringmarketplace(aws, "ResolveCustomer", args)

@inline resolve_customer(args) = resolve_customer(default_aws_config(), args)

end # module MarketplaceMetering

#==============================================================================#
# End of file
#==============================================================================#


text:
# purpose
# finite element simulation for disk domain without PML
#
using Revise
using AdFem
using PyPlot

function ricker(;dt = 0.005, f0 = 3.0)
    nw = 2/(f0*dt)
    nc = floor(Int, nw/2)
    t = dt*collect(-nc:1:nc)
    b = (π*f0*t).^2
    w = @. (1 - 2b)*exp(-b)
end

mmesh = Mesh(joinpath(PDATA, "disk.stl"))
NT = 300
Δt = 10/NT

xy = gauss_nodes(mmesh)
xg, yg = xy[:,1], xy[:,2]
xy = fem_nodes(mmesh)
x, y = xy[:,1], xy[:,2]

β = zeros(mmesh.ndof)
β_g = zeros(get_ngauss(mmesh))
βprime = zeros(get_ngauss(mmesh))
c = constant(0.1ones(get_ngauss(mmesh)))
nv = [ones(get_ngauss(mmesh)) zeros(get_ngauss(mmesh))]

R = 50000
pf = n->R*n^3
pfprime = n->3*R*n^2

# for i = 1:get_ngauss(mmesh)
#     if xg[i]<0.1
#         nv[i,:] = [-1.0;0.0]
#         n = abs(0.1-xg[i])
#     elseif xg[i]>0.9
#         nv[i,:] = [1.0;0.0]
#         n = abs(0.9-xg[i])
#     elseif yg[i]<0.1
#         nv[i,:] = [0.0;-1.0]
#         n = abs(0.1-yg[i])
#     elseif yg[i]>0.9
#         nv[i,:] = [0.0;1.0]
#         n = abs(0.9-yg[i])
#     else
#         continue
#     end
#     β_g[i] = pf(n)
#     βprime[i] = pfprime(n)
# end

# for i = 1:mmesh.ndof
#     if x[i]<0.1
#         n = abs(0.1-x[i])
#     elseif x[i]>0.9
#         n = abs(0.9-x[i])
#     elseif y[i]<0.1
#         n = abs(0.1-y[i])
#     elseif y[i]>0.9
#         n = abs(0.9-y[i])
#     else
#         continue
#     end
#     β[i] = pf(n)
# end

nv = constant(nv)
β_g = constant(β_g)
βprime = constant(βprime)
β = constant(β)

F = zeros(NT+1, get_ngauss(mmesh))
F[1:length(ricker(f0=2.0)),2312] = ricker(f0=2.0)
F = constant(F)

RHS = zeros(mmesh.ndof)
bdnode = bcnode(mmesh)

M = constant(compute_fem_mass_matrix1(mmesh))
Z1 = constant(compute_fem_mass_matrix1(β_g, mmesh))
Z2 = constant(compute_fem_mass_matrix1(β_g^2, mmesh))
M, _ = impose_Dirichlet_boundary_conditions(M, RHS, bdnode, zeros(length(bdnode)))
Z1, _ = impose_Dirichlet_boundary_conditions(Z1, RHS, bdnode, zeros(length(bdnode)))
Z2, _ = impose_Dirichlet_boundary_conditions(Z2, RHS, bdnode, zeros(length(bdnode)))

integrator1 = ExplicitNewmark(M, 2Z1, Z2, Δt)
integrator2 = integrator1
integrator3 = ExplicitNewmark(M, Z1, missing, Δt)
integrator4 = ExplicitNewmark(M, missing, missing, Δt)

function rk_one_step(d2, t)
    h1 = -β*d2 + t
    h2 = -β*(d2+Δt*h1)+t
    d2 + Δt/2*(h1+h2)
end

function one_step(u, d10, d20, d30, d40, t0,
                    d11, d21, d31, d41, t1, f)
    k1, k2, k3, k4 = compute_pml_term(u, βprime, c, nv, mmesh)
    k4 = k4 + compute_fem_source_term1(f, mmesh)
    d12 = step(integrator1, d10, d11, k1)
    t2 = step(integrator2, t0, t1, k2)
    d32 = step(integrator3, d30, d31, k3)
    d42 = step(integrator4, d40, d41, k4)
    d22 = rk_one_step(d21, t2)
    u = d12 + d22 + d32 + d42
    return u, d12, d22, d32, d42, t2
end

function simulate()
    for op in [:d1, :d2, :d3, :d4, :t, :uarr]
        @eval $op=TensorArray(NT+1)
        @eval $op=write($op, 1, zeros(mmesh.ndof))
        @eval $op=write($op, 2, zeros(mmesh.ndof))
    end

    function condition(i, tas...)
        i<=NT
    end
    function body(i, d1, d2, d3, d4, t, uarr)
        d10 = read(d1, i-1); d11 = read(d1, i)
        d20 = read(d2, i-1); d21 = read(d2, i)
        d30 = read(d3, i-1); d31 = read(d3, i)
        d40 = read(d4, i-1); d41 = read(d4, i)
        t0 = read(t, i-1); t1 = read(t, i)
        u = read(uarr, i)
        f = F[i]
        u, d12, d22, d32, d42, t2  = one_step(u, d10, d20, d30, d40, t0,
                    d11, d21, d31, d41, t1, f)
        i+1, write(d1, i+1, d12), write(d2, i+1, d22), write(d3, i+1, d32),
                write(d4, i+1, d42), write(t, i+1, t2), write(uarr, i+1, u)
    end
    i = constant(2, dtype = Int32)
    _, _, _, _, _, _, u = while_loop(condition, body, [i, d1, d2, d3, d4, t, uarr])
    set_shape(stack(u), (NT+1, mmesh.ndof))
end

u = simulate()
sess = Session(); init(sess)
U = run(sess, u)

close("all")
p = visualize_scalar_on_fem_points(U[1:15:end,:], mmesh)
saveanim(p, "anim.gif")
# vmax, vmin = maximum(U), minimum(U)
# for k = 0:5
#     close("all")
#     visualize_scalar_on_fem_points(U[k * (NT÷6) + 1,:], mmesh, vmin = vmin, vmax = vmax)
#     savefig("s$k.png")
# end


text:
using StatsBase
using Random

"""
Used in the computation of cramer's V and cohen's K.
Returns the lagged bivariate probability of two given categories, Pij.
Given i and j two categories, and l a lag,
Pij is the probability to have the category j at time t + l, if we have i at time t.
    inputs :
    - time series : the data to analyse
    - lag : the value of lag at which one wants Pij
    - category1 : the first category
    - category2 : the second category
    output :
    - Pij : the probability to observe j at t + l if we observe i at time t.
"""
function LaggedBivariateProbability(TimeSerie, Lag::Int, Category1, Category2)
    Pij = 0
    lagged_serie_length = length(TimeSerie) - Lag
    for i in Lag+1:lagged_serie_length
        if (TimeSerie[i] == Category1) && (TimeSerie[i - Lag] == Category2)
            Pij += 1/(lagged_serie_length)
        end
    end
    return Pij
end

"""
If an array of lags 'Lag' is provided instead of a single value, computes Pij for each lag value and returns an array.
"""
function LaggedBivariateProbability(TimeSerie, Lags::Array{Int64,1}, Category1, Category2)
    Pij = [LaggedBivariateProbability(TimeSerie,L,Category1,Category2) for L in Lags]
    return Lags,Pij
end

"""
If no categories are explicitely provided, will a CxC symmetric probability matrix, with C the number of != categories.
the element [i,j] of this matrix corresponds to Pij at lag 'Lag'. Use this function if you want to have the contingency table at lag 'Lag'.
"""
function LaggedBivariateProbability(TimeSeries, Lag::Int64)
    categories = sort(unique(TimeSeries))
    Pij = zeros(length(categories), length(categories))
    lagged_serie_length = length(TimeSeries) - Lag
    for (idxi, i) in enumerate(categories)
        for (idxj, j) in enumerate(categories)
            for t in Lag+1:length(TimeSeries)
                if (TimeSeries[t] == i) && (TimeSeries[t - Lag] == j)
                    Pij[idxi, idxj] += 1/(lagged_serie_length)
                end
            end
        end
    end
    return Pij
end

"""
Returns the relative frequency of a given category (of type ::Any).
For example, if we have 3 category a,b and c, and a occurs 300 times in a time series of length 900,
its relative frequency  is 1/3.

"""
function relative_frequency(TimeSerie, idx::Any)
    Pi = 0
    for i in TimeSerie
        if i == unique(TimeSerie)[idx]
            Pi += 1/length(TimeSerie)
        end
    end
    return Pi
end

"""
Computes the lagged cohen coefficient κ describing how much the different categories
are correlated to each others at different lag values in the time-series. K is a measure of agreement.
input:
    -Serie : a categorical time series
    -lag: an integer lag value
output:
    -κ : cohen's coefficient
"""
function cohen_coefficient(Serie, lag = 1)
    if typeof(lag) != Int64
        throw("typeError : 'lag' value needs to be integer.")
    end
    categories = unique(Serie)
    K = 0
    pi_denominateur = 0
    rf_squared = [relative_frequency(Serie,i)^2 for i in 1:length(categories)]
    lagged_pij = LaggedBivariateProbability(Serie, lag)
    for (idxi, i) in enumerate(categories)
        K += (lagged_pij[idxi, idxi] - rf_squared[idxi])
        pi_denominateur += rf_squared[idxi]
    end
    K = K/(1-pi_denominateur)
    return K
end

"""
If 'lag' is provided as an array of lags, computes and returns an array of K for each elements of 'lag'.
"""
function cohen_coefficient(Serie, Lags::Array{Int64,1})
    if typeof(Lags) != Array{Int64,1}
        throw("typeError : 'lag' value needs to be integer.")
    end
    categories = unique(Serie)
    K = zeros(length(Lags))
    rf_squared = [relative_frequency(Serie,i)^2 for i in 1:length(categories)]
    for (lidx,l) in enumerate(Lags)
        k = 0
        pi_denominateur = 0
        lagged_pij = LaggedBivariateProbability(Serie, l)
        for (idxi, i) in enumerate(categories)
            k += (lagged_pij[idxi, idxi] - rf_squared[idxi])
            pi_denominateur += rf_squared[idxi]
        end
        K[lidx] =  k/(1-pi_denominateur)
    end
    return K
end

"""
    cramer_coefficient(Serie, Lags::Array{Int64,1})

Returns the cramer's V coefficient for the given 'Lags' values.

Cramer's v is used in categorical data analysis to test the degree of association between
a given set of categorical variable and another set of variables (example : eye color and hair color).
Here, it measures the association between the categorical values of a time series, and the values at a later lagged time.

V lies in [0,1]. 0 no association, 1 perfect association.
It is symmetric, meaning v(A,B) = v(B,A), so the information contained in the asymmetry between the variables is lost.

    input :
    - Serie : the time series containing the data
    - Lags : Array containing the lags at which V will be computed. If an int is given
                a single point value will be returned.

    output :
    - V : the values of v for the given lags.

"""
function cramer_coefficient(Serie, Lags::Array{Int64,1})
    if typeof(Lags) != Array{Int64,1}
        throw("typeError : 'Lags' needs to be an Array{Int64,1}.")
    end
    Categories = unique(Serie)
    V = zeros(length(Lags))
    d = length(Categories)-1
    rf = [relative_frequency(Serie, i) for i in 1:length(Categories)]
    for (lidx,lag) in enumerate(Lags)
        v = 0
        lagged_pij = LaggedBivariateProbability(Serie, lag)
        for i in 1:d+1
            for j in 1:d+1
                v += ( (lagged_pij[i,j]-rf[i]*rf[j])^2 ) / (rf[i]*rf[j])
            end
        end
        V[lidx] = sqrt(v)/d
    end
    return V
end

function cramer_coefficient(Serie, lag = 1)
    if typeof(lag) != Int64
        throw("typeError : 'lag' value needs to be integer.")
    end
    v = 0
    d = length(unique(Serie))-1
    lagged_pij = LaggedBivariateProbability(Serie, lag)
    rf = [relative_frequency(Serie,i) for i in 1:d+1]
    for i in 1:d+1
        for j in 1:d+1
            v += ((lagged_pij[i,j]-rf[i]*rf[j])^2)/(rf[i]*rf[j])
        end
    end
    return sqrt(v)/d
end

"""
    H(x)

Estimates the probability distribution of the categories in 'x' and computes its entropy.
It characterizes the amount of information carried by the distribution.
it tells how "disperse" the distribution is.

"""
function H(x)
    x_count = countmap(x)
    total_occurences = sum(values(x_count))
    entropy = 0.0
    for occurence in values(x_count)
        px = occurence/total_occurences
        entropy -= px*log2(px)
    end
    return entropy
end

"""
Computing the conditional entropy of y given x: H(Y|X),
Given in bits or shannons (meaning using the log2 for the measurement).
Wikipedia: https://en.wikipedia.org/wiki/Conditional_entropy

"""
function conditional_entropy(y,x)
    xy_count = countmap(collect(zip(y,x)))
    x_count = countmap(x)
    total_occurences = sum(values(xy_count))
    entropy = 0.0
    for xy in keys(xy_count)
        p_xy = xy_count[xy]/total_occurences
        p_x = x_count[xy[2]]/total_occurences
        entropy += p_xy*log2(p_x/p_xy)
    end
    return entropy
end

"""
    theils_u(x, Lags)

Measures what portion of the information associated to the values in 'x' is know at t + lag if the value 'x' is known at t.
Input :
    x : a categorical time-series
    lags : an array of lags onto U is computed.
returns:
    U : an array of U for the given values in 'Lags'.
"""
function theils_u(x, Lags)
    return [(H(x[1:end-l]) - conditional_entropy(x[1:end-l], x[l+1:end])) / H(x[1:end-l]) for l in Lags]
end

"""
    rate_evolution(Series)

A way to test the stationarity of the input categorical time-series 'Series'.
if it varies linearly, then the time series is more or less stationary.
"""
function rate_evolution(Series)
    categories = unique(Series)
    RATE = []
    for c in categories
        init = zeros(length(Series))
        for v in 1:length(Series)
            if Series[v] == c
                init[v] = 1
            end
        end
        push!(RATE,cumsum(init))
    end
    return RATE
end

"""
    bootstrap_CI(Series, lags, coefficient, n_iter = 1000)

Provides 95% a confidence interval by shuffling 'Series' 'n_iter' times, computing the values of 'coefficient'
then finding the value of the top and bottom 2,5% to get the interval.
This is done for every point in 'lags' (can be costly if 'Series' is long).

Input :
    - Series : input array of categorical data
    - lags (Array{Int64,1}) : the lag values at which the analysis is conducted
    - coef_func (**function**) : the function for which the CI needs to be computed.
            'coefficient' can be one of the following **functions** : 'cramer_coefficient, cohen_coefficient, theils_U'.
    - n_iter (Int64) : how many iterations are run for the bootstrap procedure.
    - interval_size (Float64) : the size of the desired confidence interval in percent. Defaults to 0.95 (i.e 95% confidence interval).
returns :
    - top (Array{Float64,1}) : Array of values for the upper limit of the CI.
    - bottom (Array{Float64,1}) : Array of values for the lower limit of the CI.
"""
function bootstrap_CI(Series,  lags, coef_func, n_iter = 1000, interval_size = 0.95)
    interval_bounds = floor(Int, (n_iter - n_iter*interval_size)/2)
    critical_values = zeros(n_iter)
    bootstrap_storage = zeros(n_iter, length(lags))
    for i in 1:n_iter
        bootstrap_storage[i,:] = coef_func(shuffle(Series), lags)
    end
    top_values = sort(bootstrap_storage, dims = 1)[n_iter - interval_bounds,:]
    bottom_values = sort(bootstrap_storage, dims = 1)[interval_bounds,:]
    return top_values, bottom_values
end

export cramer_coefficient, cohen_coefficient, conditional_entropy, LaggedBivariateProbability, H, theils_u, rate_evolution


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

using Markdown
using InteractiveUtils

# ╔═╡ 6f229530-dc29-11ec-338a-0d435ffc6c7e
using RDatasets, DataFrames, CSV

# ╔═╡ 24d1040d-51b6-4674-b2c7-bb63f080ab02
using PlutoPlotly

# ╔═╡ bafe1b78-bf38-4e6e-b5f2-4057138f04ae
md"""
Notebook based on [https://plotly.com/julia/3d-scatter-plots/](https://plotly.com/julia/3d-scatter-plots/)
"""

# ╔═╡ e8fa739b-2e54-4ea0-878a-bc0f6b6a9f08
md"""
# 3D scatter plot
Like the 2D scatter plot scatter, the 3D version type="scatter3d" plots individual data in three-dimensional space.
"""

# ╔═╡ 97db89cc-4416-4b78-b466-e9612f7962a6
df = dataset("datasets", "iris");

# ╔═╡ 9df1faa3-6bc8-4930-b8fb-94771ba5ab63
plot(scatter3d(
    df;
    x=:SepalLength, y=:SepalWidth, z=:PetalWidth, group=:Species,
    type="scatter3d", mode="markers"
))

# ╔═╡ ddc5f2c7-2b98-417a-97ce-69c7b27cc848
plot(scatter3d(
    df;
    x=:SepalLength, y=:SepalWidth, z=:PetalWidth, group=:Species, mode="markers",
    marker_size=:PetalLength, marker_sizeref=0.3,
),Layout(margin=attr(l=0, r=0, b=0, t=0)))

# ╔═╡ 6e6bc516-4698-4d87-9f4f-43b03dca2eab
t = range(0, stop=20, length=100)

# ╔═╡ ae0c7d9f-1861-4978-957e-9b869850c8d9
plot(scatter3d(
    x=cos.(t),
    y=sin.(t),
    z=t,
    mode="markers",
    marker=attr(
        size=12,
        color=t,                # set color to an array/list of desired values
        colorscale="Viridis",   # choose a colorscale
        opacity=0.8
    ),
), Layout(margin=attr(l=0, r=0, b=0, t=0)))

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
PlutoPlotly = "8e989ff0-3d88-8e9f-f020-2b208a939ff0"
RDatasets = "ce6b1742-4840-55fa-b093-852dadbb1d8b"

[compat]
CSV = "~0.10.4"
DataFrames = "~1.3.4"
PlutoPlotly = "~0.3.4"
RDatasets = "~0.7.7"
"""

# ╔═╡ 00000000-0000-0000-0000-000000000002
PLUTO_MANIFEST_TOML_CONTENTS = """
# This file is machine-generated - editing it directly is not advised

julia_version = "1.7.1"
manifest_format = "2.0"

[[deps.AbstractPlutoDingetjes]]
deps = ["Pkg"]
git-tree-sha1 = "8eaf9f1b4921132a4cff3f36a1d9ba923b14a481"
uuid = "6e696c72-6542-2067-7265-42206c756150"
version = "1.1.4"

[[deps.ArgTools]]
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"

[[deps.Artifacts]]
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"

[[deps.Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

[[deps.CSV]]
deps = ["CodecZlib", "Dates", "FilePathsBase", "InlineStrings", "Mmap", "Parsers", "PooledArrays", "SentinelArrays", "Tables", "Unicode", "WeakRefStrings"]
git-tree-sha1 = "873fb188a4b9d76549b81465b1f75c82aaf59238"
uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
version = "0.10.4"

[[deps.CategoricalArrays]]
deps = ["DataAPI", "Future", "Missings", "Printf", "Requires", "Statistics", "Unicode"]
git-tree-sha1 = "109664d3a6f2202b1225478335ea8fea3cd8706b"
uuid = "324d7699-5711-5eae-9e2f-1d82baa6b597"
version = "0.10.5"

[[deps.ChainRulesCore]]
deps = ["Compat", "LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "9950387274246d08af38f6eef8cb5480862a435f"
uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
version = "1.14.0"

[[deps.ChangesOfVariables]]
deps = ["ChainRulesCore", "LinearAlgebra", "Test"]
git-tree-sha1 = "1e315e3f4b0b7ce40feded39c73049692126cf53"
uuid = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0"
version = "0.1.3"

[[deps.CodecZlib]]
deps = ["TranscodingStreams", "Zlib_jll"]
git-tree-sha1 = "ded953804d019afa9a3f98981d99b33e3db7b6da"
uuid = "944b1d66-785c-5afd-91f1-9de20f533193"
version = "0.7.0"

[[deps.ColorSchemes]]
deps = ["ColorTypes", "ColorVectorSpace", "Colors", "FixedPointNumbers", "Random"]
git-tree-sha1 = "7297381ccb5df764549818d9a7d57e45f1057d30"
uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
version = "3.18.0"

[[deps.ColorTypes]]
deps = ["FixedPointNumbers", "Random"]
git-tree-sha1 = "a985dc37e357a3b22b260a5def99f3530fb415d3"
uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
version = "0.11.2"

[[deps.ColorVectorSpace]]
deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "SpecialFunctions", "Statistics", "TensorCore"]
git-tree-sha1 = "3f1f500312161f1ae067abe07d13b40f78f32e07"
uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4"
version = "0.9.8"

[[deps.Colors]]
deps = ["ColorTypes", "FixedPointNumbers", "Reexport"]
git-tree-sha1 = "417b0ed7b8b838aa6ca0a87aadf1bb9eb111ce40"
uuid = "5ae59095-9a9b-59fe-a467-6f913c188581"
version = "0.12.8"

[[deps.Compat]]
deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"]
git-tree-sha1 = "b153278a25dd42c65abbf4e62344f9d22e59191b"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "3.43.0"

[[deps.CompilerSupportLibraries_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"

[[deps.Crayons]]
git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15"
uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
version = "4.1.1"

[[deps.DataAPI]]
git-tree-sha1 = "fb5f5316dd3fd4c5e7c30a24d50643b73e37cd40"
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
version = "1.10.0"

[[deps.DataFrames]]
deps = ["Compat", "DataAPI", "Future", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrettyTables", "Printf", "REPL", "Reexport", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"]
git-tree-sha1 = "daa21eb85147f72e41f6352a57fccea377e310a9"
uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
version = "1.3.4"

[[deps.DataStructures]]
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "cc1a8e22627f33c789ab60b36a9132ac050bbf75"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.18.12"

[[deps.DataValueInterfaces]]
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
version = "1.0.0"

[[deps.Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"

[[deps.DelimitedFiles]]
deps = ["Mmap"]
uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab"

[[deps.Distributed]]
deps = ["Random", "Serialization", "Sockets"]
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"

[[deps.DocStringExtensions]]
deps = ["LibGit2"]
git-tree-sha1 = "b19534d1895d702889b219c382a6e18010797f0b"
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
version = "0.8.6"

[[deps.Downloads]]
deps = ["ArgTools", "LibCURL", "NetworkOptions"]
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"

[[deps.ExprTools]]
git-tree-sha1 = "56559bbef6ca5ea0c0818fa5c90320398a6fbf8d"
uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04"
version = "0.1.8"

[[deps.FileIO]]
deps = ["Pkg", "Requires", "UUIDs"]
git-tree-sha1 = "9267e5f50b0e12fdfd5a2455534345c4cf2c7f7a"
uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
version = "1.14.0"

[[deps.FilePathsBase]]
deps = ["Compat", "Dates", "Mmap", "Printf", "Test", "UUIDs"]
git-tree-sha1 = "129b104185df66e408edd6625d480b7f9e9823a0"
uuid = "48062228-2e41-5def-b9a4-89aafe57970f"
version = "0.9.18"

[[deps.FixedPointNumbers]]
deps = ["Statistics"]
git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc"
uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93"
version = "0.8.4"

[[deps.Formatting]]
deps = ["Printf"]
git-tree-sha1 = "8339d61043228fdd3eb658d86c926cb282ae72a8"
uuid = "59287772-0a20-5a39-b81b-1366585eb4c0"
version = "0.4.2"

[[deps.Future]]
deps = ["Random"]
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"

[[deps.Hyperscript]]
deps = ["Test"]
git-tree-sha1 = "8d511d5b81240fc8e6802386302675bdf47737b9"
uuid = "47d2ed2b-36de-50cf-bf87-49c2cf4b8b91"
version = "0.0.4"

[[deps.HypertextLiteral]]
deps = ["Tricks"]
git-tree-sha1 = "c47c5fa4c5308f27ccaac35504858d8914e102f9"
uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2"
version = "0.9.4"

[[deps.IOCapture]]
deps = ["Logging", "Random"]
git-tree-sha1 = "f7be53659ab06ddc986428d3a9dcc95f6fa6705a"
uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89"
version = "0.2.2"

[[deps.InlineStrings]]
deps = ["Parsers"]
git-tree-sha1 = "61feba885fac3a407465726d0c330b3055df897f"
uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48"
version = "1.1.2"

[[deps.InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"

[[deps.InverseFunctions]]
deps = ["Test"]
git-tree-sha1 = "336cc738f03e069ef2cac55a104eb823455dca75"
uuid = "3587e190-3f89-42d0-90ee-14403ec27112"
version = "0.1.4"

[[deps.InvertedIndices]]
git-tree-sha1 = "bee5f1ef5bf65df56bdd2e40447590b272a5471f"
uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f"
version = "1.1.0"

[[deps.IrrationalConstants]]
git-tree-sha1 = "7fd44fd4ff43fc60815f8e764c0f352b83c49151"
uuid = "92d709cd-6900-40b7-9082-c6be49f344b6"
version = "0.1.1"

[[deps.IteratorInterfaceExtensions]]
git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856"
uuid = "82899510-4779-5014-852e-03e436cf321d"
version = "1.0.0"

[[deps.JLLWrappers]]
deps = ["Preferences"]
git-tree-sha1 = "abc9885a7ca2052a736a600f7fa66209f96506e1"
uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210"
version = "1.4.1"

[[deps.JSON]]
deps = ["Dates", "Mmap", "Parsers", "Unicode"]
git-tree-sha1 = "3c837543ddb02250ef42f4738347454f95079d4e"
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
version = "0.21.3"

[[deps.LaTeXStrings]]
git-tree-sha1 = "f2355693d6778a178ade15952b7ac47a4ff97996"
uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
version = "1.3.0"

[[deps.LazyArtifacts]]
deps = ["Artifacts", "Pkg"]
uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3"

[[deps.LibCURL]]
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"

[[deps.LibCURL_jll]]
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"

[[deps.LibGit2]]
deps = ["Base64", "NetworkOptions", "Printf", "SHA"]
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"

[[deps.LibSSH2_jll]]
deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"

[[deps.Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"

[[deps.LinearAlgebra]]
deps = ["Libdl", "libblastrampoline_jll"]
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[[deps.LogExpFunctions]]
deps = ["ChainRulesCore", "ChangesOfVariables", "DocStringExtensions", "InverseFunctions", "IrrationalConstants", "LinearAlgebra"]
git-tree-sha1 = "09e4b894ce6a976c354a69041a04748180d43637"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.3.15"

[[deps.Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"

[[deps.Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"

[[deps.MbedTLS_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"

[[deps.Missings]]
deps = ["DataAPI"]
git-tree-sha1 = "bf210ce90b6c9eed32d25dbcae1ebc565df2687f"
uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
version = "1.0.2"

[[deps.Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"

[[deps.Mocking]]
deps = ["Compat", "ExprTools"]
git-tree-sha1 = "29714d0a7a8083bba8427a4fbfb00a540c681ce7"
uuid = "78c3b35d-d492-501b-9361-3d52fe80e533"
version = "0.7.3"

[[deps.MozillaCACerts_jll]]
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"

[[deps.NetworkOptions]]
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"

[[deps.OpenBLAS_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"

[[deps.OpenLibm_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "05823500-19ac-5b8b-9628-191a04bc5112"

[[deps.OpenSpecFun_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1"
uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e"
version = "0.5.5+0"

[[deps.OrderedCollections]]
git-tree-sha1 = "85f8e6578bf1f9ee0d11e7bb1b1456435479d47c"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.4.1"

[[deps.Parameters]]
deps = ["OrderedCollections", "UnPack"]
git-tree-sha1 = "34c0e9ad262e5f7fc75b10a9952ca7692cfc5fbe"
uuid = "d96e819e-fc66-5662-9728-84c9c7592b0a"
version = "0.12.3"

[[deps.Parsers]]
deps = ["Dates"]
git-tree-sha1 = "1285416549ccfcdf0c50d4997a94331e88d68413"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.3.1"

[[deps.Pkg]]
deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"

[[deps.PlotlyBase]]
deps = ["ColorSchemes", "Dates", "DelimitedFiles", "DocStringExtensions", "JSON", "LaTeXStrings", "Logging", "Parameters", "Pkg", "REPL", "Requires", "Statistics", "UUIDs"]
git-tree-sha1 = "180d744848ba316a3d0fdf4dbd34b77c7242963a"
uuid = "a03496cd-edff-5a9b-9e67-9cda94a718b5"
version = "0.8.18"

[[deps.PlutoPlotly]]
deps = ["AbstractPlutoDingetjes", "Dates", "HypertextLiteral", "InteractiveUtils", "LaTeXStrings", "Markdown", "PlotlyBase", "PlutoUI", "Reexport"]
git-tree-sha1 = "b470931aa2a8112c8b08e66ea096c6c62c60571e"
uuid = "8e989ff0-3d88-8e9f-f020-2b208a939ff0"
version = "0.3.4"

[[deps.PlutoUI]]
deps = ["AbstractPlutoDingetjes", "Base64", "ColorTypes", "Dates", "Hyperscript", "HypertextLiteral", "IOCapture", "InteractiveUtils", "JSON", "Logging", "Markdown", "Random", "Reexport", "UUIDs"]
git-tree-sha1 = "8d1f54886b9037091edf146b517989fc4a09efec"
uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
version = "0.7.39"

[[deps.PooledArrays]]
deps = ["DataAPI", "Future"]
git-tree-sha1 = "a6062fe4063cdafe78f4a0a81cfffb89721b30e7"
uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720"
version = "1.4.2"

[[deps.Preferences]]
deps = ["TOML"]
git-tree-sha1 = "47e5f437cc0e7ef2ce8406ce1e7e24d44915f88d"
uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.3.0"

[[deps.PrettyTables]]
deps = ["Crayons", "Formatting", "Markdown", "Reexport", "Tables"]
git-tree-sha1 = "dfb54c4e414caa595a1f2ed759b160f5a3ddcba5"
uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
version = "1.3.1"

[[deps.Printf]]
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"

[[deps.RData]]
deps = ["CategoricalArrays", "CodecZlib", "DataFrames", "Dates", "FileIO", "Requires", "TimeZones", "Unicode"]
git-tree-sha1 = "19e47a495dfb7240eb44dc6971d660f7e4244a72"
uuid = "df47a6cb-8c03-5eed-afd8-b6050d6c41da"
version = "0.8.3"

[[deps.RDatasets]]
deps = ["CSV", "CodecZlib", "DataFrames", "FileIO", "Printf", "RData", "Reexport"]
git-tree-sha1 = "2720e6f6afb3e562ccb70a6b62f8f308ff810333"
uuid = "ce6b1742-4840-55fa-b093-852dadbb1d8b"
version = "0.7.7"

[[deps.REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"

[[deps.Random]]
deps = ["SHA", "Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[[deps.RecipesBase]]
git-tree-sha1 = "6bf3f380ff52ce0832ddd3a2a7b9538ed1bcca7d"
uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
version = "1.2.1"

[[deps.Reexport]]
git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b"
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
version = "1.2.2"

[[deps.Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7"
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
version = "1.3.0"

[[deps.SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"

[[deps.SentinelArrays]]
deps = ["Dates", "Random"]
git-tree-sha1 = "6a2f7d70512d205ca8c7ee31bfa9f142fe74310c"
uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c"
version = "1.3.12"

[[deps.Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"

[[deps.SharedArrays]]
deps = ["Distributed", "Mmap", "Random", "Serialization"]
uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383"

[[deps.Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"

[[deps.SortingAlgorithms]]
deps = ["DataStructures"]
git-tree-sha1 = "b3363d7460f7d098ca0912c69b082f75625d7508"
uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c"
version = "1.0.1"

[[deps.SparseArrays]]
deps = ["LinearAlgebra", "Random"]
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[[deps.SpecialFunctions]]
deps = ["ChainRulesCore", "IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"]
git-tree-sha1 = "bc40f042cfcc56230f781d92db71f0e21496dffd"
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
version = "2.1.5"

[[deps.Statistics]]
deps = ["LinearAlgebra", "SparseArrays"]
uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[[deps.TOML]]
deps = ["Dates"]
uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"

[[deps.TableTraits]]
deps = ["IteratorInterfaceExtensions"]
git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39"
uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
version = "1.0.1"

[[deps.Tables]]
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "OrderedCollections", "TableTraits", "Test"]
git-tree-sha1 = "5ce79ce186cc678bbb5c5681ca3379d1ddae11a1"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.7.0"

[[deps.Tar]]
deps = ["ArgTools", "SHA"]
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"

[[deps.TensorCore]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "1feb45f88d133a655e001435632f019a9a1bcdb6"
uuid = "62fd8b95-f654-4bbd-a8a5-9c27f68ccd50"
version = "0.1.1"

[[deps.Test]]
deps = ["InteractiveUtils", "Logging", "Random", "Serialization"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[[deps.TimeZones]]
deps = ["Dates", "Downloads", "InlineStrings", "LazyArtifacts", "Mocking", "Printf", "RecipesBase", "Serialization", "Unicode"]
git-tree-sha1 = "0a359b0ee27e4fbc90d9b3da1f48ddc6f98a0c9e"
uuid = "f269a46b-ccf7-5d73-abea-4c690281aa53"
version = "1.7.3"

[[deps.TranscodingStreams]]
deps = ["Random", "Test"]
git-tree-sha1 = "216b95ea110b5972db65aa90f88d8d89dcb8851c"
uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa"
version = "0.9.6"

[[deps.Tricks]]
git-tree-sha1 = "6bac775f2d42a611cdfcd1fb217ee719630c4175"
uuid = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775"
version = "0.1.6"

[[deps.UUIDs]]
deps = ["Random", "SHA"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[[deps.UnPack]]
git-tree-sha1 = "387c1f73762231e86e0c9c5443ce3b4a0a9a0c2b"
uuid = "3a884ed6-31ef-47d7-9d2a-63182c4928ed"
version = "1.0.2"

[[deps.Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"

[[deps.WeakRefStrings]]
deps = ["DataAPI", "InlineStrings", "Parsers"]
git-tree-sha1 = "b1be2855ed9ed8eac54e5caff2afcdb442d52c23"
uuid = "ea10d353-3f73-51f8-a26c-33c1cb351aa5"
version = "1.4.2"

[[deps.Zlib_jll]]
deps = ["Libdl"]
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"

[[deps.libblastrampoline_jll]]
deps = ["Artifacts", "Libdl", "OpenBLAS_jll"]
uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"

[[deps.nghttp2_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"

[[deps.p7zip_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
"""

# ╔═╡ Cell order:
# ╠═6f229530-dc29-11ec-338a-0d435ffc6c7e
# ╠═24d1040d-51b6-4674-b2c7-bb63f080ab02
# ╟─bafe1b78-bf38-4e6e-b5f2-4057138f04ae
# ╟─e8fa739b-2e54-4ea0-878a-bc0f6b6a9f08
# ╠═97db89cc-4416-4b78-b466-e9612f7962a6
# ╠═9df1faa3-6bc8-4930-b8fb-94771ba5ab63
# ╠═ddc5f2c7-2b98-417a-97ce-69c7b27cc848
# ╠═6e6bc516-4698-4d87-9f4f-43b03dca2eab
# ╠═ae0c7d9f-1861-4978-957e-9b869850c8d9
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002


text:
# Taken from #380
# added during development for JuliaRobotics/IncrementalInference.jl#1051

using Test
using RoME
using Statistics

##

@testset "test inflation is working via distance" begin

##

fg = initfg()
# getSolverParams(fg).inflation = 50.0

N = 100

addVariable!(fg, :x0, ContinuousEuclid{2})
addVariable!(fg, :x1, ContinuousEuclid{2})

X0_ = zeros(2,N)
X0_[1,:] .+= 1000.0
initManual!(fg, :x0, X0_)

addFactor!(fg, [:x0;:x1], EuclidDistance(Normal(100.0, 1.0)))

pts = approxConv(fg, :x0, :x1)

##
# does this give a "donut ring" at 1000?

res = 99999*ones(100)

for i in 1:N
  res[i] = calcFactorResidual(fg, :x0x1f1, [100.0], [1000.0;0.0], pts[:,i])[1]
end

@test 0.9*N < sum(abs.(res) .< 5)

## new test trying to force inflation error

X1_ = randn(2,N)
X1_[1,:] .+= 1100.0
initManual!(fg, :x1, X1_)

##

IIF._getCCW(fg, :x0x1f1).inflation = 50.0
pts = approxConv(fg, :x0x1f1, :x1)

initManual!(fg, :x1, pts)

pts = approxConv(fg, :x0x1f1, :x1)

##
# does this give a "donut ring" at 1000?

res = 99999*ones(100)

for i in 1:N
  res[i] = calcFactorResidual(fg, :x0x1f1, [100.0], [1000.0;0.0], pts[:,i])[1]
end

@test 0.9*N < sum(abs.(res) .< 5)

##

# using RoMEPlotting
# Gadfly.set_default_plot_size(25cm,20cm)

# ##

# # pts = getBelief(fg, :x1) |> getPoints
# plotKDE(manikde!(pts, ContinuousEuclid{2}))

##

end

@testset "test inflation on range solve" begin

##

N = 100
fg = initfg()
fg.solverParams.inflation = 10.0 # super size the inflation to force wide coverage

addVariable!(fg, :x1, ContinuousEuclid{2})
addVariable!(fg, :l1, ContinuousEuclid{2})

addFactor!(fg, [:l1], Prior(MvNormal([-1000.0,0], [0.1, 0.1])))
addFactor!(fg, [:x1; :l1], EuclidDistance(Normal(100.0, 1.0)))

pts = zeros(2,100)
pts[1,:] .-= 900
initManual!(fg, :x1, pts)

##

tree, _, = solveGraph!(fg);

##

pts = getBelief(fg, :x1) |> getPoints

@test 0.9*N < sum( -1150 .< pts[1,:] .< -850)
@test 0.9*N < sum( -150 .< pts[2,:] .< 150)

pts_ = [norm(pts[:,i] - [-1000;0]) for i in 1:N]

@test 0.9*N < sum(80 .< pts_ .< 120)

# must still test spread

@test 0.2*N < sum(-1150 .< pts[1,:] .< -1000)
@test 0.2*N < sum(-1000 .< pts[1,:] .< -850)
@test 0.2*N < sum(-150 .< pts[2,:] .< 0)
@test 0.2*N < sum(0 .< pts[2,:] .< 150)

##

# pl = plotKDE(fg, ls(fg))

##

end

@testset "test bearing range with inflation, #380, IIF #1051" begin

##

fg = initfg()

getSolverParams(fg).inflation = 3.0

pr_noise = [0.01, 0.01, 0.001]
od_noise = [0.2;0.2;0.2]
σ_bearing = 0.008
σ_range = 0.01

addVariable!(fg, :x0, Pose2)
prpo = MvNormal([0,0,-pi], pr_noise)
addFactor!(fg, [:x0], PriorPose2(MvNormal(rand(prpo), pr_noise)))

addVariable!(fg, :l1, Point2, tags=[:LANDMARK])
addVariable!(fg, :l2, Point2, tags=[:LANDMARK])
p2br = Pose2Point2BearingRange(Normal(pi/4 + rand(Normal(0,σ_bearing)), σ_bearing),
                                Normal(sqrt(2) + rand(Normal(0,σ_range)), σ_range))
addFactor!(fg, [:x0; :l1], p2br)

addVariable!(fg, :x1, Pose2)
pp = MvNormal([1.0,0,0], od_noise)
addFactor!(fg, [:x0,:x1], Pose2Pose2(MvNormal(rand(pp), od_noise)))

p2br = Pose2Point2BearingRange(Normal(pi/2 + rand(Normal(0,σ_bearing)), σ_bearing),
                                Normal(1 + rand(Normal(0,σ_range)), σ_range))
addFactor!(fg, [:x1; :l1], p2br)

p2br = Pose2Point2BearingRange(Normal(-pi/2 + rand(Normal(0,σ_bearing)), σ_bearing),
                                Normal(1 + rand(Normal(0,σ_range)), σ_range))
addFactor!(fg, [:x1; :l2], p2br)

addVariable!(fg, :x2, Pose2)
pp = MvNormal([1.0,0,0], od_noise)
addFactor!(fg, [:x1,:x2], Pose2Pose2(MvNormal(rand(pp), od_noise)))

p2br = Pose2Point2BearingRange(Normal(3pi/4 + rand(Normal(0,σ_bearing)), σ_bearing),
                                Normal(sqrt(2) + rand(Normal(0,σ_range)), σ_range))
addFactor!(fg, [:x2; :l1], p2br)

p2br = Pose2Point2BearingRange(Normal(-3pi/4 + rand(Normal(0,σ_bearing)), σ_bearing),
                                Normal(sqrt(2) + rand(Normal(0,σ_range)), σ_range))
addFactor!(fg, [:x2; :l2], p2br)

##

# nonparametric solution
solveGraph!(fg);
IIF.solveFactorGraphParametric!(fg)

##

@show getPPE(fg, :x2, :parametric).suggested
@show getPPE(fg, :x2, :default).suggested

test_err = getPPE(fg, :x2, :default).suggested - getPPE(fg, :x2, :parametric).suggested
# arg, workaround until #244
theta = (getBelief(fg, :x2, :default) |> getPoints)[3,:] .+ pi
theta .= TU.wrapRad.(theta)
@show theta_ = Statistics.mean(theta)
@show theta_ref = TU.wrapRad(getPPE(fg, :x2, :parametric).suggested[3] + pi)
test_err[3] = theta_ref - theta_
@show test_err .= abs.(test_err)

@test isapprox(test_err[1], 0, atol=0.5)
@test isapprox(test_err[2], 0, atol=0.5)
@test isapprox(test_err[3], 0, atol=0.5)

##

end

##

# using RoMEPlotting
# Gadfly.set_default_plot_size(25cm,20cm)

# ##

# pl1 = plotSLAM2D(fg, solveKey=:default, drawPoints=true, drawEllipse=true, drawContour=false, xmin=-2.5,xmax=0,ymin=-1.5,ymax=1.5)
# pl2 = plotSLAM2D(fg, solveKey=:parametric, drawPoints=false, drawContour=false, xmin=-2.5,xmax=0,ymin=-1.5,ymax=1.5)
# vstack(pl1, pl2)

##

# plotPose(fg, :x2)

##


text:
function mm_spec_kj5_dimspec()::MPCCDimSpec
    dimspec = MPCCDimSpec(3, 1, 2, 0, 2, 1, 0)
    return dimspec
end

function mm_spec_kj5_defn(x, pr, ps)

    f = x[1] + x[2] - (1-pr[1]) * x[3]

    ce = Vector{Num}()

    ci = Vector{Num}(undef, 2)
    ci[1] = 4x[1] - x[3]
    ci[2] = 4x[2] - x[3]

    F = Matrix{Num}(undef, 2, 1)
    F[1,1] = x[1]
    F[2,1] = x[2]

    return MPCCDefinition(f, ce, ci, F)
end

function mm_spec_kj5_nzmask()::MPCCModelNZMask
    nz_mask = MPCCModelNZMask(
        # ce
        [],
        # ci
        [   Set{Int64}([1, 2]),
            Set{Int64}([1]) ],
        # F
        [
            # F1
            [   Set{Int64}([1]) ],
            # F2
            [   Set{Int64}([2]) ]
        ] )
    return nz_mask
end

function mm_spec_kj5_testvectors()
    return Vector{MPCCModelTestVector}(undef, 0)
end

function mm_spec_kj5_knownsols()

    function local_kj5_knownsol(pr::Vector{R}, ps::Vector{Int64}) where {R <: Real}
        @assert ( 1 == length(pr) && 0 == length(ps) )

        t = pr[1]
        if ( t < 0 || t > 1)
            error("t out of range, must be in [0,1]")
        end

        x_sol = [0, 0, 0]
        f_sol = 0

        return (x_sol, f_sol)
    end

    return [ local_kj5_knownsol ]
end


text:
# Copyright 2018 IBM Corp.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

module ConceptPROV
export presentation_to_prov

using Serd
using Catlab

using ...Doctrine, ...Ontology
using ..ConceptRDF

const R = RDF.Resource

""" Convert concepts into hierarchy of PROV-O classes.

Type concepts are not really OWL classes and function concepts are not even
close to OWL classes (nor are they particularly close to OWL properties).
However, for the sake of Semantic Web interoperability, we encode type concepts
as a hierarchy of classes below PROV's Entity and function concepts as a
hierarchy of classes below PROV's Activity.

In the primary export function (`presentation_to_rdf`), concepts are represented
as individuals, not classes, which is necessary because they have properties.
Thus, when used in conjunction with this function, concepts are simultaneously
classes and individuals. This is prohibited in OWL 1, but permitted in OWL 2 DL,
where is it called "punning".

References:
- https://www.w3.org/TR/owl2-new-features/#F12:_Punning
- https://www.w3.org/TR/prov-o/
"""
function presentation_to_prov(pres::Presentation, prefix::RDF.Prefix)
  stmts = RDF.Statement[
    RDF.Prefix("rdf"), RDF.Prefix("rdfs"), RDF.Prefix("owl"),
    RDF.Prefix("prov"),
    RDF.Prefix("monocl", "https://www.datascienceontology.org/ns/monocl/"),
    prefix
  ]

  # Create mapping from concept node to all its super concept nodes.
  super_map = Dict{RDF.Node,Vector{RDF.Node}}()
  for sub in [generators(pres, Monocl.SubOb); generators(pres, Monocl.SubHom)]
    push!(get!(super_map, generator_rdf_node(dom(sub), prefix), RDF.Node[]),
          generator_rdf_node(codom(sub), prefix))
  end

  # Generate RDF triples.
  for gen in [generators(pres, Monocl.Ob); generators(pres, Monocl.Hom)]
    node = generator_rdf_node(gen, prefix)
    super_nodes = get(super_map, node) do
      [ gen isa Monocl.Ob ? R("prov","Entity") : R("prov","Activity") ]
    end
    push!(stmts, RDF.Triple(node, R("rdf","type"), R("owl","Class")))
    for super_node in super_nodes
      push!(stmts, RDF.Triple(node, R("rdfs","subClassOf"), super_node))
    end
  end
  stmts
end

end

max_stars_repo_name: cclauss/semanticflowgraph

max_issues_repo_name: cclauss/semanticflowgraph

max_forks_repo_name: cclauss/semanticflowgraph


text:
module MaxHelpingHandHintDecal

using ..Ahorn, Maple

@mapdef Entity "MaxHelpingHand/HintDecal" HintDecal(x::Integer, y::Integer, texture::String="1-forsakencity/sign_you_can_go_up", scaleX::Number=1.0, scaleY::Number=1.0, foreground::Bool=false)

const placements = Ahorn.PlacementDict(
    "Hint Decal (max480's Helping Hand)" => Ahorn.EntityPlacement(
        HintDecal
    ),
    "Custom Bird Tutorial (Show Hints) (max480's Helping Hand)" => Ahorn.EntityPlacement(
        Maple.EverestCustomBird,
        "rectangle",
        Dict{String,Any}(
            "info" => "MAXHELPINGHAND_SHOWHINTS",
            "controls" => "ShowHints"
        )
    )
)

# This code handling decal selection, rendering and properties window was borrowed from a Ahorn plugin by lilybeevee

function Ahorn.selection(entity::HintDecal)
    x, y = Ahorn.position(entity)
    sprite = "decals/$(get(entity, "texture", ""))"
    scaleX = get(entity, "scaleX", 1.0)
    scaleY = get(entity, "scaleY", 1.0)

    return Ahorn.getSpriteRectangle(sprite, x, y, sx=scaleX, sy=scaleY)
end

function Ahorn.render(ctx::Ahorn.Cairo.CairoContext, entity::HintDecal, room::Maple.Room)
    sprite = "decals/$(get(entity, "texture", ""))"
    scaleX = get(entity, "scaleX", 1.0)
    scaleY = get(entity, "scaleY", 1.0)

    Ahorn.drawSprite(ctx, sprite, 0, 0, sx=scaleX, sy=scaleY)
end

animationRegex = r"\D+0*?$"
filterAnimations(s::String) = occursin(animationRegex, s)

function decalTextures()
    Ahorn.loadChangedExternalSprites!()
    textures = Ahorn.spritesToDecalTextures(Ahorn.getAtlas("Gameplay"))
    filter!(filterAnimations, textures)
    sort!(textures)
    return textures
end

Ahorn.editingOptions(entity::HintDecal) = Dict{String, Any}(
    "texture" => decalTextures()
)

end

max_stars_repo_name: Kitty-Cats/MaxHelpingHand

max_issues_repo_name: Kitty-Cats/MaxHelpingHand

max_forks_repo_name: Kitty-Cats/MaxHelpingHand