text:
# Test basic methods
@testset "Basics" begin
    # initialize model and point variable
    m = InfiniteModel()
    @independent_parameter(m, a in [0, 1])
    @independent_parameter(m, b[1:2] in [0, 1])
    @dependent_parameters(m, c[1:2] in [0, 1])
    @infinite_variable(m, ivref(a, b, c))
    num = Float64(0)
    info = VariableInfo(false, num, false, num, false, num, false, num, false, false)
    new_info = VariableInfo(true, 0., true, 0., true, 0., true, 0., true, false)
    var = PointVariable(info, ivref, [0., 0., 1., 1., 0.])
    object = VariableData(var, "var")
    idx = PointVariableIndex(1)
    vref = PointVariableRef(m, idx)
    gvref = GeneralVariableRef(m, 1, PointVariableIndex)
    # JuMP.owner_model
    @testset "JuMP.owner_model" begin
        @test owner_model(vref) === m
        @test owner_model(gvref) === m
    end
    # JuMP.index
    @testset "JuMP.index" begin
        @test index(vref) == idx
        @test index(gvref) == idx
    end
    # dispatch_variable_ref
    @testset "dispatch_variable_ref" begin
        @test dispatch_variable_ref(m, idx) == vref
        @test dispatch_variable_ref(gvref) == vref
    end
    # _add_data_object
    @testset "_add_data_object" begin
        @test InfiniteOpt._add_data_object(m, object) == idx
    end
    # _data_dictionary
    @testset "_data_dictionary" begin
        @test InfiniteOpt._data_dictionary(m, PointVariable) === m.point_vars
        @test InfiniteOpt._data_dictionary(vref) === m.point_vars
        @test InfiniteOpt._data_dictionary(gvref) === m.point_vars
    end
    # JuMP.is_valid
    @testset "JuMP.is_valid" begin
        @test is_valid(m, vref)
        @test is_valid(m, gvref)
    end
    # _data_object
    @testset "_data_object" begin
        @test InfiniteOpt._data_object(vref) === object
        @test InfiniteOpt._data_object(gvref) === object
    end
    # _core_variable_object
    @testset "_core_variable_object" begin
        @test InfiniteOpt._core_variable_object(vref) === var
        @test InfiniteOpt._core_variable_object(gvref) === var
    end
    # _set_core_variable_object
    @testset "_set_core_variable_object" begin
        @test InfiniteOpt._set_core_variable_object(vref, var) isa Nothing
    end
    @testset "_variable_info" begin
        @test InfiniteOpt._variable_info(vref) == info
    end
    # _update_variable_info
    @testset "_update_variable_info" begin
        @test isa(InfiniteOpt._update_variable_info(vref, new_info), Nothing)
        @test InfiniteOpt._variable_info(vref) == new_info
    end
    # _measure_dependencies
    @testset "_measure_dependencies" begin
        @test InfiniteOpt._measure_dependencies(vref) == MeasureIndex[]
        @test InfiniteOpt._measure_dependencies(gvref) == MeasureIndex[]
    end
    # _constraint_dependencies
    @testset "_constraint_dependencies" begin
        @test InfiniteOpt._constraint_dependencies(vref) == ConstraintIndex[]
        @test InfiniteOpt._constraint_dependencies(gvref) == ConstraintIndex[]
    end
    # JuMP.name
    @testset "JuMP.name" begin
        @test name(vref) == "var"
        @test name(gvref) == "var"
    end
    # infinite_variable_ref
    @testset "infinite_variable_ref" begin
        @test infinite_variable_ref(vref) == ivref
        @test infinite_variable_ref(gvref) == ivref
    end
    # raw_parameter_values
    @testset "raw_parameter_values" begin
        @test raw_parameter_values(vref) == Float64[0., 0., 1., 1., 0.]
        @test raw_parameter_values(gvref) == Float64[0., 0., 1., 1., 0.]
    end
    # parameter_values
    @testset "parameter_values" begin
        @test parameter_values(vref) == (Float64(0), Float64[0, 1], Float64[1, 0])
        @test parameter_values(gvref) == (Float64(0), Float64[0, 1], Float64[1, 0])
    end
    # _update_variable_param_values
    @testset "_update_variable_param_values" begin
        @test isa(InfiniteOpt._update_variable_param_values(vref, ones(5)),
                  Nothing)
        @test raw_parameter_values(vref) == ones(5)
        @test isa(InfiniteOpt._update_variable_param_values(vref, [0., 0., 1., 1., 0.]),
                  Nothing)
    end
    # test parameter_refs
    @testset "parameter_refs" begin
        @test parameter_refs(vref) == ()
        @test parameter_refs(gvref) == ()
    end
    # JuMP.set_name
    @testset "JuMP.set_name" begin
        # test normal
        @test isa(set_name(vref, "new"), Nothing)
        @test name(vref) == "new"
        # test default
        @test isa(set_name(gvref, "a"), Nothing)
        @test name(vref) == "a"
    end
    # _make_variable_ref
    @testset "_make_variable_ref" begin
        @test InfiniteOpt._make_variable_ref(m, idx) == gvref
    end
    # _var_name_dict
    @testset "_var_name_dict" begin
        @test InfiniteOpt._var_name_dict(m) isa Nothing
    end
    # _update_var_name_dict
    @testset "_update_var_name_dict" begin
        m.name_to_var = Dict{String, ObjectIndex}()
        dict = InfiniteOpt._data_dictionary(vref)
        @test InfiniteOpt._update_var_name_dict(m, dict) isa Nothing
        @test InfiniteOpt._var_name_dict(m) == Dict(name(vref) => idx)
        m.name_to_var = nothing
    end
    # parameter_by_name
    @testset "JuMP.variable_by_name" begin
        # test normal
        @test variable_by_name(m, "a") == gvref
        @test variable_by_name(m, "test") isa Nothing
        # prepare variable with same name
        idx2 = PointVariableIndex(2)
        @test InfiniteOpt._add_data_object(m, object) == idx2
        vref2 = PointVariableRef(m, idx2)
        @test set_name(vref2, "a") isa Nothing
        # test multiple name error
        @test_throws ErrorException variable_by_name(m, "a")
    end
    # _delete_data_object
    @testset "_delete_data_object" begin
        @test InfiniteOpt._delete_data_object(vref) isa Nothing
        @test length(InfiniteOpt._data_dictionary(vref)) == 1
        @test !is_valid(m, vref)
    end
end

