diff --git a/src/io/sampling.jl b/src/io/sampling.jl index 37a153320..1e2808de2 100644 --- a/src/io/sampling.jl +++ b/src/io/sampling.jl @@ -395,10 +395,18 @@ function fix_factor!(d::Domain, factor::Symbol, val::Real)::Nothing return nothing end function fix_factor!(d::Domain, factors::Vector{Symbol})::Nothing - for f in factors - fix_factor!(d, f) - end + params = DataFrame(d.model) + factor_rows = findall(in(factors), params.fieldname) + + # Get current values and dist_params lengths + vals = params[factor_rows, :val] + dist_lens = length.(params[factor_rows, :dist_params]) + # Create new dist_params tuples + new_params = [Tuple(fill(v, len)) for (v, len) in zip(vals, dist_lens)] + params[factor_rows, :dist_params] .= new_params + + update!(d, params) return nothing end function fix_factor!(d::Domain; factors...)::Nothing @@ -480,8 +488,8 @@ function get_attr(dom::Domain, factor::Symbol, attr::Symbol) end """ - set_factor_bounds(dom::Domain, factor::Symbol, new_bounds::Tuple)::Nothing - set_factor_bounds(dom::Domain; factors...)::Nothing + set_factor_bounds!(dom::Domain, factor::Symbol, new_bounds::Tuple)::Nothing + set_factor_bounds!(dom::Domain; factors...)::Nothing Set new bound values for a given parameter. Sampled values for a parameter will lie within the range `lower_bound ≤ s ≤ upper_bound`, for every sample value `s`. @@ -504,6 +512,13 @@ set_factor_bounds(dom, :wave_stress, (0.1, 0.2)) ``` """ function set_factor_bounds(dom::Domain, factor::Symbol, new_dist_params::Tuple)::Domain + Base.@warn "set_factor_bounds is deprecated, use set_factor_bounds! instead" maxlog = + 1 _category = :deprecation + + set_factor_bounds!(dom, factor, new_dist_params) + return dom +end +function set_factor_bounds!(dom::Domain, factor::Symbol, new_dist_params::Tuple)::Domain old_val = get_attr(dom, factor, :val) new_val = mean(new_dist_params[1:2]) @@ -514,14 +529,36 @@ function set_factor_bounds(dom::Domain, factor::Symbol, new_dist_params::Tuple): ms[!, :is_constant] .= (ms[!, :lower_bound] .== ms[!, :upper_bound]) update!(dom, ms) - return dom end + function set_factor_bounds(dom::Domain; factors...)::Domain - for (factor, bounds) in factors - dom = set_factor_bounds(dom, factor, bounds) - end + Base.@warn "set_factor_bounds is deprecated, use set_factor_bounds! instead" maxlog = + 1 _category = :deprecation + set_factor_bounds!(dom; factors...) + return dom +end +function set_factor_bounds!(dom::Domain; factors...)::Domain + ms = model_spec(dom) + factor_symbols = collect(keys(factors)) + factor_rows = findall(in(factor_symbols), ms.fieldname) + + # Update dist_params and values in bulk + new_params = collect(values(factors)) + ms[factor_rows, :dist_params] .= new_params + + # Calculate new values preserving types + old_vals = ms[factor_rows, :val] + new_vals = mean.(zip(first.(new_params), last.(new_params))) + ms[factor_rows, :val] .= [ + v isa Int ? round(n) : n for (v, n) in zip(old_vals, new_vals) + ] + + # Update `is_constant` column + ms[!, :is_constant] .= (ms[!, :lower_bound] .== ms[!, :upper_bound]) + + update!(dom, ms) return dom end diff --git a/test/sampling.jl b/test/sampling.jl index dc95cf3ba..43e90629d 100644 --- a/test/sampling.jl +++ b/test/sampling.jl @@ -199,7 +199,7 @@ end end @testset "Set new sampling bounds" begin - set_factor_bounds = ADRIA.set_factor_bounds + set_factor_bounds! = ADRIA.set_factor_bounds! dom = ADRIA.load_domain(TEST_DOMAIN_PATH) num_samples = 32 @@ -223,10 +223,10 @@ end factors = ms[factor_mask, :] factor_fieldnames = (factors.fieldname...,) - @testset "set_factor_bounds" begin + @testset "set_factor_bounds!" begin bounds_ranges = [range(b[1], b[2], 5) for b in factors.default_dist_params] new_bounds = Tuple.(sort.(rand.(bounds_ranges, 2))) - dom = set_factor_bounds(dom; NamedTuple{factor_fieldnames}(new_bounds)...) + dom = set_factor_bounds!(dom; NamedTuple{factor_fieldnames}(new_bounds)...) scens = ADRIA.sample_guided(dom, num_samples) _test_bounds(scens, factor_mask, bounds_ranges) @@ -235,7 +235,7 @@ end @testset "set to default bounds" begin new_bounds = ADRIA.get_attr.([dom], factor_fieldnames, [:default_dist_params]) - dom = set_factor_bounds(dom; NamedTuple{factor_fieldnames}(new_bounds)...) + dom = set_factor_bounds!(dom; NamedTuple{factor_fieldnames}(new_bounds)...) factor_params = dom.model[ms.fieldname .∈ [factor_fieldnames]][1] @test all(factor_params.dist_params .== factor_params.default_dist_params) @@ -250,10 +250,10 @@ end factors = ms[factor_mask, :] factor_fieldnames = (factors.fieldname...,) - @testset "set_factor_bounds" begin + @testset "set_factor_bounds!" begin bounds_ranges = [b[1]:b[2] for b in factors.default_dist_params] new_bounds = Tuple.(sort.(rand.(bounds_ranges, 2))) - dom = set_factor_bounds(dom; NamedTuple{factor_fieldnames}(new_bounds)...) + dom = set_factor_bounds!(dom; NamedTuple{factor_fieldnames}(new_bounds)...) scens = ADRIA.sample_guided(dom, num_samples) _test_bounds(scens, factor_mask, bounds_ranges) @@ -262,7 +262,7 @@ end @testset "get_default_dist_params" begin new_bounds = ADRIA.get_attr.([dom], factor_fieldnames, [:default_dist_params]) - dom = set_factor_bounds(dom; NamedTuple{factor_fieldnames}(new_bounds)...) + dom = set_factor_bounds!(dom; NamedTuple{factor_fieldnames}(new_bounds)...) factor_params = dom.model[ms.fieldname .∈ [factor_fieldnames]][1] @test all(factor_params.dist_params .== factor_params.default_dist_params) @@ -279,12 +279,12 @@ end ms.dist .== ADRIA.DiscreteOrderedUniformDist factors = ms[factor_mask, :] factor_fieldnames = (factors.fieldname...,) - @testset "set_factor_bounds" begin + @testset "set_factor_bounds!" begin bounds_ranges = [b[1]:b[2] for b in factors.default_dist_params] new_bounds = Tuple.(sort.(rand.(bounds_ranges, 2))) new_steps = [ceil((nb[2] - nb[1]) / 10) for nb in new_bounds] new_dist_params = [(b[1], b[2], s) for (b, s) in zip(new_bounds, new_steps)] - dom = set_factor_bounds( + dom = set_factor_bounds!( dom; NamedTuple{factor_fieldnames}(new_dist_params)... ) scens = ADRIA.sample_guided(dom, num_samples) @@ -295,7 +295,7 @@ end @testset "get_default_dist_params" begin new_bounds = ADRIA.get_attr.([dom], factor_fieldnames, [:default_dist_params]) - dom = set_factor_bounds(dom; NamedTuple{factor_fieldnames}(new_bounds)...) + dom = set_factor_bounds!(dom; NamedTuple{factor_fieldnames}(new_bounds)...) factor_params = dom.model[ms.fieldname .∈ [factor_fieldnames]][1] @test all(factor_params.dist_params .== factor_params.default_dist_params) @@ -309,13 +309,13 @@ end factor_mask = ms.component .∈ [test_components] .&& ms.dist .== TriangularDist factors = ms[factor_mask, :] factor_fieldnames = (factors.fieldname...,) - @testset "set_factor_bounds" begin + @testset "set_factor_bounds!" begin bounds_ranges = [range(b[1], b[2], 5) for b in factors.default_dist_params] new_bounds = Tuple.(sort.(rand.(bounds_ranges, 2))) mode_ranges = [range(nb[1], nb[2], 5) for nb in new_bounds] new_modes = (rand.(mode_ranges)) new_dist_params = [(b[1], b[2], p) for (b, p) in zip(new_bounds, new_modes)] - dom = set_factor_bounds( + dom = set_factor_bounds!( dom; NamedTuple{factor_fieldnames}(new_dist_params)... ) scens = ADRIA.sample_guided(dom, num_samples) @@ -326,7 +326,7 @@ end @testset "get_default_dist_params" begin new_bounds = ADRIA.get_attr.([dom], factor_fieldnames, [:default_dist_params]) - dom = set_factor_bounds(dom; NamedTuple{factor_fieldnames}(new_bounds)...) + dom = set_factor_bounds!(dom; NamedTuple{factor_fieldnames}(new_bounds)...) factor_params = dom.model[ms.fieldname .∈ [factor_fieldnames]][1] @test all(factor_params.dist_params .== factor_params.default_dist_params) @@ -342,13 +342,13 @@ end ms.dist .== ADRIA.DiscreteTriangularDist factors = ms[factor_mask, :] factor_fieldnames = (factors.fieldname...,) - @testset "set_factor_bounds" begin + @testset "set_factor_bounds!" begin bounds_ranges = [b[1]:b[2] for b in factors.default_dist_params] new_bounds = Tuple.(sort.(rand.(bounds_ranges, 2))) new_mode_ranges = [nb[1]:nb[2] for nb in new_bounds] new_peaks = (rand.(new_mode_ranges)) new_dist_params = [(b[1], b[2], p) for (b, p) in zip(new_bounds, new_peaks)] - dom = set_factor_bounds( + dom = set_factor_bounds!( dom; NamedTuple{factor_fieldnames}(new_dist_params)... ) scens = ADRIA.sample_guided(dom, num_samples) @@ -359,7 +359,7 @@ end @testset "get_default_dist_params" begin new_bounds = ADRIA.get_attr.([dom], factor_fieldnames, [:default_dist_params]) - dom = set_factor_bounds(dom; NamedTuple{factor_fieldnames}(new_bounds)...) + dom = set_factor_bounds!(dom; NamedTuple{factor_fieldnames}(new_bounds)...) factor_params = dom.model[ms.fieldname .∈ [factor_fieldnames]][1] @test all(factor_params.dist_params .== factor_params.default_dist_params)