Skip to content

Commit

Permalink
feat: add describe function for FittingProblem
Browse files Browse the repository at this point in the history
This is to begin addressing some of the parameter binding issues that were
being encountered. The `describe` function differs from just displaying the
FittingProblem in that it will resolve and pretty print the parameter bindings.

Bound parameters will no longer appear as `FREE` or `FROZEN` but rather list
the model and that model's parameter symbol that they are bound to.
  • Loading branch information
fjebaker committed Oct 2, 2024
1 parent b2f5ef4 commit 472f545
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 17 deletions.
25 changes: 22 additions & 3 deletions src/composite-models.jl
Original file line number Diff line number Diff line change
Expand Up @@ -157,14 +157,25 @@ function Base.show(io::IO, @nospecialize(model::CompositeModel))
)
end

function _print_param(io, free, name, val, q0, q1, q2, q3, q4)
function _print_param(io, free, name, val, q0, q1, q2, q3, q4; binding = nothing)
print(io, lpad("$name", q0), " ->")
if val isa FitParam
info = get_info_tuple(val)
print(io, lpad(info[1], q1 + 1))
if free
print(io, " Β± ", rpad(info[2], q2))
print(io, " ∈ [", lpad(info[3], q3), ", ", rpad(info[4], q4), "]")
end