# Test variable definition methods
@testset "Definition" begin
    # initialize model and infinite variables
    m = InfiniteModel()
    @independent_parameter(m, pref in [0, 1])
    @independent_parameter(m, pref2 in [0, 1])
    @dependent_parameters(m, prefs[1:2] in [0, 1])
    num = Float64(0)
    info = VariableInfo(false, num, false, num, false, num, false, num, false, false)
    info2 = VariableInfo(true, num, true, num, true, num, true, num, true, false)
    info3 = VariableInfo(true, num, true, num, true, num, true, num, false, true)
    @infinite_variable(m, ivref(pref, pref2))
    @infinite_variable(m, ivref2(pref, prefs))
    divref = dispatch_variable_ref(ivref)
    divref2 = dispatch_variable_ref(ivref2)
    # _check_tuple_shape
    @testset "_check_tuple_shape" begin
        # test normal
        @test isa(InfiniteOpt._check_tuple_shape(error, divref, IC.VectorTuple{Float64}(0.5, 0.5)),
                  Nothing)
        # prepare param value tuple
        tuple = IC.VectorTuple{Float64}(0.5, [0.5, 0.5])
        # test normal with array
        @test isa(InfiniteOpt._check_tuple_shape(error, divref2, tuple), Nothing)
        # test for errors in shape
        @test_throws ErrorException InfiniteOpt._check_tuple_shape(error, divref,
                                                              IC.VectorTuple{Float64}(0.5,))
        @test_throws ErrorException InfiniteOpt._check_tuple_shape(error, divref,
                                                        IC.VectorTuple{Float64}(0.5, [0.5]))
        @test_throws ErrorException InfiniteOpt._check_tuple_shape(error, divref2,
                                                          IC.VectorTuple{Float64}(0.5, 0.5))
        tuple = IC.VectorTuple{Float64}(0.5, [0.5, 0.5, 0.5])
        @test_throws ErrorException InfiniteOpt._check_tuple_shape(error, divref2,
                                                                   tuple)
    end
    # _check_element_support
    @testset "_check_element_support (IndependentParameterRef)" begin
        # test normal
        ps = [dispatch_variable_ref(pref)]
        vals = Float64[0, 2]
        @test InfiniteOpt._check_element_support(error, ps, vals, 1) == 2
        # test error
        ps = [dispatch_variable_ref(pref), dispatch_variable_ref(pref2)]
        @test_throws ErrorException InfiniteOpt._check_element_support(error, ps, vals, 1)
    end
    # _check_element_support
    @testset "_check_element_support (DependentParameterRef)" begin
        # test normal
        ps = dispatch_variable_ref.(prefs)
        vals = Float64[0, 1, 0, 1]
        @test InfiniteOpt._check_element_support(error, ps, vals, 3) == 5
        # test error
        vals = Float64[0, 0, 2, 1]
        @test_throws ErrorException InfiniteOpt._check_element_support(error, ps, vals, 3)
    end
    # _check_tuple_values
    @testset "_check_tuple_values" begin
        # test normal
        @test isa(InfiniteOpt._check_tuple_values(error, divref, Float64[0.5, 0.5]),
                  Nothing)
        # test normal with array
        vals = Float64[0, 0.5, 1]
        @test isa(InfiniteOpt._check_tuple_values(error, divref2, vals), Nothing)
        # test for out of bound errors
        @test_throws ErrorException InfiniteOpt._check_tuple_values(error, divref,
                                                                    Float64[0, 2])
        vals = Float64[0, 2, 1]
        @test_throws ErrorException InfiniteOpt._check_tuple_values(error, divref2,
                                                                    vals)
    end
    # _update_point_info
    @testset "_update_point_info" begin
        basic_func = (a::Vector) -> 1
        # prepare info for test
        new_info = VariableInfo(true, 0., true, 0., false, 0., false, basic_func,
                                 true, false)
        InfiniteOpt._update_variable_info(divref, new_info)
        expected = VariableInfo{Float64, Float64, Float64, Float64}(true, 0.,
                                true, 0., false, 0., false, 0., true, false)
        # test with current info
        @test InfiniteOpt._update_point_info(info, divref, Float64[0, 0]) == expected
        # prepare info for test
        new_info = VariableInfo(false, 0., false, 0., true, 0., true, basic_func,
                                false, true)
        InfiniteOpt._update_variable_info(divref, new_info)
        expected = VariableInfo{Float64, Float64, Float64, Float64}(false, 0.,
                                false, 0., true, 0., true, 1, false, true)
        # test with current info
        @test InfiniteOpt._update_point_info(info, divref, Float64[0, 0]) == expected
        # prepare info for test
        curr_info = VariableInfo(true, 0., true, 0., false, 0., true, 0.,
                                 true, false)
        # test with current info
        @test InfiniteOpt._update_point_info(curr_info, divref, Float64[0, 0]) == curr_info
        # undo info changes
        basic_func = (a::Vector) -> NaN
        old_info = VariableInfo(false, NaN, false, NaN, false, NaN, false, basic_func,
                            false, false)
        InfiniteOpt._update_variable_info(divref, old_info)
        # test with user defined start function
        @test set_start_value_function(divref, (a, b) -> a + b) isa Nothing
        expected = VariableInfo{Float64, Float64, Float64, Float64}(false, 0.,
                                false, 0., false, 0., true, 3, false, false)
        @test InfiniteOpt._update_point_info(info, divref, Float64[1, 2]) == expected
        @test reset_start_value_function(divref) isa Nothing
    end
    # test _make_variable
    @testset "_make_variable" begin
        # test for all errors
        @test_throws ErrorException InfiniteOpt._make_variable(error, info,
                                              Point, parameter_refs = pref)
        @test_throws ErrorException InfiniteOpt._make_variable(error, info,
                                                               Point)
        @test_throws ErrorException InfiniteOpt._make_variable(error, info,
                                      Point, infinite_variable_ref = ivref)
        @test_throws ErrorException InfiniteOpt._make_variable(error, info,
                                               Point, parameter_values = 3)
        @test_throws ErrorException InfiniteOpt._make_variable(error, info,
                                               Point, parameter_values = 3,
                                               infinite_variable_ref = pref)
        @test_throws ErrorException InfiniteOpt._make_variable(error, info,
                                               Point, parameter_values = (1, 1, 1),
                                               infinite_variable_ref = ivref)
        @test_throws ErrorException InfiniteOpt._make_variable(error, info,
                                               Point, parameter_values = (1, 2),
                                               infinite_variable_ref = ivref)
        # test a variety of builds
        @test InfiniteOpt._make_variable(error, info, Point, infinite_variable_ref = ivref,
                   parameter_values = (0.5, 0.5)).infinite_variable_ref == ivref
        @test InfiniteOpt._make_variable(error, info, Point, infinite_variable_ref = ivref,
                   parameter_values = (0.5, 0.5)).parameter_values == [0.5, 0.5]
        @test InfiniteOpt._make_variable(error, info, Point, infinite_variable_ref = ivref,
                             parameter_values = (0.5, 0.5)).info == info
        @test_throws ErrorException InfiniteOpt._make_variable(error, info, Point,
                                                  infinite_variable_ref = ivref,
                                                  parameter_values = (0.5, 2))
        @test InfiniteOpt._make_variable(error, info, Point, infinite_variable_ref = ivref2,
               parameter_values = (0.5, [0, 0])).infinite_variable_ref == ivref2
        @test InfiniteOpt._make_variable(error, info, Point, infinite_variable_ref = ivref2,
                     parameter_values = (0.5, [0, 0])).parameter_values == [0.5, 0, 0]
        @test_throws ErrorException InfiniteOpt._make_variable(error, info, Point,
                                            infinite_variable_ref = ivref2,
                                            parameter_values = (0.5, [0, 0, 0]))
    end
    # build_variable
    @testset "JuMP.build_variable" begin
        # test for all errors
        @test_throws ErrorException build_variable(error, info, Infinite,
                                                  infinite_variable_ref = ivref)
        @test_throws ErrorException build_variable(error, info, Infinite,
                                                   parameter_values = 3)
        @test_throws ErrorException build_variable(error, info, Point)
        @test_throws ErrorException build_variable(error, info, Point,
                                                  infinite_variable_ref = ivref)
        @test_throws ErrorException build_variable(error, info, Point,
                                                   parameter_values = 3)
        # test a variety of builds
        @test build_variable(error, info, Point, infinite_variable_ref = ivref,
                   parameter_values = (0.5, 0.5)).infinite_variable_ref == ivref
        @test build_variable(error, info, Point, infinite_variable_ref = ivref,
                   parameter_values = (0.5, 0.5)).parameter_values == [0.5, 0.5]
        @test build_variable(error, info, Point, infinite_variable_ref = ivref,
                             parameter_values = (0.5, 0.5)).info == info
        @test_throws ErrorException build_variable(error, info, Point,
                                                  infinite_variable_ref = ivref,
                                                  parameter_values = (0.5, 2))
        @test build_variable(error, info, Point, infinite_variable_ref = ivref2,
               parameter_values = (0.5, [0, 0])).infinite_variable_ref == ivref2
        @test build_variable(error, info, Point, infinite_variable_ref = ivref2,
                     parameter_values = (0.5, [0, 0])).parameter_values == [0.5, 0, 0]
        @test_throws ErrorException build_variable(error, info, Point,
                                            infinite_variable_ref = ivref2,
                                            parameter_values = (0.5, [0, 0, 0]))
    end
    # _add_point_support
    @testset "_add_point_support (IndependentParameterRef)" begin
        # test normal
        ps = [dispatch_variable_ref(pref)]
        vals = Float64[0, 2]
        @test InfiniteOpt._add_point_support(ps, vals, 1) == 2
        @test supports(pref, label = UserDefined) == [0]
        @test delete_supports(pref) isa Nothing
        # test other
        ps = [dispatch_variable_ref(pref), dispatch_variable_ref(pref2)]
        vals = Float64[0, 1]
        @test InfiniteOpt._add_point_support(ps, vals, 1) == 3
        @test supports(pref, label = UserDefined) == [0]
        @test supports(pref2, label = UserDefined) == [1]
        @test delete_supports(pref) isa Nothing
        @test delete_supports(pref2) isa Nothing
    end
    # _add_point_support
    @testset "_add_point_support (DependentParameterRef)" begin
        # test normal
        ps = dispatch_variable_ref.(prefs)
        vals = Float64[0, 0]
        @test InfiniteOpt._add_point_support(ps, vals, 1) == 3
        @test supports(prefs, label = UserDefined) == zeros(2, 1)
        @test delete_supports(prefs) isa Nothing
    end
    # _update_param_supports
    @testset "_update_param_supports" begin
        # test normal
        @test isa(InfiniteOpt._update_param_supports(divref, Float64[0.5, 1]),
                  Nothing)
        @test supports(pref) == [0.5]
        @test supports(pref2) == [1]
        # prepare array tuple
        tuple = IC.VectorTuple{Float64}(0.5, [0, 1])
        # test normal with array
        @test isa(InfiniteOpt._update_param_supports(divref2, Float64[0.5, 0, 1]),
                  Nothing)
        @test supports(pref) == [0.5]
        @test supports(prefs[1]) == [0]
        @test supports(prefs[2]) == [1]
        @test delete_supports(pref) isa Nothing
        @test delete_supports(prefs) isa Nothing
    end
    # _update_infinite_point_mapping
    @testset "_update_infinite_point_mapping" begin
        # test first addition
        idx1 = PointVariableIndex(12)
        pvref = PointVariableRef(m, idx1)
        @test isa(InfiniteOpt._update_infinite_point_mapping(pvref, divref),
                  Nothing)
        @test InfiniteOpt._point_variable_dependencies(ivref) == [idx1]
        # test second addition
        idx2 = PointVariableIndex(42)
        pvref = PointVariableRef(m, idx2)
        @test isa(InfiniteOpt._update_infinite_point_mapping(pvref, divref),
                  Nothing)
        @test InfiniteOpt._point_variable_dependencies(ivref) == [idx1, idx2]
        # undo changes
        empty!(InfiniteOpt._point_variable_dependencies(ivref))
    end
    # _check_and_make_variable_ref
    @testset "_check_and_make_variable_ref" begin
        # prepare secondary model and infinite variable
        m2 = InfiniteModel()
        @independent_parameter(m2, pref3 in [0, 1])
        @infinite_variable(m2, ivref3(pref3))
        v = build_variable(error, info, Point, infinite_variable_ref = ivref3,
                           parameter_values = 0.5)
        # test for invalid variable error
        @test_throws VariableNotOwned{InfiniteVariableRef} InfiniteOpt._check_and_make_variable_ref(m, v, "")
        # test normal
        v = build_variable(error, info, Point, infinite_variable_ref = ivref3,
                           parameter_values = 0)
        idx = PointVariableIndex(1)
        vref = PointVariableRef(m2, idx)
        @test InfiniteOpt._check_and_make_variable_ref(m2, v, "") == vref
        @test supports(pref3) == [0]
        @test InfiniteOpt._point_variable_dependencies(ivref3) == [idx]
    end
    # add_variable
    @testset "JuMP.add_variable" begin
        # prepare secondary model and infinite variable
        m2 = InfiniteModel()
        @independent_parameter(m2, pref3 in [0, 1])
        @infinite_variable(m2, ivref3(pref3))
        v = build_variable(error, info, Point, infinite_variable_ref = ivref3,
                           parameter_values = 0.5)
        # test for invalid variable error
        @test_throws VariableNotOwned{InfiniteVariableRef} add_variable(m, v)
        # test normal
        v = build_variable(error, info, Point, infinite_variable_ref = ivref,
                           parameter_values = (0, 1))
        idx = PointVariableIndex(1)
        vref = PointVariableRef(m, idx)
        gvref = InfiniteOpt._make_variable_ref(m, idx)
        @test add_variable(m, v, "name") == gvref
        @test haskey(InfiniteOpt._data_dictionary(vref), idx)
        @test supports(pref) == [0]
        @test supports(pref2) == [1]
        @test name(vref) == "name"
        @test InfiniteOpt._point_variable_dependencies(ivref) == [idx]
        # prepare infinite variable with all the possible info additions
        v = build_variable(error, info2, Point, infinite_variable_ref = ivref,
                           parameter_values = (0, 1))
        # test info addition functions
        idx = PointVariableIndex(2)
        vref = PointVariableRef(m, idx)
        gvref = InfiniteOpt._make_variable_ref(m, idx)
        @test add_variable(m, v, "name") == gvref
        @test !optimizer_model_ready(m)
        # lower bound
        cindex = ConstraintIndex(1)
        cref = InfOptConstraintRef(m, cindex)
        @test has_lower_bound(vref)
        @test InfiniteOpt._lower_bound_index(vref) == cindex
        @test constraint_object(cref) isa ScalarConstraint{GeneralVariableRef,
                                                 MOI.GreaterThan{Float64}}
        @test InfiniteOpt._data_object(cref).is_info_constraint
        # upper bound
        cindex = ConstraintIndex(2)
        cref = InfOptConstraintRef(m, cindex)
        @test has_upper_bound(vref)
        @test InfiniteOpt._upper_bound_index(vref) == cindex
        @test constraint_object(cref) isa ScalarConstraint{GeneralVariableRef,
                                                 MOI.LessThan{Float64}}
        @test InfiniteOpt._data_object(cref).is_info_constraint
        # fix
        cindex = ConstraintIndex(3)
        cref = InfOptConstraintRef(m, cindex)
        @test has_upper_bound(vref)
        @test is_fixed(vref)
        @test InfiniteOpt._fix_index(vref) == cindex
        @test constraint_object(cref) isa ScalarConstraint{GeneralVariableRef,
                                                 MOI.EqualTo{Float64}}
        @test InfiniteOpt._data_object(cref).is_info_constraint
        # binary
        cindex = ConstraintIndex(4)
        cref = InfOptConstraintRef(m, cindex)
        @test has_upper_bound(vref)
        @test is_binary(vref)
        @test InfiniteOpt._binary_index(vref) == cindex
        @test constraint_object(cref) isa ScalarConstraint{GeneralVariableRef,
                                                 MOI.ZeroOne}
        @test InfiniteOpt._data_object(cref).is_info_constraint
        @test InfiniteOpt._constraint_dependencies(vref) == [ConstraintIndex(i)
                                                             for i = 1:4]
        # prepare infinite variable with integer info addition
        v = build_variable(error, info3, Point, infinite_variable_ref = ivref,
                           parameter_values = (0, 1))
        # test integer addition functions
        idx = PointVariableIndex(3)
        vref = PointVariableRef(m, idx)
        gvref = InfiniteOpt._make_variable_ref(m, idx)
        @test add_variable(m, v, "name") == gvref
        @test !optimizer_model_ready(m)
        cindex = ConstraintIndex(8)
        cref = InfOptConstraintRef(m, cindex)
        @test has_upper_bound(vref)
        @test is_integer(vref)
        @test InfiniteOpt._integer_index(vref) == cindex
        @test constraint_object(cref) isa ScalarConstraint{GeneralVariableRef,
                                                 MOI.Integer}
        @test InfiniteOpt._data_object(cref).is_info_constraint
        @test InfiniteOpt._constraint_dependencies(vref) == [ConstraintIndex(i)
                                                             for i = 5:8]
    end
end

# Test the point variable macro
@testset "Macro Definition" begin
    # initialize model, parameters, and infinite variables
    m = InfiniteModel()
    @infinite_parameter(m, t in [0, 1])
    @infinite_parameter(m, x[1:2] in [-1, 1])
    @infinite_variable(m, 0 <= z(t, x) <= 1, Int, start = (a, x) -> a + sum(x))
    @infinite_variable(m, z2[1:2](t) == 3)
    # test single variable definition
    @testset "Single" begin
        # test simple anon case
        idx = PointVariableIndex(1)
        vref = PointVariableRef(m, idx)
        gvref = InfiniteOpt._make_variable_ref(m, idx)
        @test @point_variable(m, infinite_variable_ref = z,
                              parameter_values = (0, [0, 0])) == gvref
        @test infinite_variable_ref(vref) == z
        @test parameter_values(vref) == (0, [0, 0])
        @test is_integer(vref)
        @test lower_bound(vref) == 0
        @test start_value(vref) == 0
        # test anon with changes to fixed
        idx = PointVariableIndex(2)
        vref = PointVariableRef(m, idx)
        gvref = InfiniteOpt._make_variable_ref(m, idx)
        @test @point_variable(m, infinite_variable_ref = z, lower_bound = -5,
                          parameter_values = (0, [0, 0]), binary = true) == gvref
        @test infinite_variable_ref(vref) == z
        @test parameter_values(vref) == (0, [0, 0])
        @test !is_integer(vref)
        @test is_binary(vref)
        @test lower_bound(vref) == -5
        # test regular with alias
        idx = PointVariableIndex(3)
        vref = PointVariableRef(m, idx)
        gvref = InfiniteOpt._make_variable_ref(m, idx)
        @test @point_variable(m, z(0, [0, 0]), z0, Bin) == gvref
        @test infinite_variable_ref(vref) == z
        @test parameter_values(vref) == (0, [0, 0])
        @test is_binary(vref)
        @test lower_bound(vref) == 0
        @test name(vref) == "z0"
        # test regular with semi anon
        idx = PointVariableIndex(4)
        vref = PointVariableRef(m, idx)
        gvref = InfiniteOpt._make_variable_ref(m, idx)
        @test @point_variable(m, z(0, [0, 0]), base_name = "z0",
                              binary = true) == gvref
        @test infinite_variable_ref(vref) == z
        @test parameter_values(vref) == (0, [0, 0])
        @test is_binary(vref)
        @test lower_bound(vref) == 0
        @test name(vref) == "z0"
    end
    # test array variable definition
    @testset "Array" begin
        # test anon array with one infvar
        idxs = [PointVariableIndex(5), PointVariableIndex(6)]
        vrefs = [PointVariableRef(m, idx) for idx in idxs]
        gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs]
        @test @point_variable(m, [1:2], infinite_variable_ref = z,
                              parameter_values = (0, [0, 0])) == gvrefs
        @test infinite_variable_ref(vrefs[1]) == z
        @test parameter_values(vrefs[2]) == (0, [0, 0])
        @test is_integer(vrefs[1])
        @test lower_bound(vrefs[2]) == 0
        # test anon array with different inf vars
        idxs = [PointVariableIndex(7), PointVariableIndex(8)]
        vrefs = [PointVariableRef(m, idx) for idx in idxs]
        gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs]
        @test @point_variable(m, [i = 1:2], infinite_variable_ref = z2[i],
                              parameter_values = 0) == gvrefs
        @test infinite_variable_ref(vrefs[1]) == z2[1]
        @test infinite_variable_ref(vrefs[2]) == z2[2]
        @test parameter_values(vrefs[2]) == (0,)
        @test fix_value(vrefs[2]) == 3
        @test name(vrefs[1]) == ""
        # test array with same infvar
        idxs = [PointVariableIndex(9), PointVariableIndex(10)]
        vrefs = [PointVariableRef(m, idx) for idx in idxs]
        gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs]
        @test @point_variable(m, z(0, [0, 0]), a[1:2], Bin) == gvrefs
        @test infinite_variable_ref(vrefs[1]) == z
        @test parameter_values(vrefs[2]) == (0, [0, 0])
        @test is_binary(vrefs[1])
        @test lower_bound(vrefs[2]) == 0
        @test name(vrefs[1]) == "a[1]"
        # test test array with differnt infvars
        idxs = [PointVariableIndex(11), PointVariableIndex(12)]
        vrefs = [PointVariableRef(m, idx) for idx in idxs]
        gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs]
        @test @point_variable(m, z2[i](0), b[i = 1:2] >= -5) == gvrefs
        @test infinite_variable_ref(vrefs[1]) == z2[1]
        @test infinite_variable_ref(vrefs[2]) == z2[2]
        @test parameter_values(vrefs[2]) == (0,)
        @test lower_bound(vrefs[2]) == -5
        @test name(vrefs[1]) == "b[1]"
        # test semi anon array
        idxs = [PointVariableIndex(13), PointVariableIndex(14)]
        vrefs = [PointVariableRef(m, idx) for idx in idxs]
        gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs]
        @test @point_variable(m, z2[i](0), [i = 1:2], lower_bound = -5) == gvrefs
        @test infinite_variable_ref(vrefs[1]) == z2[1]
        @test infinite_variable_ref(vrefs[2]) == z2[2]
        @test lower_bound(vrefs[2]) == -5
        @test name(vrefs[1]) == ""
    end
    # test errors
    @testset "Errors" begin
        # test model assertion errors
        m2 = Model()
        @test_throws AssertionError @point_variable(m2, infinite_variable_ref = z,
                                                 parameter_values = (0, [0, 0]))
        @test_throws AssertionError @point_variable(m2, z(0, [0, 0]), bob, Bin)
        @test_throws AssertionError @point_variable(m2, [1:2],
                      infinite_variable_ref = z, parameter_values = (0, [0, 0]))
        # test double specification
        @test_macro_throws ErrorException @point_variable(m, z(0, [0, 0]), bob,
                                                      infinite_variable_ref = z)
        @test_macro_throws ErrorException @point_variable(m, z(0, [0, 0]), bob,
                                                 parameter_values = (0, [0, 0]))
        # test the adding expressions to infvar
        @test_macro_throws ErrorException @point_variable(m, z(0, [0, 0]) >= 0,
                                                          bob, Bin)
        @test_macro_throws ErrorException @point_variable(m, z(0, [0, 0]) == 0,
                                                          bob, Bin)
        @test_macro_throws ErrorException @point_variable(m, z(0, [0, 0]) in 0,
                                                          bob, Bin)
        # test other syntaxes
        @test_macro_throws ErrorException @point_variable(m,
                                               0 <= z(0, [0, 0]) <= 1, bob, Bin)
        @test_macro_throws ErrorException @point_variable(m, [1:2], Bin,
                      infinite_variable_ref = z, parameter_values = (0, [0, 0]))
        @test_macro_throws ErrorException @point_variable(m, bob,
                     infinite_variable_ref = z, parameter_values = (0, [0, 0]))
        # test redefinition catch
        @test_macro_throws ErrorException @point_variable(m, z(0, [0, 0]), z0,
                                                          Bin)
    end
