diff -r a60d2f12ef93 -r 22a64e826ee7 src/Logger.jl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Logger.jl Tue Dec 07 11:41:07 2021 +0200 @@ -0,0 +1,96 @@ +# +# This module implements logging of intermediate computational results for +# generating convergence graphs, etc. +# + +""" +Logging routines for intermediate computational results. +Includes `Log`, `log!`, `if_log!`, and `write_log`. +""" +module Logger + +import DelimitedFiles: writedlm + +############## +# Our exports +############## + +export Log, + log!, + if_log!, + write_log + +########## +# Logging +########## + +""" +`struct Log{T}` + +A log of items of type `T` along with log configuration. +The constructor takes no arguments; create the log with `Log{T}()` for `T` your +data type, e.g., `Float64`. +""" +struct Log{T} + log :: Dict{Int, T} + + Log{T}() where T = new{T}(Dict{Int, T}()) +end + +""" +`if_log!(f :: Functdion, log :: Log{T}, i :: Int)` + +If based on the log settings, `i` is a verbose iteration, store the value of `f()` +in the log at index `i`. Typically to be used with `do`-notation: + +```julia +if_log!(log, iteration) do + # calculate value to be logged +end +``` +""" +function if_log!(f :: Function, log :: Log{T}, i :: Int) where T + if mod(i, log.verbose_iterations)==0 + log!(f, log, i) + #printstyled("$(i): $(val)\n", color=:light_black) + end +end + +""" +`log!(f :: Function, log :: Log{T}, i :: Int) ` + +Store the value `f()` in the log at index `i`. +""" +function log!(f :: Function, log :: Log{T}, i :: Int) where T + val = f() + push!(log.log, i => val) +end + +############## +# Data export +############## + +""" +`write_log(filename :: AbstractString, log :: Log{T})` + +Write a `Log{T}` as a CSV file using `DelimitedFiles`. +If T is a structural type, the field names are used as header fields. +Otherwise a single `value` field is attempted to be written. +""" +function write_log(filename :: AbstractString, log :: Log{T}) where T + k = fieldnames(T) + @assert(:iter ∉ k) + + open(filename, "w") do io + # Write header + writedlm(io, isempty(k) ? [:iter :value] : ((:iter, k...),)) + # Write values + iters = sort(collect(keys(log.log))) + for i ∈ iters + v = log.log[i] + writedlm(io, isempty(k) ? [i v] : ((i, (getfield(v, j) for j ∈ k)...),)) + end + end +end + +end # module