if !isnothing(binding)
print(
io,
" ",
Crayons.Crayon(foreground = :magenta),
lpad(binding, 7),
Crayons.Crayon(reset = true),
)
elseif free
print(
io,
Crayons.Crayon(foreground = :green),
Expand All @@ -174,6 +185,7 @@ function _print_param(io, free, name, val, q0, q1, q2, q3, q4)
else
print(
io,
" ",
Crayons.Crayon(foreground = :cyan),
lpad("FROZEN", 15 + q1 + q2 + q3 + q4),
Crayons.Crayon(reset = true),
Expand All @@ -183,7 +195,7 @@ function _print_param(io, free, name, val, q0, q1, q2, q3, q4)
println(io)
end

function _printinfo(io::IO, @nospecialize(model::CompositeModel))
function _printinfo(io::IO, @nospecialize(model::CompositeModel); bindings = nothing)
expr_buffer = 5
sym_buffer = 5

Expand All @@ -208,6 +220,7 @@ function _printinfo(io::IO, @nospecialize(model::CompositeModel))
)
println(io, "Model key and parameters:")

param_index = 1
for (sym, m) in destructed.model_map
param_syms = destructed.parameter_symbols[sym]
basename = Base.typename(typeof(m)).name
Expand All @@ -224,7 +237,13 @@ function _printinfo(io::IO, @nospecialize(model::CompositeModel))
for ps in param_syms
param = destructed.parameter_map[ps]
free = param isa FitParam ? !isfrozen(param) : true
_print_param(io, free, ps, param, param_offset, q1, q2, q3, q4)
val, binding = if !isnothing(bindings) && !isempty(bindings)
get(bindings, param_index, param => nothing)
else
param, nothing
end
_print_param(io, free, ps, val, param_offset, q1, q2, q3, q4; binding)
param_index += 1
end
end
end
Expand Down
70 changes: 65 additions & 5 deletions src/fitting/problem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,45 @@ struct FittableMultiModel{M}
FittableMultiModel(model::Vararg{<:AbstractSpectralModel}) = new{typeof(model)}(model)
end

function translate_bindings(
model_index::Int,
m::FittableMultiModel,
bindings::Vector{Vector{Pair{Int,Int}}},
)
# map the parameter index to a string to display
translation = Dict{Int,Pair{paramtype(m.m[1]),String}}()
for b in bindings
# we skip the first item in the list since that is the root of the binding
root = b[1]

params = parameter_named_tuple(m.m[first(root)])
symbol = propertynames(params)[last(root)]
value = params[last(root)]

for pair in @views b[2:end]
# check if this binding applies to the current model
if first(pair) == model_index
translation[last(pair)] = value => "~Model $(first(root)) $(symbol)"
end
end
end

translation
end

function Base.show(io::IO, ::MIME"text/plain", @nospecialize(model::FittableMultiModel))
buff = IOBuffer()
println(buff, "Models:")
for m in model.m
for (i, m) in enumerate(model.m)
buf = IOBuffer()
print(buf, "- ")
print(
buf,
"\n",
Crayons.Crayon(foreground = :yellow),
"Model $i",
Crayons.Crayon(reset = true),
": ",
)
_printinfo(buf, m)
print(buff, indent(String(take!(buf)), 2))
end
Expand Down Expand Up @@ -135,11 +168,38 @@ function Base.show(io::IO, ::MIME"text/plain", @nospecialize(prob::FittingProble
buff,
" . ",
Crayons.Crayon(foreground = :green),
"Free (DOF)",
"Free",
Crayons.Crayon(reset = true),
" : $(free)",
" : $(free)",
)
print(io, encapsulate(String(take!(buff))))
end

export FittingProblem, FittableMultiModel, FittableMultiDataset

"""
details(prob::FittingProblem)
Show details about the fitting problem, including the specific model parameters that are bound together.
"""
function details(prob::FittingProblem)
buff = IOBuffer()
println(buff, "Models:")
for (i, m) in enumerate(prob.model.m)
buf = IOBuffer()
print(
buf,
"\n",
Crayons.Crayon(foreground = :yellow),
"Model $i",
Crayons.Crayon(reset = true),
": ",
)

_printinfo(buf, m; bindings = translate_bindings(i, prob.model, prob.bindings))
print(buff, indent(String(take!(buf)), 2))
end

print(encapsulate(String(take!(buff))))
end

export FittingProblem, FittableMultiModel, FittableMultiDataset, details
18 changes: 9 additions & 9 deletions test/io/test-printing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ expected = """
β”Œ DummyAdditive
β”‚ K -> 1 Β± 0.1 ∈ [ 0, Inf ]\e[32m FREE\e[0m
β”‚ a -> 1 Β± 0.1 ∈ [ 0, Inf ]\e[32m FREE\e[0m
β”‚ b -> 5\e[36m FROZEN\e[0m
β”‚ b -> 5 \e[36m FROZEN\e[0m
β”” """
@test string == expected

Expand All @@ -32,14 +32,14 @@ expected = """β”Œ CompositeModel with 3 model components:
β”‚ \e[36m a1\e[0m => \e[36mDummyAdditive\e[0m
β”‚ K_1 -> 1 Β± 0.1 ∈ [ 0, Inf ]\e[32m FREE\e[0m
β”‚ a_1 -> 1 Β± 0.1 ∈ [ 0, Inf ]\e[32m FREE\e[0m
β”‚ b_1 -> 5\e[36m FROZEN\e[0m
β”‚ b_1 -> 5 \e[36m FROZEN\e[0m
β”‚ \e[36m a2\e[0m => \e[36mDummyAdditive\e[0m
β”‚ K_2 -> 1 Β± 0.1 ∈ [ 0, Inf ]\e[32m FREE\e[0m
β”‚ a_2 -> 1 Β± 0.1 ∈ [ 0, Inf ]\e[32m FREE\e[0m
β”‚ b_2 -> 5\e[36m FROZEN\e[0m
β”‚ b_2 -> 5 \e[36m FROZEN\e[0m
β”‚ \e[36m m1\e[0m => \e[36mDummyMultiplicative\e[0m
β”‚ a_3 -> 1 Β± 0.1 ∈ [ 0, Inf ]\e[32m FREE\e[0m
β”‚ b_3 -> 5\e[36m FROZEN\e[0m
β”‚ b_3 -> 5 \e[36m FROZEN\e[0m
β”” """
@test string == expected

Expand All @@ -55,20 +55,20 @@ expected = """β”Œ CompositeModel with 5 model components:
β”‚ \e[36m a1\e[0m => \e[36mDummyAdditive\e[0m
β”‚ K_1 -> 1 Β± 0.1 ∈ [ 0, Inf ]\e[32m FREE\e[0m
β”‚ a_1 -> 1 Β± 0.1 ∈ [ 0, Inf ]\e[32m FREE\e[0m
β”‚ b_1 -> 5\e[36m FROZEN\e[0m
β”‚ b_1 -> 5 \e[36m FROZEN\e[0m
β”‚ \e[36m m1\e[0m => \e[36mDummyMultiplicative\e[0m
β”‚ a_2 -> 1 Β± 0.1 ∈ [ 0, Inf ]\e[32m FREE\e[0m
β”‚ b_2 -> 5\e[36m FROZEN\e[0m
β”‚ b_2 -> 5 \e[36m FROZEN\e[0m
β”‚ \e[36m a2\e[0m => \e[36mDummyAdditive\e[0m
β”‚ K_2 -> 1 Β± 0.1 ∈ [ 0, Inf ]\e[32m FREE\e[0m
β”‚ a_3 -> 1 Β± 0.1 ∈ [ 0, Inf ]\e[32m FREE\e[0m
β”‚ b_3 -> 5\e[36m FROZEN\e[0m
β”‚ b_3 -> 5 \e[36m FROZEN\e[0m
β”‚ \e[36m m2\e[0m => \e[36mDummyMultiplicative\e[0m
β”‚ a_4 -> 1 Β± 0.1 ∈ [ 0, Inf ]\e[32m FREE\e[0m
β”‚ b_4 -> 5\e[36m FROZEN\e[0m
β”‚ b_4 -> 5 \e[36m FROZEN\e[0m
β”‚ \e[36m m3\e[0m => \e[36mDummyMultiplicative\e[0m
β”‚ a_5 -> 1 Β± 0.1 ∈ [ 0, Inf ]\e[32m FREE\e[0m
β”‚ b_5 -> 5\e[36m FROZEN\e[0m
β”‚ b_5 -> 5 \e[36m FROZEN\e[0m
β”” """
@test string == expected

Expand Down

0 comments on commit 472f545

Please sign in to comment.