end

# test usage methods
@testset "Usage" begin
    # initialize model and stuff
    m = InfiniteModel()
    @independent_parameter(m, t in [0, 1])
    @dependent_parameters(m, x[1:2] in [-1, 1])
    @infinite_variable(m, y(t, x))
    @point_variable(m, y(0, [0, 0]), y0)
    vref = dispatch_variable_ref(y0)
    # test used_by_measure
    @testset "used_by_measure" begin
        @test !used_by_measure(vref)
        push!(InfiniteOpt._measure_dependencies(vref), MeasureIndex(1))
        @test used_by_measure(y0)
        @test used_by_measure(vref)
        empty!(InfiniteOpt._measure_dependencies(vref))
    end
    # test used_by_constraint
    @testset "used_by_constraint" begin
        @test !used_by_constraint(vref)
        push!(InfiniteOpt._constraint_dependencies(vref), ConstraintIndex(1))
        @test used_by_constraint(y0)
        @test used_by_constraint(vref)
        empty!(InfiniteOpt._constraint_dependencies(vref))
    end
    # test used_by_objective
    @testset "used_by_objective" begin
        @test !used_by_objective(y0)
        @test !used_by_objective(vref)
        InfiniteOpt._data_object(vref).in_objective = true
        @test used_by_objective(vref)
        InfiniteOpt._data_object(vref).in_objective = false
    end
    # test is_used
    @testset "is_used" begin
        # test not used
        @test !is_used(vref)
        # test used by constraint and/or measure
        push!(InfiniteOpt._constraint_dependencies(vref), ConstraintIndex(1))
        @test is_used(y0)
        empty!(InfiniteOpt._constraint_dependencies(vref))
        # test used by objective
        InfiniteOpt._data_object(vref).in_objective = true
        @test is_used(vref)
    end
end


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

using Markdown
using InteractiveUtils

# ╔═╡ cb961c7a-325f-11ec-17ae-d731e8fa429d
md"""

# Loading and starting Genie apps

At any time, you can load and serve an existing Genie app. Loading a Genie app will bring into scope all your app's files, including the main app module, controllers, models, etcetera.

## Starting a Genie REPL session MacOS / Linux

The recommended approach is to start an interactive REPL in Genie's environment by executing `bin/repl` in the os shell, while in the project's root folder.

"""

# ╔═╡ d6385f96-0d16-4dca-92f0-3041b6108de2
md"""
```sh
$ bin/repl
```

The app's environment will be loaded.

In order to start the web server, you can next execute:

```julia
julia> up()
```

"""

# ╔═╡ 05d1edf1-a48e-47f7-bf4f-b61ab86b0ae6
md"""
If you want to directly start the server, use `bin/server` instead of `bin/repl`:

```sh
$ bin/server
```
"""

# ╔═╡ 3117bf6b-8d66-464c-9769-3d8923e4c9e4
md"""
This will automatically start the web server _in non interactive mode_.

Finally, there is the option to start the serve and drop to an interactive REPL, using `bin/serverinteractive` instead.
"""

# ╔═╡ 5fa54447-ffd1-48e9-8526-67156920ea50
md"""
## Starting a Genie REPL on Windows

On Windows the workflow is similar to macOS and Linux, but dedicated Windows scripts, `repl.bat`, `server.bat`, and `serverinteractive.bat` are provided inside the project folder, within the `bin/` directory. Double click them or execute them in the os shell (cmd or PowerShell) to start an interactive REPL session or a server session, respectively, as explained in the previous paragraphs.

---
**HEADS UP**

It is possible that the Windows executables `repl.bat`, `server.bat`, and `serverinteractive.bat` are missing - this is usually the case if the app was generated on a Linux/Mac and ported to a windows computer. You can create them at anytime by running this generator in the Genie/Julia REPL (at the root of the Genie project):
"""

# ╔═╡ 407ad975-3018-49ac-98b0-9023c61f062b
md"""

```julia

julia> using Genie

julia> Genie.Generator.setup_windows_bin_files()
```
"""

# ╔═╡ 05072f0d-b81c-4892-bc9d-df0fcfac9489
md"""
Alternatively, you can pass the path to the project as the argument to `setup_windows_bin_files`:
"""

# ╔═╡ 70117605-5d7e-4530-bb71-1d9266801ba5
md"""
```julia
julia> Genie.Generator.setup_windows_bin_files("path/to/your/Genie/project")
```
"""

# ╔═╡ 81c7b086-2d3d-437f-89d8-cb91f38a94d3
md"""
## Juno / Jupyter / other Julia environment

For Juno, Jupyter, and other interactive environments, first make sure that you `cd` into your app's project folder.

We will need to make the local package environment available:
"""

# ╔═╡ d96f95b8-5cb9-40a6-a598-fa0b152afd67
md"""

```julia
using Pkg
Pkg.activate(".")
```
"""

# ╔═╡ 295e615a-8086-4441-b555-6824a7c4e78c
md"""
Then:

```julia
using Genie

Genie.loadapp()
```
"""

# ╔═╡ 5568bbb0-af35-45b8-b0e6-40df88b16484
md"""
## Manual loading in Julia's REPL

In order to load a Genie app within an open Julia REPL session, first make sure that you're in the root dir of a Genie app. This is the project's folder and you can tell by the fact that there should be a `bootstrap.jl` file, plus Julia's `Project.toml` and `Manifest.toml` files, amongst others. You can `julia> cd(...)` or `shell> cd ...` your way into the folder of the Genie app.

Next, from within the active Julia REPL session, we have to activate the local package environment:
"""

# ╔═╡ 74838525-f6e6-4c01-a1ce-51cf49cfe955
md"""

```julia
julia> ] # enter pkg> mode

pkg> activate .
```
"""

# ╔═╡ 64a032f4-7f43-4b98-89e7-5101fe0160c5
md"""
Then, back to the julian prompt, run the following to load the Genie app:

```julia
julia> using Genie

julia> Genie.loadapp()
```
"""

# ╔═╡ 5273d572-858c-48b4-9d23-d70e14e18ec6
md"""

The app's environment will now be loaded.

In order to start the web server execute

```julia
julia> startup()
```
"""

# ╔═╡ 16e41c1d-bad6-4292-b16a-cc1586c0ba99
md"""
---
**HEADS UP**

The recommended way to load an app is via the `bin/repl`, `bin/server` and `bin/serverinteractive` commands. It will correctly start the Julia process and start the app REPL with all the dependencies loaded with just one command.

---
"""

# ╔═╡ Cell order:
# ╟─cb961c7a-325f-11ec-17ae-d731e8fa429d
# ╟─d6385f96-0d16-4dca-92f0-3041b6108de2
# ╟─05d1edf1-a48e-47f7-bf4f-b61ab86b0ae6
# ╟─3117bf6b-8d66-464c-9769-3d8923e4c9e4
# ╟─5fa54447-ffd1-48e9-8526-67156920ea50
# ╟─407ad975-3018-49ac-98b0-9023c61f062b
# ╟─05072f0d-b81c-4892-bc9d-df0fcfac9489
# ╟─70117605-5d7e-4530-bb71-1d9266801ba5
# ╟─81c7b086-2d3d-437f-89d8-cb91f38a94d3
# ╟─d96f95b8-5cb9-40a6-a598-fa0b152afd67
# ╟─295e615a-8086-4441-b555-6824a7c4e78c
# ╟─5568bbb0-af35-45b8-b0e6-40df88b16484
# ╟─74838525-f6e6-4c01-a1ce-51cf49cfe955
# ╟─64a032f4-7f43-4b98-89e7-5101fe0160c5
# ╟─5273d572-858c-48b4-9d23-d70e14e18ec6
# ╟─16e41c1d-bad6-4292-b16a-cc1586c0ba99

ext: jl


text:
@testset "Codebook generation" begin

# Generate some random data
n = 100
dim = 2
U = UInt8
Xfloat = rand(dim, n)
codes = U.(collect(1:n))

# Test constructors
cb = CodeBook(codes, Xfloat)
@test cb isa CodeBook{U, eltype(Xfloat)}
@test size(cb.vectors) == size(Xfloat)
@test length(cb.codes) == length(codes)
for (code, idx) in cb.codemap  # tests codemap creation, getindex
    @test cb[code] == Xfloat[:, cb.codemap[code]] == Xfloat[:, idx]
end
@test_throws DimensionMismatch CodeBook(codes, rand(2,n-3))
@test_throws ErrorException CodeBook{UInt8}(rand(2,257))

for T in [UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64,
          Float16, Float32, Float64]
    for U in [UInt8, UInt16]  # not really necessary for UInt32, UInt64
        X = rand(T, dim, Int.(typemax(U)))
        @test CodeBook(X) isa CodeBook{U,T}
        if T<:Unsigned && QuantizedArrays.TYPE_TO_BITS[T] <= QuantizedArrays.TYPE_TO_BITS[U]
            @test CodeBook{U,U}(X) isa CodeBook{U,U}
        elseif T<:Unsigned && QuantizedArrays.TYPE_TO_BITS[T] >= QuantizedArrays.TYPE_TO_BITS[U]
            @test_throws InexactError CodeBook{U,U}(X)
        elseif T<:AbstractFloat
            @test CodeBook{U, Float64}(X) isa CodeBook{U, Float64}
        end
    end
end

@test QuantizedArrays.encode(cb, Xfloat) == cb.codes

#TODO(Corneliu): Functional testing of codebook
#                generation algorithms i.e. `build_codebooks`
T = Float32
U = UInt16
m = 2
dim = 4
npoints = 10
for method in [:pq, :opq, :rvq]
    cbs, rot = QuantizedArrays.build_codebooks(rand(T, dim, npoints),
                2, m, U, method=method)
    @test cbs isa Vector{CodeBook{U,T}}
    @test length(cbs) == m
    @test rot isa Matrix{T}
    @test size(rot) == (dim, dim)
end

end


text:
# Write to text (REPL)

maxstrwidth(x::AbstractVector, colname) = maximum(map(ts -> length(string(ts)), [x; colname]))

function padval(val, maxlength::Int, center::Bool)
    paddingrequired = max(0, maxlength - length(string(val)))
    strval = string(val)
    center ?
    repeat(" ", floor(Int,paddingrequired/2)) * strval * repeat(" ", ceil(Int,paddingrequired/2)) :
    strval * repeat(" ", paddingrequired)
end #padval

showline(io, ts, tswidth::Int, val, valwidth::Int; center::Bool=false) =
    println(io, "┃ $(padval(ts,tswidth,center)) ┃ $(padval(val,valwidth,center)) ┃")

showline(io, ts, tswidth::Int, vals::AbstractArray, valwidths::Vector{Int}; center::Bool=false) =
    showline(io, ts, tswidth, vec(vals), valwidths, center=center)

showline(io, ts, tswidth::Int, vals::AbstractVector, valwidths::Vector{Int}; center::Bool=false) =
    println(io, "┃ $(padval(ts, tswidth, center)) ┃ $(showinnerline(vals, valwidths, center)) ┃")

showinnerline(colvals::AbstractVector, colwidths::Vector{Int}, center::Bool=false) =
    join(map((colval, colwidth) -> padval(colval, colwidth, center), colvals, colwidths), " │ ")

