diff --git a/src/fitting/binding.jl b/src/fitting/binding.jl index 3ff56adf..ecfa88a3 100644 --- a/src/fitting/binding.jl +++ b/src/fitting/binding.jl @@ -12,6 +12,8 @@ function _construct_bound_mapping(bindings, parameter_count) # the model we use as a reference to bind *to* reference = binding[1] for b in @views binding[2:end] + # get the number of the parameter that we are binding + parameter_number = parameter_mapping[b[1]][b[2]] parameter_mapping[b[1]][b[2]] = reference[2] # mark for removal: find the parameter index in the global array @@ -21,11 +23,17 @@ function _construct_bound_mapping(bindings, parameter_count) # need to now shuffle all the indices greater than this one down by 1 for k = b[2]+1:length(parameter_mapping[b[1]]) - parameter_mapping[b[1]][k] -= 1 + if (parameter_mapping[b[1]][k] > parameter_number) + parameter_mapping[b[1]][k] -= 1 + end end # and for subsequent models for j = b[1]+1:length(parameter_count) - parameter_mapping[j] .-= 1 + for k = 1:length(parameter_mapping[j]) + if parameter_mapping[j][k] > parameter_number + parameter_mapping[j][k] -= 1 + end + end end end end diff --git a/test/fitting/test-binding.jl b/test/fitting/test-binding.jl index 06f8ddfc..9e56ba00 100644 --- a/test/fitting/test-binding.jl +++ b/test/fitting/test-binding.jl @@ -54,3 +54,26 @@ values = trunc.(Int, get_value.(parameters)) model1 = PowerLaw() model2 = PowerLaw() + PowerLaw() + +# test multiple bindings with multiple models and multiple datasets +prob = FittingProblem(model1 => dummy_data1, model1 => dummy_data1, model1 => dummy_data1) +bind!(prob, :K, :a) +_, mapping = SpectralFitting._build_parameter_mapping(prob.model, prob.bindings) +@test mapping == ([1, 2], [1, 2], [1, 2]) + +# 3 models, 1 bound parameter +prob = FittingProblem(model1 => dummy_data1, model1 => dummy_data1, model1 => dummy_data1) +bind!(prob, :a) +_, mapping = SpectralFitting._build_parameter_mapping(prob.model, prob.bindings) +@test mapping == ([1, 2], [3, 2], [4, 2]) + +# 3 models (2 the same, 1 different), bind one parameter between the two +prob = FittingProblem(model1 => dummy_data1, model2 => dummy_data1, model1 => dummy_data1) +bind!(prob, 1 => :a, 2 => :a_2, 3 => :a) +_, mapping = SpectralFitting._build_parameter_mapping(prob.model, prob.bindings) +@test mapping == ([1, 2], [3, 4, 5, 2], [6, 2]) + +# 2 models, both different, bind a parameter that is only in one model (check it does no-ops okay) +# prob = FittingProblem(model1 => dummy_data1, model2 => dummy_data1) +# bind!(prob, :K) +# note that this does not work at present because `_get_index_of_symbol` throws an error if the symbol is not found