hline(colwidths::Vector{Int}, line::AbstractString, joiner::AbstractString) =
    join(map(colwidth -> repeat(line, colwidth+2), colwidths), joiner)

function paneltotext{T}(io::IO, A::TimeAxisArray{T,2})
    timestamps, colnames = A.axes[1].val, A.axes[2].val
    n, m = length(timestamps), length(colnames)
    tsname = "$(dimname(A.axes[1])) \\ $(dimname(A.axes[2]))"
    tswidth = maxstrwidth(timestamps, tsname)
    colwidths = map(colname -> maxstrwidth(A[:,colname].data, string(colname)), colnames)
    totalcolswidth = sum(colwidths) + 3(length(colnames)-1 - 2)
    println(io, "┏",repeat("━", tswidth + 2), "┳", hline(colwidths, "━", "┯"), "┓")
    showline(io, tsname, tswidth, colnames, colwidths, center=true)
    println(io, "┠",repeat("─", tswidth + 2), "╂", hline(colwidths, "─", "┼"),"┨")
    if n < 9
        [showline(io, timestamps[i], tswidth, A[i,:].data, colwidths) for i in eachindex(timestamps)]
    else
        [showline(io, timestamps[i], tswidth, A[i,:].data, colwidths) for i in 1:4]
        showline(io, "⋮", tswidth, repmat(["⋮"], m), colwidths, center=true)
        [showline(io, timestamps[i], tswidth, A[i,:].data, colwidths) for i in n-3:n]
    end
    println(io, "┗",repeat("━", tswidth + 2), "┻", hline(colwidths, "━", "┷"), "┛")
    return timestamps
end #paneltotext

panellabeltotext(ns::Vector{Symbol}, cs::Vector{Symbol}) = join(map((n,c) -> "$n: $c", ns, cs), ", ")

function textrep{T}(io::IO, A::TimeAxisArray{T,1}, typealiasname::AbstractString)
    timestamps = A.axes[1].val
    n = length(timestamps)
    tsname = dimname(A.axes[1])
    tswidth = maxstrwidth(timestamps, tsname)
    valname = "Value"
    valwidth = maxstrwidth(A.data, valname)
    println(io, "$n-element $typealiasname{$T,1,...}:")
    println(io, "┏",repeat("━", tswidth + 2), "┳", repeat("━", valwidth + 2),"┓")
    showline(io, tsname, tswidth, valname, valwidth, center=true)
    println(io, "┠",repeat("─", tswidth + 2), "╂", repeat("─", valwidth + 2),"┨")
    if n < 9
        [showline(io, timestamps[i], tswidth, A.data[i], valwidth) for i in eachindex(timestamps)]
    else
        [showline(io, timestamps[i], tswidth, A.data[i], valwidth) for i in 1:4]
        showline(io, "⋮", tswidth, "⋮", valwidth, center=true)
        [showline(io, timestamps[i], tswidth, A.data[i], valwidth) for i in n-3:n]
    end
    println(io, "┗",repeat("━", tswidth + 2), "┻", repeat("━", valwidth + 2),"┛")
    return timestamps
end #textrep 1D

function textrep{T}(io::IO, A::TimeAxisArray{T,2}, typealiasname::AbstractString)
    println(io, "$(length(A.axes[1].val))x$(length(A.axes[2].val)) $typealiasname{$T,2,...}:")
    return paneltotext(io, A)
end #textrep 2D

function textrep{T,N}(io::IO, A::TimeAxisArray{T,N}, typealiasname::AbstractString)
    higherdimnames = Symbol[dimname(A.axes[i]) for i in 3:N]
    higherdimcategories = Vector{Symbol}[A.axes[i].val for i in 3:N]
    dimsizes = join(size(A), "x")
    println(io, "$dimsizes $typealiasname{$T,$N,...}:")
    for categoryset in product(higherdimcategories...)
        println(io, "\n", panellabeltotext(higherdimnames, collect(categoryset)))
        paneltotext(io, A[:,:,categoryset...])
    end #for
    return A.axes[1].val
end #textrep 3D+

function Base.show(io::IO, A::TimeAxisArray)
    timestamps = textrep(io, A, "TimeAxisArray")
    tsstart, tsend = timestamps[1], timestamps[end]
    print(io, "Spans $tsstart to $tsend")
    return nothing
end #show

function Base.show(io::IO, A::RegularTimeAxisArray)
    timestamps = textrep(io, A, "RegularTimeAxisArray")
    tsstart, tsend, tsinterval = timestamps[1], timestamps[end], step(timestamps)
    print(io, "Spans $tsstart to $tsend at intervals of $tsinterval")
    return nothing
end #show

# Read from disk

function readtimeaxisarray(f, timeparser::Function,
                           dataparser::Function=x->stringfallback(x, NaN);
                           timecol::Bool=true, header::Bool=true, namedaxes::Bool=false, defaultval=NaN,
                           headlines::Int=header?1:0, delim::Char=',', kwargs...)

    # Read in data
    rawdata = readdlm(f, delim, header=false; kwargs...)

    # Process array contents
    data = map(dataparser, rawdata[1+headlines:end,(1+timecol):end])

    # Process time axis
    timestamps = timecol ? map(timeparser, rawdata[1+headlines:end,1]) : map(timeparser, 1:size(data,1))
    timestamps = collect(promote(timestamps...))
    isregularspaced(timestamps) && (timestamps = timestamps[1]:(timestamps[2]-timestamps[1]):timestamps[end])

    # Process headers / higher dimension axes
    ndatacols = size(data,2)
    if ndatacols == 1
        A = TimeAxisArray(vec(data), timestamps)
    elseif !header
        A = TimeAxisArray(data, timestamps, [defaultcolumnnames[i] for i in 1:ndatacols])
    else
        headers = map(symbolize, rawdata[1:headlines, (1+timecol):end])
        dataaxisnames = (timecol && namedaxes) ?
            map(symbolize, rawdata[1:headlines,1]) : defaultaxisnames[2:headlines+1]
        axes = map(i -> Axis{dataaxisnames[i]}(unique(headers[i,:])), 1:headlines) |> reverse
        dims = tuple(length(timestamps), map(length, axes)...)
        A = TimeAxisArray(fill(defaultval, dims), timestamps, axes...)
        for col in 1:ndatacols
            A[:,reverse(vec(headers[:, col]))...] = data[:,col]
        end #for
    end #if

    return A

end #readdlm

# Write to disk

Base.writedlm{T}(f::AbstractString, A::TimeAxisArray{T,1}, delim::Char=',') = writedlm(f, Any[timestamps(A) A.data], delim)

function Base.writedlm{T,N}(f::AbstractString, A::TimeAxisArray{T,N}, delim::Char=',')

    fileArray = Matrix{Any}(size(A,1)+N-1,0)

    higherdimnames = Symbol[dimname(A.axes[i]) for i in 2:N]
    higherdimcategories = Vector{Symbol}[A.axes[i].val for i in 2:N]

    fileArray = [fileArray [reverse(higherdimnames); timestamps(A)]]

    for categoryset in product(higherdimcategories...)
        fileArray = [fileArray [reverse(collect(categoryset)); A[:,categoryset...].data]]
    end #for

    writedlm(f, fileArray, delim)

end #writedlm

max_stars_repo_name: GordStephen/TimeAxisArrays

max_issues_repo_name: GordStephen/TimeAxisArrays

max_forks_repo_name: GordStephen/TimeAxisArrays


text:
using GridapMHD

using Gridap
using Test

@time @testset "ManufacturedSolMHDTest" begin include("ManufacturedSolMHDTest.jl") end

@time @testset "ConvergenceMHDTest" begin include("ConvergenceMHDTest.jl") end

@time @testset "ConvergenceWithPeriodicBCMHDTest" begin include("ConvergenceWithPeriodicBCMHDTest.jl") end

@time @testset "ShercliffTest" begin include("ShercliffTest.jl") end

@time @testset "HuntTest" begin include("HuntTest.jl") end

@time @testset "ThinWallBCTest" begin include("ThinWallBCTest.jl") end

@time @testset "TransientTest" begin include("TransientTest.jl") end

@time @testset "DriverInductionlessMHDTest" begin include("DriverInductionlessMHDTest.jl") end


text:
struct RittWuMethod <: AbstractGeometricProver end

mutable struct RittWuProof{S} <: AbstractGeometricProof
    coords::OrderedDict{Symbol, Coordinate}
    H::Vector{S}
    T::Vector{S}
    R::Matrix{S}
    u::Vector{PolyVar{true}}
    x::Vector{PolyVar{true}}
end

function show(io::IO, rwp::RittWuProof)
    println(io, "Assigned coordinates:")
    println(io, "---------------------")
    for (P, c) in rwp.coords
        println(io, P, " = ", c)
    end
    println(io)
    for (idx, p) in enumerate(eachcol(rwp.R))
        status = iszero(first(p)) ? "success" : "fail"
        println(io, "Goal $idx: $status")
    end
    println(io, "\nNondegeneracy conditions:")
    println(io, "-------------------------")
    for c in ndg(rwp)
        show(io, c)
        println(io, " ≠ 0")
    end
end

function prove(hp::Hypothesis, th::Thesis, ::Type{RittWuMethod}, coords, u, x)
    H = [cc for c in hp.constraints for cc in algebry(c, coords) if !iszero(cc)]
    G = [cc for c in th.constraints for cc in algebry(c, coords)]
    T = triangulize(copy(H), x)

    R = Matrix{eltype(T)}(undef, length(x) + 1, length(G))
    @inbounds for (idx, g) in enumerate(G)
        R[end, idx] = g
        @inbounds for i in length(x):-1:1
            R[i, idx] = pseudorem(R[i+1, idx], T[i], x[i])
        end
    end

    return RittWuProof(coords, H, T, R, u, x)
end

function prove(hp::Hypothesis, th::Thesis, ::Type{RittWuMethod})
    coords, x, u = assign_variables(hp)
    return prove(hp, th, RittWuMethod, coords, u, x)
end

isproved(rwp::RittWuProof) = [iszero(first(p)) for p in eachcol(rwp.R)]
ndg(p::RittWuProof) = [LC(t, xi) for (t, xi) in zip(p.T, p.x) if maxdegree(LC(t, xi)) != 0]


text:
using Plots
using DataFrames
using Images
using Statistics
using ImageBinarization

mutable struct Setup
    cmdir::String
    series::String
    measurement::String
    point::String
    filter::String
    rep::String
    imgid::String
    texpsec::Float64
    darktype::String
    sfilter::String
    srep::String
    img::String
    dark::String
    exp::String
    fext::String
    pext::String
end

function select_image_name(setup::Setup, imgid="Dark")

    if imgid == "Dark"
        if setup.darktype == "before"
            string(setup.sfilter, "_" , setup.filter, "_" , setup.exp, "_", setup.darktype,
                                  "_", setup.dark,  setup.fext)
        else
            string(setup.sfilter, "_" , setup.filter, "_" , setup.exp, "_", setup.dark,  setup.fext)
        end
    else
        string(setup.sfilter, "_", setup.filter, "_", setup.srep, "_", setup.rep, "_", setup.exp,
               "_", setup.img,  setup.fext)
    end

end

function get_image_name(inames::Vector{String}, imgn::String)
	names = [split(f,"/")[end] for f in inames]
	indx = findall([occursin(imgn, name) for name in names])[1]
	inames[indx]
end

function get_image(ffimg::String)
	imgdf = DataFrame(CSV.File(ffimg, header=false,delim="\t"))
	img   = dftomat(imgdf)
    imgn = img ./maximum(img)
    (img = img, imgn = imgn)
end

function select_image(xfiles::Vector{String}, setup::Setup, imgid::String)
	imgn = select_image_name(setup, imgid)
    println("imgn = ", imgn)
	ximg = get_image_name(xfiles, imgn)
    #println("ximg = ", ximg)
	get_image(ximg)
end

function get_corrected_image(files::Vector{String}, setup::Setup)
	imgm = select_image(files, setup, "Imag")
	drkm = select_image(files, setup, "Dark")

	img = imgm.img .- drkm.img
	imgn = img ./maximum(img)
    (img = img, imgn = imgn, dark=drkm.img)
end

function spectrum_max(xfiles::Vector{String}, setup::Setup,
                      xfn::Vector{String}, filtnm::NamedTuple, adctopes::Float64; nsigma::Float64=3.0)
	ZMX = Vector{Float64}()
	ZSM = Vector{Float64}()
	ZI = Vector{Float64}()
	ZJ = Vector{Float64}()

    fold = setup.filter
	for fltr in xfn
        setup.filter = fltr
        #println("in spectrum_max: setup point = ", setup.point)
		cimgz = get_corrected_image(xfiles, setup)
		imgmz, imgp = signal_around_maximum(cimgz.img, cimgz.dark; nsigma=nsigma)
		push!(ZMX,imgp.max)
		push!(ZSM,sum(imgmz.img))
		push!(ZI,imgp.imax)
		push!(ZJ,sum(imgp.jmax))

        #println(" for filter ",fltr, " sum = ", sum(imgmz.img))
	end
    setup.filter = fold
	DataFrame("fltn" => xfn, "cflt" => filtnm.center, "lflt" => filtnm.left, "rflt" => filtnm.right, "wflt" => filtnm.width,
		      "sum"=> ZSM, "sumpes"=> adctopes *(ZSM ./filtnm.width), "max"=> ZMX, "imax" => ZI, "jmax" => ZJ)
end

function spectrum_max_allpoints!(setup::Setup,
                                xpt::Vector{String}, xfn::Vector{String},
                                filtnm::NamedTuple, adctopes::Float64; nsigma::Float64=3.0, odir, etype="csv")
    pold = setup.point
    for pt in xpt
        setup.point = pt
        xpath = joinpath(setup.cmdir,setup.series,setup.measurement, setup.point)
        dfiles = string("*",setup.fext)
	    xfiles = Glob.glob(dfiles, xpath)
        #println("in spectrum_max_allpoints: xpath = ", xpath)
        sdf = spectrum_max(xfiles, setup, xfn, filtnm, adctopes; nsigma=nsigma)
        sdfnm = get_outpath(setup, etype)
        sdff = joinpath(odir, sdfnm)
	    println("Writing point to  =", sdff)
	    CSV.write(sdff, sdf)
    end
    setup.point = pold
end

function spectrum_sum(xfiles::Vector{String}, setup::Setup,
                      xfn::Vector{String}, filtnm::NamedTuple, adctopes::Float64)

    ZSM = Vector{Float64}()

    #println("in spectrum_sum: setup = ", setup)
    for fltr in xfn
        setup.filter = fltr
        cimgz = get_corrected_image(xfiles, setup)
        push!(ZSM,sum(cimgz.img))
    end

    #println("in spectrum_sum (after): setup = ", setup)
    DataFrame("fltn" => xfn, "cflt" => filtnm.center, "lflt" => filtnm.left, "rflt" => filtnm.right, "wflt" => filtnm.width,
    "sum"=> ZSM, "sumpes"=> adctopes *(ZSM ./filtnm.width))
end

function get_outpath(setup::Setup, etype="csv")

    if etype == "csv"
	    sdfnm = string(setup.series, "_", setup.measurement, "_",
                   setup.point,  "_", setup.srep,  "_", setup.rep, setup.fext)
    else
        sdfnm = string(setup.series, "_", setup.measurement, "_",
                   setup.point,  "_", setup.srep,        "_", setup.rep, setup.pext)
    end
end

# function write_spectrum!(sdf::DataFrame, setup::Setup; odir, etype="csv")

#     if etype == "csv"
# 	    sdfnm = string(setup.series, "_", setup.measurement, "_",
#                    setup.point,  "_", setup.srep,        "_", setup.rep, setup.fext)
#     else
#         sdfnm = string(setup.series, "_", setup.measurement, "_",
#                    setup.point,  "_", setup.srep,        "_", setup.rep, setup.pext)
#     end

# 	sdff = joinpath(odir, sdfnm)
# 	#println("Writing point to  =", sdff)
# 	CSV.write(sdff, sdf)

# end

function read_spectrum(setup::Setup, csvdir)

	sdfnm = string(setup.series, "_", setup.measurement, "_",
                   setup.point,  "_", setup.srep,        "_", setup.rep, setup.fext)

	sdff = joinpath(csvdir, sdfnm)
	#println("reading file =", sdff)

    load_df_from_csv(csvdir, sdfnm, enG)

end

function spectrum_fromfile_allpoints(setup::Setup, xpt::Vector{String}, csvdir)
    dfdict = Dict()
    for pt in xpt
        setup.point = pt
        df = read_spectrum(setup, csvdir)
        dfdict[pt] = df
    end

    dfdict
end

"""
    dftomat(img::DataFrame)

Copy a dataframe into a 2x2 matrix.

# Fields
- `img::DataFrame`: The "image dataframe", a sqaure dataframe (typically 512 x 512)

"""
function dftomat(img::DataFrame)
	mimg = Array{Float64}(undef, size(img)...);
	for i in 1:size(img)[1]
		for j in 1:size(img)[2]
			if img[i,j] >= 0.0 && !isnan(img[i,j])
    			mimg[i, j] = img[i,j]
			else
				mimg[i, j] = 0.0
			end
		end
	end
	mimg
end
"""
    signal_around_maximum(img::Matrix{Float64}; xrange::Int64=10)

Finds the maximum of the image, then adds signal in a window defined by xwindow

# Fields
- `img::DataFrame`: The "corrected image matrix"
- `dark::DataFrame`: The "corrected dark matrix"
- `nsigma::Int64`: number of sigmas for noise cutoff

"""
function signal_around_maximum(img::Matrix{Float64}, dimg::Matrix{Float64}; nsigma::Float64=2.0)

    cutoff::Float64 =  nsigma * std(dimg)

    #println("mean dimg =", mean(dimg), " std  = ", std(dimg), " cutoff =", cutoff)

	mxx::Float64, indxt = findmax(img)
    sx::Int = size(img)[1]
    sy::Int = size(img)[2]
    kx::Int = indxt[1]
    ky::Int = indxt[2]

    #println("max =", mxx)
    #println("sx =", sx, " sy = ", sy, " kx = ", kx, " ky = ", ky)

    if mxx < cutoff
        #println("max =", mxx, " less than cutoff! ", cutoff, " taking max")
        img2 = Array{Float64}(undef,1, 1)
        img2[1,1] = mxx
        imgn = 1.0
        return (img = img2, imgn = imgn), (max=mxx, imax=kx, jmax=ky)
    end

    ik::Int = 0
    for ii in kx:sx
        if img[ii,ky] > cutoff
            ik = ii
        else
            break
        end
    end

    jk::Int = 0
    for jj in ky:sy
        if img[kx,jj] > cutoff
            jk = jj
        else
            break
        end
    end

    ixr::Int = min(sx, ik)
    iyr::Int = min(sy, jk)

    #println("ik = ", ik, " jk = ", jk)
    #println("ixr = ", ixr, " iyr = ", iyr)

	for ii in kx:-1:1
        if img[ii,ky] > cutoff
            ik = ii
        else
            break
        end
    end

    for jj in ky:-1:1
        if img[kx,jj] > cutoff
            jk = jj
        else
            break
        end
    end

	ixl = max(1, ik)
	iyl = max(1, jk)

    #println("ik = ", ik, " jk = ", jk)
    #println("ixl = ", ixl, " iyl = ", iyl)

	img2 = Array{Float64}(undef, ixr - ixl + 1, iyr - iyl + 1)

	for (i, ix) in enumerate(ixl:ixr)
		for (j, iy) in enumerate(iyl:iyr)
			img2[i,j]=img[ix,iy]
		end
	end

    #println("size of img2 =", size(img2))

    imgn = img2 ./maximum(img2)
    (img = img2, imgn = imgn), (max=mxx, imax=kx, jmax=ky)

end

"""
    sum_edge(img::Matrix{Float64}, edge::Matrix{Float64})

Adds all the pixels in matrix img that are identified as "edge" (>0) in matrix edge

# Fields
- `img::Matrix{Float64}`: Image matrix
- `edge::Matrix{Float64}`: edge matrix

"""
function sum_edge(img::Matrix{Float64}, edge::Matrix{Float64})
	sum::Float64 = 0.0
	nedge::Int   = 0
	for i::Int in 1:size(img)[1]
		for j::Int in 1:size(img)[2]
			if edge[i,j] > 0.0
				sum += img[i,j]
				nedge += 1
			end
		end
	end
	sum, nedge
end

"""
    edges = sujoy(img; four_connectivity=true)

Compute edges of an image using the Sujoy algorithm.

# Parameters

* `img` (Required): any gray image
* `four_connectivity=true`: if true, kernel is based on 4-neighborhood, else, kernel is based on
   8-neighborhood,

# Returns

* `edges` : gray image
"""
function sujoy(img; four_connectivity=true)
    img_channel = Gray.(img)

    min_val = minimum(img_channel)
    img_channel = img_channel .- min_val
    max_val = maximum(img_channel)

    if max_val == 0
        return img
    end

    img_channel = img_channel./max_val

    if four_connectivity
        krnl_h = centered(Gray{Float32}[0 -1 -1 -1 0; 0 -1 -1 -1 0; 0 0 0 0 0; 0 1 1 1 0; 0 1 1 1 0]./12)
        krnl_v = centered(Gray{Float32}[0 0 0 0 0; -1 -1 0 1 1;-1 -1 0 1 1;-1 -1 0 1 1;0 0 0 0 0 ]./12)
    else
        krnl_h = centered(Gray{Float32}[0 0 -1 0 0; 0 -1 -1 -1 0; 0 0 0 0 0; 0 1 1 1 0; 0 0 1 0 0]./8)
        krnl_v = centered(Gray{Float32}[0 0 0 0 0;  0 -1 0 1 0; -1 -1 0 1 1;0 -1 0 1 0; 0 0 0 0 0 ]./8)
    end

    grad_h = imfilter(img_channel, krnl_h')
    grad_v = imfilter(img_channel, krnl_v')

    grad = (grad_h.^2) .+ (grad_v.^2)

    return grad
end

"""
    plot_images(imgnt)

Plots the images with laser on and off, as well as corrected, as heatmaps.

# Fields
- `imgnt::NamedTuple`: A named tuple containing the three images
- `whichf::String`: filter number (by convention from 2 to 11)
- `whichr::String`: repetition number (1,2,3): files with repetitions of the same measurement.

"""
function plot_images(imgnt::NamedTuple, whichr::String, whichf::String)
	imghm = heatmap(imgnt.image, title=string("rep=", whichr, " filt=", whichf, " Img" ), titlefontsize=10)

	drkhm = heatmap(imgnt.dark, title=string("rep=", whichr, " filt=", whichf, " Dark" ), titlefontsize=10)

	simghm = heatmap(imgnt.cimage, title=string("rep=", whichr, " filt=", whichf, " Img - Dark" ))

    sdarkhm = heatmap(imgnt.cdark, title=string("rep=", whichr, " filt=", whichf, " Dark - Dark" ))

	plot(imghm, drkhm, simghm, sdarkhm, layout=(2,2), titlefontsize=10)
    xlims!(0,512)
    yticks!([0,250,512])
    xticks!([0,250,512])
    ylims!(0,512)
end

max_stars_repo_name: jjgomezcadenas/LaserLab

max_issues_repo_name: jjgomezcadenas/LaserLab

max_forks_repo_name: jjgomezcadenas/LaserLab


text:
#=
Helper functions that works around the fact, that there is no generic
Table interface for this functionality. Once this is in e.g. Tables.jl,
it should be removed from GeometryBasics!
=#

"""
Gets the column names of any Array like (Table/AbstractArray)
"""
function column_names(t)
    s = Tables.schema(t)
    if s === nothing
        return propertynames(first(Tables.rows(t)))
    else
        s.names
    end
end

function hascolumn(t, colname::Symbol)
    return Base.sym_in(colname, column_names(t))
end

"""
    getcolumns(t, colnames::Symbol...)
Gets a column from any Array like (Table/AbstractArray).
For AbstractVectors, a column will be the field names of the element type.
"""
function getcolumns(t, colnames::Symbol...)
    named_tuple = Tables.columntable(Tables.select(t, colnames...))
    getfield.((named_tuple,), colnames)
end
getcolumn(t, colname::Symbol) = getcolumns(t, colname)[1]

"""
    MetaType(::Type{T})
Returns the Meta Type corresponding to `T`
E.g:
```julia
MetaType(Point) == PointMeta
"""
MetaType(::Type{T}) where T = error("No Meta Type for $T")

"""
    MetaFree(::Type{T})
Returns the original type containing no metadata for `T`
E.g:
```julia
MetaFree(PointMeta) == Point
"""
MetaFree(::Type{T}) where T = error("No meta free Type for $T")

"""
    meta(x::MetaObject)
Returns the metadata of `x`
"""
meta(x::T) where T = error("$T has no meta!")

metafree(x::T) where T = x

macro meta_type(name, mainfield, supertype, params...)
    MetaName = Symbol("$(name)Meta")
    field = QuoteNode(mainfield)
    NoParams = Symbol("$(MetaName)NoParams")
    expr = quote
        struct $MetaName{$(params...), Typ <: $supertype{$(params...)}, Names, Types} <: $supertype{$(params...)}
            main::Typ
            meta::NamedTuple{Names, Types}
        end

        const $NoParams{Typ, Names, Types} = $MetaName{$(params...), Typ, Names, Types} where {$(params...)}

        function Base.getproperty(x::$MetaName{$(params...), Typ, Names, Types}, field::Symbol) where {$(params...), Typ, Names, Types}
            field === $field && return getfield(x, :main)
            field === :main && return getfield(x, :main)
            Base.sym_in(field, Names) && return getfield(getfield(x, :meta), field)
            error("Field $field not part of Element")
        end

        GeometryBasics.MetaType(T::Type{<: $supertype}) = $MetaName{T}
        function GeometryBasics.MetaType(
                ST::Type{<: $supertype{$(params...)}},
                ::Type{NamedTuple{Names, Types}}) where {$(params...), Names, Types}
            return $MetaName{$(params...), ST, Names, Types}
        end

        GeometryBasics.MetaFree(::Type{<: $MetaName{Typ}}) where Typ = Typ
        GeometryBasics.MetaFree(::Type{<: $MetaName}) = $name
        GeometryBasics.metafree(x::$MetaName) = x.main
        GeometryBasics.metafree(x::AbstractVector{<: $MetaName}) = getcolumns(x, $field)[1]
        GeometryBasics.meta(x::$MetaName) = x.meta
        GeometryBasics.meta(x::AbstractVector{<: $MetaName}) = getcolumns(x, :meta)[1]
        function (MT::Type{<: $MetaName})(args...; meta...)
            nt = values(meta)
            obj = MetaFree(MT)(args...)
            return MT(obj, nt)
        end

        function StructArrays.staticschema(::Type{$MetaName{$(params...), Typ, Names, Types}}) where {$(params...), Typ, Names, Types}
            NamedTuple{($field, Names...), Base.tuple_type_cons(Typ, Types)}
        end

        function StructArrays.createinstance(
                ::Type{$MetaName{$(params...), Typ, Names, Types}},
                metafree, args...
            ) where {$(params...), Typ, Names, Types}
            $MetaName(metafree, NamedTuple{Names, Types}(args))
        end

        function GeometryBasics.meta(elements::AbstractVector{T}; meta...) where T <: $supertype
            n = length(elements)
            for (k, v) in meta
                if v isa AbstractVector
                    mn = length(v)
                    mn != n && error("Metadata array needs to have same length as data.
                    Found $(n) data items, and $mn metadata items")
                else
                    error("Metadata needs to be an array with the same length as data items. Found: $(typeof(v))")
                end
            end
            nt = values(meta)
            # get the first element to get the per element named tuple type
            ElementNT = typeof(map(first, nt))

            StructArray{MetaType(T, ElementNT)}(($(mainfield) = elements, nt...))
        end

    end
    return esc(expr)
end

@meta_type(Point, position, AbstractPoint, Dim, T)
Base.getindex(x::PointMeta, idx::Int) = getindex(metafree(x), idx)

@meta_type(NgonFace, ngon, AbstractNgonFace, N, T)
Base.getindex(x::NgonFaceMeta, idx::Int) = getindex(metafree(x), idx)

@meta_type(SimplexFace, simplex, AbstractSimplexFace, N, T)
Base.getindex(x::SimplexFaceMeta, idx::Int) = getindex(metafree(x), idx)

@meta_type(Polygon, polygon, AbstractPolygon, N, T)

"""
    pointmeta(mesh::Mesh; meta_data...)

Attaches metadata to the coordinates of a mesh
"""
function pointmeta(mesh::Mesh; meta_data...)
    Mesh(meta(coordinates(mesh); meta_data...), faces(mesh))
end

"""
    facemeta(mesh::Mesh; meta_data...)

Attaches metadata to the faces of a mesh
"""
function facemeta(mesh::Mesh; meta_data...)
    Mesh(coordinates(mesh), meta(faces(mesh); meta_data...))
end


text:
using Pkg
Pkg.add("Gtk")
using Gtk
win = GtkWindow("Musikalisches_Wurfelspiel.jl", 940, 520)
g=GtkGrid()
a = GtkEntry()  # a widget for entering text
set_gtk_property!(a, :text, "This is Gtk!")
b = GtkButton("Musikalisches_Wurfelspiel")
logo=GtkImage("logo-mozart.png")
label = GAccessor.markup(label,"""
A Musikalisches Würfelspiel (German for "musical dice game") was a  \n system for using dice to randomly generate music from precomposed \n options. These games were quite popular throughout Western Europe in the \n 18th century. Several different games were devised, some that did not require dice,\n but merely choosing a random number.
\n
                          GTK+ website""")
function on_button_clicked(w)
	include("mozart.jl")
end
d = GtkCheckButton("Check me!")
c = GtkScale(false, 0:10)     # a slider
signal_connect(on_button_clicked, b, "clicked")

g[1,1]=label
g[2,1]=logo
g[1,4]=b
g[1,2]=c
g[2,2]=d
g[1:2,3]=a
set_gtk_property!(g, :column_homogeneous, true)
set_gtk_property!(g, :column_spacing, 15)  # introduce a 15-pixel gap between columns
push!(win, g)
showall(win)


text:
push!(LOAD_PATH, "../src")
using Test
using ImplicitGlobalGrid; GG = ImplicitGlobalGrid
import MPI
import ImplicitGlobalGrid: @require

## Test setup (NOTE: Testset "2. initialization including MPI" completes the test setup as it initializes MPI and must therefore mandatorily be at the 2nd position)
p0 = MPI.MPI_PROC_NULL
nx = 4;
ny = 4;
nz = 1;

@testset "$(basename(@__FILE__))" begin
    @testset "1. pre-MPI_Init-exception" begin
        @require !GG.grid_is_initialized()
        @test_throws ErrorException init_global_grid(nx, ny, nz, quiet=true, init_MPI=false);  # Error: init_MPI=false while MPI has not been initialized before.
        @test !GG.grid_is_initialized()
    end;

    @testset "2. initialization including MPI" begin
        me, dims, nprocs, coords, comm_cart = init_global_grid(nx, ny, nz, dimx=1, dimy=1, dimz=1, quiet=true);
        @testset "initialized" begin
            @test GG.grid_is_initialized()
            @test MPI.Initialized()
        end;
        @testset "return values" begin
            @test me     == 0
            @test dims   == [1, 1, 1]
            @test nprocs == 1
            @test coords == [0, 0, 0]
            @test typeof(comm_cart) == MPI.Comm
        end;
        @testset "values in global grid" begin
            @test GG.global_grid().nxyz_g    == [nx, ny, nz]
            @test GG.global_grid().nxyz      == [nx, ny, nz]
            @test GG.global_grid().dims      == dims
            @test GG.global_grid().overlaps  == [2, 2, 2]
            @test GG.global_grid().nprocs    == nprocs
            @test GG.global_grid().me        == me
            @test GG.global_grid().coords    == coords
            @test GG.global_grid().neighbors == [p0 p0 p0; p0 p0 p0]
            @test GG.global_grid().periods   == [0, 0, 0]
            @test GG.global_grid().disp      == 1
            @test GG.global_grid().reorder   == 1
            @test GG.global_grid().comm      == comm_cart
            @test GG.global_grid().quiet     == true
        end;
        finalize_global_grid(finalize_MPI=false);
    end;

    @testset "3. initialization with pre-initialized MPI" begin
        @require MPI.Initialized()
        @require !GG.grid_is_initialized()
        init_global_grid(nx, ny, nz, quiet=true, init_MPI=false);
        @test GG.grid_is_initialized()
        finalize_global_grid(finalize_MPI=false);
    end;

    @testset "4. initialization with periodic boundaries" begin
        nz=4;
        init_global_grid(nx, ny, nz, dimx=1, dimy=1, dimz=1, periodx=1, periodz=1, quiet=true, init_MPI=false);
        @testset "initialized" begin
            @test GG.grid_is_initialized()
        end;
        @testset "values in global grid" begin # (Checks only what is different than in the basic test.)
            @test GG.global_grid().nxyz_g    == [nx-2, ny, nz-2]
            @test GG.global_grid().nxyz      == [nx,   ny, nz  ]
            @test GG.global_grid().neighbors == [0 p0 0; 0 p0 0]
            @test GG.global_grid().periods   == [1, 0, 1]
        end
        finalize_global_grid(finalize_MPI=false);
    end;

    @testset "5. initialization with non-default overlaps and one periodic boundary" begin
        nz  = 8;
        olz = 3;
        olx = 3;
        init_global_grid(nx, ny, nz, dimx=1, dimy=1, dimz=1, periodz=1, overlapx=olx, overlapz=olz, quiet=true, init_MPI=false);
        @testset "initialized" begin
            @test GG.grid_is_initialized()
        end
        @testset "values in global grid" begin # (Checks only what is different than in the basic test.)
            @test GG.global_grid().nxyz_g    == [nx, ny, nz-olz]  # Note: olx has no effect as there is only 1 process and this boundary is not periodic.
            @test GG.global_grid().nxyz      == [nx, ny, nz    ]
            @test GG.global_grid().neighbors == [p0 p0 0; p0 p0 0]
            @test GG.global_grid().periods   == [0, 0, 1]
        end;
        finalize_global_grid(finalize_MPI=false);
    end;

    @testset "6. post-MPI_Init-exceptions" begin
        nx = 4;
        ny = 4;
        nz = 4;
        @test_throws ErrorException init_global_grid(1, ny, nz, quiet=true, init_MPI=false);                         # Error: nx==1.
        @test_throws ErrorException init_global_grid(nx, 1, nz, quiet=true, init_MPI=false);                         # Error: ny==1, while nz>1.
        @test_throws ErrorException init_global_grid(nx, ny, 1, dimz=3, quiet=true, init_MPI=false);                # Error: dimz>1 while nz==1.
        @test_throws ErrorException init_global_grid(nx, ny, 1, periodz=1, quiet=true, init_MPI=false);             # Error: periodz==1 while nz==1.
        @test_throws ErrorException init_global_grid(nx, ny, nz, periody=1, overlapy=3, quiet=true, init_MPI=false); # Error: periody==1 while ny<2*overlapy-1 (4<5).
        @test_throws ErrorException init_global_grid(nx, ny, nz, quiet=true);                                        # Error: MPI already initialized
    end;
end;

## Test tear down
MPI.Finalize()


text:
using Distributed
addprocs(4)
@everywhere include("get_objective_difference_solenoid.jl")
get_JavgN(0.001)

max_stars_repo_name: nishaChandramoorthy/linearResponse

max_issues_repo_name: nishaChandramoorthy/linearResponse

max_forks_repo_name: nishaChandramoorthy/linearResponse


text:
using BenchmarkTools, Coexist

SUITE = BenchmarkGroup()

max_stars_repo_name: vollmersj/coexist-julia

max_forks_repo_name: vollmersj/coexist-julia


text:
function [X,J,dXdx,dXdxI]=JacobiDG2(DG,F,Topo,Param)
ksi=DG.xwX;
eta=DG.xwY;
nX=DG.OrdPolyX+1;
nY=DG.OrdPolyY+1;
X=zeros(nX,nY,3);
dXdx=zeros(nX,nY,2,2);
dXdxI=zeros(nX,nY,2,2);
J=zeros(nX,nY);
for j=1:nY
  for i=1:nX
    X(i,j,1:2)=0.25*((1-ksi(i))*(1-eta(j))*F.P(1:2,1)...
                    +(1+ksi(i))*(1-eta(j))*F.P(1:2,2)...
                    +(1+ksi(i))*(1+eta(j))*F.P(1:2,3)...
                    +(1-ksi(i))*(1+eta(j))*F.P(1:2,4));
    [X(i,j,2),dXdx(i,j,2,2)]=Topo(X(i,j,1),X(i,j,2),Param);
  end
end

dXdx(:,:,1,1)=DG.DSX*X(:,:,1);
dXdx(:,:,2,1)=DG.DSX*X(:,:,2);
dXdx(:,:,1,2)=X(:,:,1)*DG.DSY';
dXdx(:,:,2,2)=X(:,:,2)*DG.DSY';
for j=1:nY
  for i=1:nX
    J(i,j)=det(reshape(dXdx(i,j,:,:),2,2));
    dXdxI(i,j,:,:)=inv(reshape(dXdx(i,j,:,:),2,2))*J(i,j);
  end
end
end


text:
using Test, Random, Statistics, BPMF

Random.seed!(0)

#data
R = [
    0 0 7;
    0 1 6;
    0 2 7;
    0 3 4;
    0 4 5;
    0 5 4;
    1 0 6;
    1 1 7;
    1 3 4;
    1 4 3;
    1 5 4;
    2 1 3;
    2 2 3;
    2 3 1;
    2 4 1;
    3 0 1;
    3 1 2;
    3 2 2;
    3 3 3;
    3 4 3;
    3 5 4;
    4 0 1;
    4 2 1;
    4 3 2;
    4 4 3;
    4 5 3;
]

#################################################################
#       GBPMF
#################################################################
#init parameter
β₀ = 2
μ₀ = 0
D = 3
ν₀ = D
W₀ = one(zeros(D, D))
α = 2
T = 100
N = length(unique(R[:, 1]))
M = length(unique(R[:, 2]))
U = []
V = []

#learning
gibbs_model = BPMF.GBPMFModel(R, N, M, D, T, U, V, α, β₀, μ₀, ν₀, W₀)
BPMF.fit(gibbs_model)
BPMF.predict_all(gibbs_model, 10)
BPMF.predict(gibbs_model, R, 10)

println(sqrt(mean((R[:, 3] - BPMF.predict(gibbs_model, R, 10)) .^ 2)))

#################################################################
#       VBPMF
#################################################################
#init parameter
N = length(unique(R[:, 1]))
M = length(unique(R[:, 2]))
D = 3
τ² = 1
L = 10
U = []
V = []
σ² = []
ρ² = []

#learning
variational_model = BPMF.VBPMFModel(R, N, M, D, L, U, V, τ², σ², ρ²)
BPMF.fit(variational_model)
BPMF.predict(variational_model, R)

println(sqrt(mean((R[:, 3] - BPMF.predict(variational_model, R)) .^ 2)))


text:
# Conjugate models for multivariate normal

using Distributions
using ConjugatePriors

using ConjugatePriors:
    posterior,
    posterior_randmodel,
    NormalWishart,
    NormalInverseWishart

ConjugatePriors.NormalInverseWishart(nix2::NormalInverseChisq) =
    NormalInverseWishart([nix2.μ], nix2.κ, nix2.ν*reshape([nix2.σ2], 1, 1), nix2.ν)

@testset "Conjugate models for multivariate normal" begin

    @testset "MvNormal -- Normal (known covariance)" begin

        n = 3
        p = 4
        X = reshape(Float64[1:12;], p, n)
        w = rand(n)
        Xw = X * Diagonal(w)

        Sigma = 0.75I + fill(0.25, p, p)
        ss = suffstats(MvNormalKnownCov(Sigma), X)
        ssw = suffstats(MvNormalKnownCov(Sigma), X, w)

        s_t = sum(X, dims=2)
        ws_t = sum(Xw, dims=2)
        tw_t = length(w)
        wtw_t = sum(w)

        @test ss.sx ≈ s_t
        @test ss.tw ≈ tw_t

        @test ssw.sx ≈ ws_t
        @test ssw.tw ≈ wtw_t

        # Posterior
        n = 10
        # n = 100
        mu_true = [2., 3.]
        Sig_true = Matrix(1.0I, 2, 2)
        Sig_true[1,2] = Sig_true[2,1] = 0.25
        mu0 = [2.5, 2.5]
        Sig0 = Matrix(1.0I, 2, 2)
        Sig0[1,2] = Sig0[2,1] = 0.5
        X = rand(MultivariateNormal(mu_true, Sig_true), n)
        pri = MultivariateNormal(mu0, Sig0)

        post = posterior((pri, Sig_true), MvNormal, X)
        @test isa(post, FullNormal)

        @test post.μ ≈ inv(inv(Sig0) + n*inv(Sig_true))*(n*inv(Sig_true)*mean(X,dims=2) + inv(Sig0)*mu0)
        @test post.Σ.mat ≈ inv(inv(Sig0) + n*inv(Sig_true))

        # posterior_sample

        ps = posterior_randmodel((pri, Sig_true), MvNormal, X)
        @test isa(ps, FullNormal)
        @test insupport(ps, ps.μ)
        @test insupport(InverseWishart, ps.Σ.mat)

    end

    @testset "NormalInverseWishart - MvNormal" begin

        mu_true = [2., 2.]
        Sig_true = Matrix(1.0I, 2, 2)
        Sig_true[1,2] = Sig_true[2,1] = 0.25

        X = rand(MultivariateNormal(mu_true, Sig_true), n)
        Xbar = mean(X,dims=2)
        Xm = X .- mean(X,dims=2)

        mu0 = [2., 3.]
        kappa0 = 3.
        nu0 = 4.
        T0 = Matrix(1.0I, 2, 2)
        T0[1,2] = T0[2,1] = .5
        pri = NormalInverseWishart(mu0, kappa0, T0, nu0)

        post = posterior(pri, MvNormal, X)

        @test post.mu ≈ (kappa0*mu0 + n*Xbar)./(kappa0 + n)
        @test post.kappa ≈ kappa0 + n
        @test post.nu ≈ nu0 + n
        @test Matrix(post.Lamchol) ≈ T0 + Xm*transpose(Xm) + kappa0*n/(kappa0+n)*(Xbar-mu0)*(Xbar-mu0)'

        ps = posterior_randmodel(pri, MultivariateNormal, X)

        @test isa(ps, MultivariateNormal)
        @test insupport(ps, ps.μ) && insupport(InverseWishart, ps.Σ.mat)

        @testset "Equivalence with Normal-Inverse Chi-squared" begin
            nix2 = NormalInverseChisq(1., 2., 3., 4.)
            niw = NormalInverseWishart(nix2)

            x = rand(Normal(3, 2), 100)

            ss = suffstats(Normal, x)
            ss_mv = suffstats(MvNormal, reshape(x, 1, :))

            post_nix2 = posterior(nix2, ss)
            post_niw = posterior(niw, ss_mv)

            @test all(post_nix2.μ .≈ post_niw.mu)
            @test post_nix2.κ ≈ post_niw.kappa
            @test post_nix2.ν ≈ post_niw.nu
            @test all(post_nix2.σ2 .≈ Matrix(post_niw.Lamchol)[1] ./ post_niw.nu)

            μ, σ2 = rand(post_nix2)
            @test logpdf(post_nix2, μ, σ2) ≈ logpdf(post_niw, [μ], reshape([σ2], 1, 1))
            @test logpdf(nix2, μ, σ2) ≈ logpdf(niw, [μ], reshape([σ2], 1, 1))

        end

    end

    @testset "NormalWishart - MvNormal" begin

        mu_true = [2., 2.]
        Lam_true = Matrix(1.0I, 2, 2)
        Lam_true[1,2] = Lam_true[2,1] = 0.25

        X = rand(MvNormal(mu_true, inv(Lam_true)), n)
        Xbar = mean(X,dims=2)
        Xm = X .- Xbar

        mu0 = [2., 3.]
        kappa0 = 3.
        nu0 = 4.
        T0 = Matrix(1.0I, 2, 2)
        T0[1,2] = T0[2,1] = .5
        pri = NormalWishart(mu0, kappa0, T0, nu0)

        post = posterior(pri, MvNormal, X)

        @test post.mu ≈ (kappa0*mu0 + n*Xbar)./(kappa0 + n)
        @test post.kappa ≈ kappa0 + n
        @test post.nu ≈ nu0 + n
        @test Matrix(post.Tchol) ≈ T0 + Xm*transpose(Xm) + kappa0*n/(kappa0+n)*(Xbar-mu0)*(Xbar-mu0)'

        ps = posterior_randmodel(pri, MvNormal, X)

        @test isa(ps, MultivariateNormal)
        @test insupport(ps, ps.μ)
        @test insupport(InverseWishart, ps.Σ.mat)  # InverseWishart on purpose

    end
end


text:
function surf3(gr::Graph, v::cmgl.Float, a::Array{cmgl.Float, 3}; stl::String="", opt::String="")
    cmgl.surf3_val(gr.ptr, v, Data(a).ptr, stl, opt)
end

function surf3(gr::Graph, v::cmgl.Float, x::Array{cmgl.Float}, y::Array{cmgl.Float}, z::Array{cmgl.Float}, a::Array{cmgl.Float, 3}; stl::String="", opt::String="")
    cmgl.surf3_xyz_val(gr.ptr, v, Data(x).ptr, Data(y).ptr, Data(z).ptr, Data(a).ptr, stl, opt)
end

function surf3(gr::Graph, v::Array{cmgl.Float, 1}, a::Array{cmgl.Float, 3}; stl::String="", opt::String="")
    for val in v
        cmgl.surf3_val(gr.ptr, val, Data(a).ptr, stl, opt)
    end
end

function surf3(gr::Graph, v::Array{cmgl.Float, 1}, x::Array{cmgl.Float}, y::Array{cmgl.Float}, z::Array{cmgl.Float}, a::Array{cmgl.Float, 3}; stl::String="", opt::String="")
    for val in v
        cmgl.surf3_xyz_val(gr.ptr, val, Data(x).ptr, Data(y).ptr, Data(z).ptr, Data(a).ptr, stl, opt)
    end
end

function surf3(gr::Graph, a::Array{cmgl.Float, 3}; stl::String="", opt::String="")
    cmgl.surf3(gr.ptr, Data(a).ptr, stl, opt)
end

function surf3(gr::Graph, x::Array{cmgl.Float}, y::Array{cmgl.Float}, z::Array{cmgl.Float}, a::Array{cmgl.Float, 3}; stl::String="", opt::String="")
    cmgl.surf3_xyz(gr.ptr, Data(x).ptr, Data(y).ptr, Data(z).ptr, Data(a).ptr, stl, opt)
end

function cloud(gr::Graph, a::Array{cmgl.Float, 3}; stl::String="", opt::String="")
    cmgl.cloud(gr.ptr, Data(a).ptr, stl, opt)
end

function cloud(gr::Graph, x::Array{cmgl.Float}, y::Array{cmgl.Float}, z::Array{cmgl.Float}, a::Array{cmgl.Float, 3}; stl::String="", opt::String="")
    cmgl.cloud_xyz(gr.ptr, Data(x).ptr, Data(y).ptr, Data(z).ptr, Data(a).ptr, stl, opt)
end

function dens3(gr::Graph, a::Array{cmgl.Float, 3}; sval::cmgl.Float=-1, stl::String="", opt::String="")
    cmgl.dens3(gr.ptr, Data(a).ptr, stl, sval, opt)
end

function dens3(gr::Graph, x::Array{cmgl.Float}, y::Array{cmgl.Float}, z::Array{cmgl.Float}, a::Array{cmgl.Float, 3}; sval::cmgl.Float=-1, stl::String="", opt::String="")
    cmgl.dens3_xyz(gr.ptr, Data(x).ptr, Data(y).ptr, Data(z).ptr, Data(a).ptr, stl, sval, opt)
end

function cont3(gr::Graph, v::Array{cmgl.Float, 1}, a::Array{cmgl.Float, 3}; sval::cmgl.Float=-1, stl::String="", opt::String="")
    cmgl.cont3_val(gr.ptr, Data(v).ptr, Data(a).ptr, stl, sval, opt)
end

function cont3(gr::Graph, v::Array{cmgl.Float, 1}, x::Array{cmgl.Float}, y::Array{cmgl.Float}, z::Array{cmgl.Float}, a::Array{cmgl.Float, 3}; sval::cmgl.Float=-1, stl::String="", opt::String="")
    cmgl.cont3_xyz_val(gr.ptr, Data(v).ptr, Data(x).ptr, Data(y).ptr, Data(z).ptr, Data(a).ptr, stl, sval, opt)
end

function cont3(gr::Graph, v::cmgl.Float, a::Array{cmgl.Float, 3}; sval::cmgl.Float=-1, stl::String="", opt::String="")
    cmgl.cont3_val(gr.ptr, Data(cmgl.Float[v]).ptr, Data(a).ptr, stl, sval, opt)
end

function cont3(gr::Graph, v::cmgl.Float, x::Array{cmgl.Float}, y::Array{cmgl.Float}, z::Array{cmgl.Float}, a::Array{cmgl.Float, 3}; sval::cmgl.Float=-1, stl::String="", opt::String="")
    cmgl.cont3_xyz_val(gr.ptr, Data(cmgl.Float[v]).ptr, Data(x).ptr, Data(y).ptr, Data(z).ptr, Data(a).ptr, stl, sval, opt)
end

function cont3(gr::Graph, a::Array{cmgl.Float, 3}; sval::cmgl.Float=-1, stl::String="", opt::String="")
    cmgl.cont3(gr.ptr, Data(a).ptr, stl, sval, opt)
end

function cont3(gr::Graph, x::Array{cmgl.Float}, y::Array{cmgl.Float}, z::Array{cmgl.Float}, a::Array{cmgl.Float, 3}; sval::cmgl.Float=-1, stl::String="", opt::String="")
    cmgl.cont3_xyz(gr.ptr, Data(x).ptr, Data(y).ptr, Data(z).ptr, Data(a).ptr, stl, sval, opt)
end

function contf3(gr::Graph, v::Array{cmgl.Float, 1}, a::Array{cmgl.Float, 3}; sval::cmgl.Float=-1, stl::String="", opt::String="")
    cmgl.contf3_val(gr.ptr, Data(v).ptr, Data(a).ptr, stl, sval, opt)
end

function contf3(gr::Graph, v::Array{cmgl.Float, 1}, x::Array{cmgl.Float}, y::Array{cmgl.Float}, z::Array{cmgl.Float}, a::Array{cmgl.Float, 3}; sval::cmgl.Float=-1, stl::String="", opt::String="")
    cmgl.contf3_xyz_val(gr.ptr, Data(v).ptr, Data(x).ptr, Data(y).ptr, Data(z).ptr, Data(a).ptr, stl, sval, opt)
end

function contf3(gr::Graph, v::cmgl.Float, a::Array{cmgl.Float, 3}; sval::cmgl.Float=-1, stl::String="", opt::String="")
    cmgl.contf3_val(gr.ptr, Data(cmgl.Float[v]).ptr, Data(a).ptr, stl, sval, opt)
end

function contf3(gr::Graph, v::cmgl.Float, x::Array{cmgl.Float}, y::Array{cmgl.Float}, z::Array{cmgl.Float}, a::Array{cmgl.Float, 3}; sval::cmgl.Float=-1, stl::String="", opt::String="")
    cmgl.contf3_xyz_val(gr.ptr, Data(cmgl.Float[v]).ptr, Data(x).ptr, Data(y).ptr, Data(z).ptr, Data(a).ptr, stl, sval, opt)
end

function contf3(gr::Graph, a::Array{cmgl.Float, 3}; sval::cmgl.Float=-1, stl::String="", opt::String="")
    cmgl.contf3(gr.ptr, Data(a).ptr, stl, sval, opt)
end

function contf3(gr::Graph, x::Array{cmgl.Float}, y::Array{cmgl.Float}, z::Array{cmgl.Float}, a::Array{cmgl.Float, 3}; sval::cmgl.Float=-1, stl::String="", opt::String="")
    cmgl.contf3_xyz(gr.ptr, Data(x).ptr, Data(y).ptr, Data(z).ptr, Data(a).ptr, stl, sval, opt)
end

function grid3(gr::Graph, a::Array{cmgl.Float, 3}; sval::cmgl.Float=-1, stl::String="", opt::String="")
    cmgl.grid3(gr.ptr, Data(a).ptr, stl, sval, opt)
end

function grid3(gr::Graph, x::Array{cmgl.Float}, y::Array{cmgl.Float}, z::Array{cmgl.Float}, a::Array{cmgl.Float, 3}; sval::cmgl.Float=-1, stl::String="", opt::String="")
    cmgl.grid3_xyz(gr.ptr, Data(x).ptr, Data(y).ptr, Data(z).ptr, Data(a).ptr, stl, sval, opt)
end

function beam(gr::Graph, tr::Array{cmgl.Float}, g1::Array{cmgl.Float}, g2::Array{cmgl.Float}, a::Array{cmgl.Float, 3}, r::Array{cmgl.Float}; stl::String="", flag::Int=0, num::Int=3)
    cmgl.beam(gr.ptr, Data(tr).ptr, Data(g1).ptr, Data(g2).ptr, Data(a).ptr, Data(r).ptr, stl, flag, num)
end

function beam(gr::Graph, v::Array{cmgl.Float, 1}, tr::Array{cmgl.Float}, g1::Array{cmgl.Float}, g2::Array{cmgl.Float}, a::Array{cmgl.Float, 3}, r::Array{cmgl.Float}; stl::String="", flag::Int=0)
    cmgl.beam_val(gr.ptr, Data(v).ptr, Data(tr).ptr, Data(g1).ptr, Data(g2).ptr, Data(a).ptr, Data(r).ptr, stl, flag)
end


text:
using Images, FileIO

ppmimg = load("data/bitmapInputTest.ppm")
save("data/bitmapOutputTest.jpg", ppmimg)

max_stars_repo_name: ethansaxenian/RosettaDecode

max_issues_repo_name: ethansaxenian/RosettaDecode

max_forks_repo_name: ethansaxenian/RosettaDecode


text:
using DomainSets, BasisFunctions, FrameFun
using Test

@testset "Platform approximation problems" begin
    ap1 = approximationproblem(Fourier(10))
    ap2 = approximationproblem(Fourier(10)^2)
    ap3 = approximationproblem(platform(Fourier(10)),10)
    ap4 = approximationproblem(Fourier(10), 0.0..0.5)
    ap5 = approximationproblem(Fourier(10), 20; samplingstyle=OversamplingStyle())

    @test length(factors(ap2))==2

    for ap in (ap1, ap2, ap3, ap4)
        @test !FrameFun.ap_hasproperty(ap, samplingparameter)
    end
    @test FrameFun.ap_hasproperty(ap5, samplingparameter)

    for ap in (ap1, ap2, ap3, ap4)
        if platform(ap) isa ProductPlatform
            FrameFun.cache!(ap, samplingparameter, (10,10))
        else
            FrameFun.cache!(ap, samplingparameter, 10)
        end
    end

    @test SamplingStyle(ap1) == InterpolationStyle()
    @test SamplingStyle(ap2) == ProductSamplingStyle(InterpolationStyle(),InterpolationStyle())
    @test SamplingStyle(ap3) == InterpolationStyle()
    @test SamplingStyle(ap4) == OversamplingStyle()
    @test SamplingStyle(ap5) == OversamplingStyle()

    @test SolverStyle(ap1) == InverseStyle()
    @test SolverStyle(ap2) == ProductSolverStyle(InverseStyle(),InverseStyle())
    @test SolverStyle(ap3) == InverseStyle()
    @test SolverStyle(ap4) == AZStyle()
    @test SolverStyle(ap5) == DirectStyle() # TODO: make this into an efficient least squares solver

    for ap in (ap1, ap2, ap3, ap4, ap5)
        @test FrameFun.ap_hasproperty(ap, samplingparameter)
    end

    @test dictionary(ap1) == Fourier(10)
    @test dictionary(ap2) == Fourier(10)^2
    @test dictionary(ap3) == Fourier(10)
    @test iscompatible(dictionary(ap4), extensionframe(Fourier(10), 0.0..0.5))
    @test dictionary(ap5) == Fourier(10)
end

@testset "Adaptive approximation problems" begin
    ap1 = approximationproblem(platform(Fourier(10)))
    ap2 = approximationproblem(platform(Fourier(10)^2))
    ap3 = approximationproblem(platform(extensionframe(Fourier(10), 0.0..0.5)))
    ap4 = approximationproblem(platform(Fourier(10)); samplingstyle=OversamplingStyle())

    for ap in (ap1,ap2,ap3,ap4)
        @test ap isa FrameFun.AdaptiveApproximation
    end

    @test dictionary(ap1,10)== Fourier(10)
    @test dictionary(ap2,10)== Fourier(10)^2
    @test iscompatible(dictionary(ap3,10),extensionframe(Fourier(10), 0.0..0.5))
    @test dictionary(ap4,10)== Fourier(10)

    @test SamplingStyle(ap1) == InterpolationStyle()
    @test SamplingStyle(ap4) == OversamplingStyle()
    ap1b = approximationproblem(ap1, 20)
    ap4b = approximationproblem(ap4, 20)
    @test ap1b isa FrameFun.PlatformApproximation
    @test ap4b isa FrameFun.PlatformApproximation
    @test SamplingStyle(ap1b) == InterpolationStyle()
    @test SamplingStyle(ap4b) == OversamplingStyle()
end


text:
module FieldMetadata

export @metadata, @chain

struct MetadataError <: Exception
    var::String
end

Base.showerror(io::IO, e::MetadataError) = print(io, e.var)

"""
    @metadata name default [type=Any]

Generate a macro that constructs methods of the same name.
These methods return the metadata information provided for each
field of the struct.

If no method is definjed for a type or field, the default value
is used. If a type is passed to the macro, the type of metadata will be checked
when it is loaded with the method. The default type is `Any`.

```julia
@metadata def_range (0, 0) Tuple
@def_range struct Model
    a::Int | (1, 4)
    b::Int | (4, 9)
end

model = Model(3, 5)
def_range(model, Val{:a})
(1, 4)

def_range(model)
((1, 4), (4, 9))
```
"""
macro metadata(name, default, checktyp=Any)
    symname = QuoteNode(name)
    default = esc(default)
    name = esc(name)
    checktyp = esc(checktyp)
    return quote
        macro $name(expr)
            name = $symname
            return funcs_from_unknown(expr, name, $checktyp)
        end

        macro $name(typ, expr)
            name = $symname
            return funcs_from_block(typ, expr, name, $checktyp)
        end

        # Single field methods
        @inline $name(x, key) = $default
        @inline $name(x::Type, key::Type) = $default
        @inline $name(::X, key::Symbol) where X = $name(X, Val{key})
        @inline $name(::X, key::Type) where X = $name(X, key)
        @inline $name(::Type{X}, key::Symbol) where X = $name(X, Val{key})

        # All field methods
        @inline $name(::X) where X = $name(X)
        @inline $name(x::Type{X}) where X = $name(X, fieldname_vals(X))
        @inline $name(::Type{X}, keys::Tuple) where X =
            ($name(X, keys[1]), $name(X, Base.tail(keys))...)
        @inline $name(::Type{X}, keys::Tuple{}) where X = tuple()
    end
end

"""
Chain together any macros. Useful for combining @metadata macros.

### Example
```julia
@chain columns @label @units @default_kw

@columns struct Foo
  bar::Int | 7 | u"g" | "grams of bar"
end
```
"""
macro chain(name, ex)
    macros = reverse(chained_macros(ex))
    return quote
        macro $(esc(name))(ex)
            for mac in $macros
                ex = Expr(:macrocall, mac, LineNumberNode(80, "FieldMetadata.jl"), ex)
            end
            esc(ex)
        end
        macro $(esc(name))(typ, ex)
            for mac in $macros
                ex = Expr(:macrocall, mac, LineNumberNode(87, "FieldMetadata.jl"), typ, ex)
            end
            esc(ex)
        end
    end
end

Base.@pure fieldname_vals(::Type{X}) where X = ([Val{fn} for fn in fieldnames(X)]...,)

function funcs_from_unknown(expr::Expr, name::Symbol, checktyp; update=false)
    macros = chained_macros(expr)
    typ = firsthead(x -> namify(x.args[2]), expr, :struct)
    # If there is no struct this is a begin block with chained macros
    if typ === nothing
        typ = if length(macros) > 0
            findexpr = expr
            for i in 1:length(macros) - 1
                findexpr = findexpr.args[3]
            end
            findexpr.args[3]
        else
            error("incorrect arguments for @$name")
        end
        update = true
    end
    func_exprs = Expr[]
    # Getting the block is the same whatever the format
    firsthead(expr, :block) do block
        parseblock!(block, func_exprs, name, typ, checktyp)
    end
    if length(macros) == 0
        if update
            Expr(:block, func_exprs...)
        else
            Expr(:block, :(Base.@__doc__ $(esc(expr))), func_exprs...)
        end
    else
        Expr(:block, esc(expr), func_exprs...)
    end
end

function funcs_from_block(objtyp::Union{Symbol,Expr}, expr::Expr, name::Symbol, checktyp)
    macros = chained_macros(objtyp)
    # if !(objtyp isa Symbol) && objtyp.head == :call
        # ojbtyp = eval(typ)
    # end
    func_exprs = Expr[]
    firsthead(expr, :block) do block
        parseblock!(block, func_exprs, name, objtyp, checktyp)
    end
    if length(macros) == 0
        Expr(:block, func_exprs...)
    else
        Expr(:block, esc(typ), esc(ex), func_exprs...)
    end
end

# Parse the block: and Function expressions are built for each line,
# and one layer of metadata is removed. Both arguments are modified.
function parseblock!(block::Expr, exprs::Vector, method::Symbol, typ::Union{Symbol,Expr}, checktyp)
    for (i, line) in enumerate(block.args)
        :head in fieldnames(typeof(line)) || continue
        # Allow Parameters.jl to coexist
        if line.head == :(=)
            # The fieldname is the first arg
            fn = line.args[1]
            # Make sure this is a field
            if fn isa Symbol || fn.head == :(::)
                key = getkey(fn)
                # Then make sure its a call to |
                expr = line.args[2]
                if expr.head == :call && expr.args[1] == :(|)
                    process_equals_line!(exprs, line, expr, key, method, typ, checktyp)
                end
            end
        elseif line.head == :call && line.args[1] == :(|)
            process_bar_line!(exprs, block.args, method, typ, checktyp, i)
        end
    end
end

function process_equals_line!(exprs, parent, expr, key, method, typ, checktyp)
    child = expr.args[2]
    if child isa Expr && child.head == :call && child.args[1] == :(|)
        process_equals_line!(exprs, expr, child, key, method, typ, checktyp)
    else
        val = expr.args[3]
        val == :_ || addmethod!(exprs, method, typ, checktyp, key, val)
        # Replace the rest of the line after the = call
        parent.args[2] = child
    end
end

# exprs, line and block may all be mutated
function process_bar_line!(exprs, args, method, typ, checktyp, i)
    expr = args[i]
    if expr.head == :call && expr.args[1] == :(|)
        child = expr.args[2]
        if child isa Symbol
            key = child
            val = expr.args[3]
            val == :_ || addmethod!(exprs, method, typ, checktyp, key, val)
            args[i] = key
        elseif child.head != :call
            # Replace the line with the field
            key = getkey(child)
            val = expr.args[3]
            val == :_ || addmethod!(exprs, method, typ, checktyp, key, val)
            expr.head = child.head
            expr.args = child.args
        else
            process_bar_line!(exprs, expr.args, method, typ, checktyp, 2)
        end
    else
        error("expression is not a | : `$expr`")
    end
end

function addmethod!(exprs, method, typ, checktyp, key, value)
    func = quote
        @inline function $method(::Type{<:$typ}, ::Type{Val{$(QuoteNode(key))}})
            value = $value
            value isa $checktyp || FieldMetadata.metadata_error($typ, $checktyp, $(QuoteNode(key)), value)
            value
        end
    end
    push!(exprs, esc(func))
end

@noinline metadata_error(typ, checktyp, key, value) =
    throw(MetadataError("$value of type $(typeof(value)) is not in $checktyp for key $key in $typ"))

# Field could be just the name `a`
getkey(ex::Symbol) = ex
# Or the name and type `a::T`, or somethng else
getkey(ex::Expr) = firsthead(y -> y.args[1], ex, :(::))

chained_macros(ex) = chained_macros!(Symbol[], ex)
function chained_macros!(macros, ex::Expr)
    if ex.head == :macrocall
        push!(macros, ex.args[1])
        length(ex.args) > 2 && chained_macros!(macros, ex.args[3])
    end
    macros
end
chained_macros!(macros, ex::Symbol) = Symbol[]

function firsthead(f, ex::Expr, sym)
    if ex.head == sym
        out = f(ex)
        return out
    else
        for arg in ex.args
            x = firsthead(f, arg, sym)
            x == nothing || return x
        end
        return nothing
    end
end
firsthead(f, ex, sym) = nothing

namify(x) = x
namify(x::Expr) = namify(x.args[1])

# FieldMetadata api
@metadata default nothing
@metadata units 1
@metadata prior nothing
@metadata label "" AbstractString
@metadata description "" AbstractString
@metadata limits (0.0, 1.0) Tuple
@metadata bounds (0.0, 1.0) Tuple
@metadata logscaled false Bool
@metadata flattenable true Bool
@metadata plottable true Bool
@metadata selectable Nothing

# Set the default label to be the field name
label(x::Type, ::Type{Val{F}}) where F = F

end # module


text:
using ControlSystems

"""
    y = simulateHBF(x, f1, f2, mode=0)

Simulate a Saramaki half-band filter.

The `f1` and `f2` vectors contain coefficients for the structure. (`f1` and `f2`
can each also be a tuple of arrays (val, csd) where the first array contains the
coeffiecients).

The `mode` flag determineswhether the input is filtered, interpolated, or
decimated according to the following table:
- `mode` = 0:   Plain filtering, no interpolation or decimation.
- `mode` = 1:   The input is interpolated.
- `mode` = 2:   The output is decimated, even samples are taken.
- `mode` = 3:   The output is decimated, odd samples are taken.
"""
function simulateHBF(x, f1=NaN, f2=NaN, mode=0)
    if f1 isa Number && isnan(f1)
        f1, f2 = exampleHBF(4)
    end
    if f1 isa Tuple # Presume that f1 is a (val, csd) tuple
        f1 = f1[1]
    end
    if f2 isa Tuple # Presume that f2 is a (val, csd) tuple
        f2 = f2[1]
    end

    n1 = length(f1)
    n2 = length(f2)
    f2imp = [f2[end:-1:1]; f2]
    if mode == 0    # Insert zeros
        f2imp = [f2imp'; zeros(1, 2*n2)]
        f2imp = f2imp[1:4*n2-1]
    end
    F2 = tf(f2imp, [1; zeros(length(f2imp)-1)], 1)

    if mode == 0    # Plain
        up, = lsim(F2, x, 1:length(x))[:]
        y = 0.5 * delay(x, 2*n2-1) + f1[1] * up
        for i = 2:n1
            up, = lsim(F2, up, 1:length(up))
            up, = lsim(F2, up, 1:length(up))
            y = f1[i] * up + delay(y, 4*n2-2)
        end

    elseif mode == 1    # Interpolating
        up = zeros(size(x))
        nz = 2*n2 - 1
        for i = n1:-1:1
            if i == 1
                up, = lsim(F2, up + f1[i] * x, 1:length(x))
                nz = n2 - 1
            else
                up, = lsim(F2, up + f1[i] * x, 1:length(x))
                up, = lsim(F2, up, 1:length(up))
            end
            x = delay(x, nz)
        end
        y = [2*up'; x']
        y = y[:]    # Interleave the upper and lower streams

    elseif mode == 2 || mode == 3   # Decimating
        x = x[1:2*(end÷2)]
        if mode == 3
            y = 0.5 * x[1:2:end]
            up = x[2:2:end]
            nz = n2 - 1
        else
            y = 0.5 * x[2:2:end]
            up = x[1:2:end]
            nz = n2
        end
        for i = 1:n1
            if i == 1
                up, = lsim(F2, up, 1:length(up))
            else
                up, = lsim(F2, up, 1:length(up))
                up, = lsim(F2, up, 1:length(up))
            end
            y = f1[i] * up + delay(y, nz)
            nz = 2 * n2 - 1
        end

    else
        throw(ArgumentError("$mode is not a valid value for the mode variable."))
    end

    return y[:]
end

max_stars_repo_name: Mahmoud-Kharsa/DeltaSigma

max_issues_repo_name: Mahmoud-Kharsa/DeltaSigma

max_forks_repo_name: Mahmoud-Kharsa/DeltaSigma