diff --git a/Project.toml b/Project.toml index fab19bca..1b56f8d1 100644 --- a/Project.toml +++ b/Project.toml @@ -20,13 +20,16 @@ StatsBase = "0.27, 0.28, 0.29, 0.30, 0.31, 0.32, 0.33, 0.34" julia = "1.6" [extras] -Minio = "4281f0d9-7ae0-406e-9172-b7277c1efa20" ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1" LightGraphs = "093fc24a-ae57-5d10-9952-331d41423f4d" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" MLDatasets = "eb30cadb-4394-5ae3-aed4-317e484a6458" +Minio = "4281f0d9-7ae0-406e-9172-b7277c1efa20" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee" +Gadfly = "c91e804a-d5a3-530f-b6f0-dfbca275c004" +Cairo="159f3aea-2a34-519c-b102-8c37f9878175" +Fontconfig="186bb1d3-e1f7-5a2c-a377-96d770f13627" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" TestImages = "5e47fb64-e119-507b-a336-dd2b206d9990" Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" diff --git a/README.md b/README.md index 396e6640..fb4b2514 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,8 @@ logger in Julia: You can log to TensorBoard any type. Numeric types will be logged as scalar, arrays will be binned into histograms, images and audio will be logged as such, -and we even support [Plots](https://github.com/JuliaPlots/Plots.jl) and -[PyPlot](https://github.com/JuliaPlots/Plots.jl) figures! +and we even support [Plots](https://github.com/JuliaPlots/Plots.jl), +[PyPlot](https://github.com/JuliaPlots/Plots.jl) and [Gadfly](https://github.com/GiovineItalia/Gadfly.jl) figures! For details about how types are logged by default, or how to customize this behaviour for your custom types, refer to the documentation or the examples folder. @@ -71,7 +71,7 @@ end ``` ## Integration with third party packages -We also support native logging of the types defined by a few third-party packages, such as `Plots` and `PyPlot` plots. +We also support native logging of the types defined by a few third-party packages, such as `Plots`, `PyPlot` and `Gadfly` plots. If there are other libraries that you think we should include in the list, please open an issue. ## Roadmap diff --git a/docs/src/index.md b/docs/src/index.md index 9102b45a..69d67411 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -111,6 +111,7 @@ at [Reading back TensorBoard data](@ref) We also support logging custom types from a the following third-party libraries: - [Plots.jl](https://github.com/JuliaPlots/Plots.jl): the `Plots.Plot` type will be rendered to PNG at the resolution specified by the object and logged as an image - [PyPlot.jl](https://github.com/JuliaPy/PyPlot.jl): the `PyPlot.Figure` type will be rendered to PNG at the resolution specified by the object and logged as an image + - [Gadfly.jl](https://github.com/GiovineItalia/Gadfly.jl) type will be rendered to PNG at the resolution specified by the object and logged as an image. `Cairo` and `Fontconfig` packages must be imported for this functionality to work as it is required by `Gadfly`. - [Tracker.jl](https://github.com/FluxML/Tracker.jl): the `TrackedReal` and `TrackedArray` types will be logged as vector data - [ValueHistories.jl](https://github.com/JuliaML/ValueHistories.jl): the `MVHistory` type is used to store the deserialized content of .proto files. diff --git a/examples/Gadfly.jl b/examples/Gadfly.jl new file mode 100644 index 00000000..aff9608d --- /dev/null +++ b/examples/Gadfly.jl @@ -0,0 +1,14 @@ +using TensorBoardLogger #import the TensorBoardLogger package +using Logging #import Logging package +using Gadfly, Cairo, Fontconfig + +logger = TBLogger("Gadflylogs", tb_append) #create tensorboard logger + +################log scalars example: y = x²################ +#using logger interface +x = rand(100) +y = rand(100) +p = plot(x=x, y=y, Geom.point); +with_logger(logger) do + @info "gadfly" plot=p +end \ No newline at end of file diff --git a/examples/Scalars.jl b/examples/Scalars.jl index 36461c4a..e44a3f30 100644 --- a/examples/Scalars.jl +++ b/examples/Scalars.jl @@ -23,3 +23,28 @@ with_logger(logger) do @info "scalar/complex" y = z end end + + +################control step increments with context################ +with_logger(logger) do + for epoch in 1:10 + for i=1:100 + # increments global_step by default + with_TBLogger_hold_step() do + # all of these are logged at the same global_step + # and the logger global_step is only then increased + @info "train1/scalar" val=i + @info "train2/scalar" val2=i/2 + @info "train3/scalar" val3=100-i + end + end + # step increment at end can be disabled for easy train/test sync + with_TBLogger_hold_step(;step_at_end=false) do + # all of these are logged at the same global_step + # and the logger global_step is only then increased + @info "test1/scalar" epoch=epoch + @info "test2/scalar" epoch2=epoch^2 + @info "test3/scalar" epoch3=epoch^3 + end + end +end diff --git a/src/Optional/Gadfly.jl b/src/Optional/Gadfly.jl new file mode 100644 index 00000000..d40423d5 --- /dev/null +++ b/src/Optional/Gadfly.jl @@ -0,0 +1,15 @@ +import .Gadfly: Plot, render, draw +function Base.convert(t::Type{PngImage}, plot::Gadfly.Plot) + pb = PipeBuffer(); + show(pb, MIME("image/png"), render(plot)); + # draw(Gadfly.PNG(pb), plot); # leaving here for now, does same thing + return PngImage(pb) +end + +preprocess(name, plot::Gadfly.Plot, data) = preprocess(name, convert(PngImage, plot), data) +preprocess(name, plots::AbstractArray{<:Gadfly.Plot}, data) = begin + for (i, plot)=enumerate(plots) + preprocess(name*"/$i", plot, data) + end + return data +end \ No newline at end of file diff --git a/src/TBLogger.jl b/src/TBLogger.jl index d998160a..dc80994b 100644 --- a/src/TBLogger.jl +++ b/src/TBLogger.jl @@ -298,3 +298,53 @@ Base.show(io::IO, mime::MIME"text/plain", tbl::TBLogger) = begin """ Base.print(io, str) end + +""" +`with_TBLogger_hold_step(f, [step]; step_at_end::Bool=true)` +Context function to ease control of logging steps and synchronization. +Amount of step increment can be controlled via `set_step_increment!``. + +Example: +```julia +with_logger(lg) do + for epoch in 1:10 + for i=1:100 + # increments global_step by default + with_TBLogger_hold_step() do + # all of these are logged at the same global_step + # and the logger global_step is only then increased + @info "train1/scalar" i=i + @info "train2/scalar" i2=i^2 + @info "train3/scalar" i3=i^3 + end + end + # step increment at end can be disabled for easy train/test sync + with_TBLogger_hold_step(;step_at_end=false) do + # all of these are logged at the same global_step + # and the logger global_step is only then increased + @info "test1/scalar" i=i + @info "test2/scalar" i2=i^2 + @info "test3/scalar" i3=i^3 + end + end +end +``` + +""" +function with_TBLogger_hold_step(f, step::Int; step_at_end::Bool=true) + logger = CoreLogging.current_logger() + @assert logger isa TBLogger "with_TBLogger_hold_step: current logger is not a TBLogger, cannot establish current step automatically" + curr_step = logger.global_step + curr_increment = logger.step_increment + set_step!(logger, step) + set_step_increment!(logger, 0) + f() + set_step!(logger, curr_step) + set_step_increment!(logger, curr_increment) + step_at_end && increment_step!(logger, curr_increment) +end +function with_TBLogger_hold_step(f; step_at_end::Bool=true) + logger = CoreLogging.current_logger() + isa(logger, TBLogger) || error("with_TBLogger_hold_step: current logger is not a TBLogger, cannot establish current step automatically") + with_TBLogger_hold_step(f, logger.global_step; step_at_end=step_at_end) +end \ No newline at end of file diff --git a/src/TensorBoardLogger.jl b/src/TensorBoardLogger.jl index 758d74d0..46da2293 100644 --- a/src/TensorBoardLogger.jl +++ b/src/TensorBoardLogger.jl @@ -19,7 +19,7 @@ using Base.CoreLogging: CoreLogging, AbstractLogger, LogLevel, Info, handle_message, shouldlog, min_enabled_level, catch_exceptions, with_logger, NullLogger -export TBLogger, reset!, set_step!, increment_step!, set_step_increment! +export TBLogger, reset!, set_step!, increment_step!, set_step_increment!, with_TBLogger_hold_step export log_histogram, log_value, log_vector, log_text, log_image, log_images, log_audio, log_audios, log_graph, log_embeddings, log_custom_scalar export map_summaries, TBReader @@ -102,6 +102,16 @@ function __init__() @require PyPlot="d330b81b-6aea-500a-939a-2ce795aea3ee" begin include("Optional/PyPlot.jl") end + @require Gadfly="c91e804a-d5a3-530f-b6f0-dfbca275c004" begin + @require Fontconfig="186bb1d3-e1f7-5a2c-a377-96d770f13627" begin + @require Cairo="159f3aea-2a34-519c-b102-8c37f9878175" begin + using .Cairo + using .Fontconfig + include("Optional/Gadfly.jl") + end + end + end + # @require Gadfly="c91e804a-d5a3-530f-b6f0-dfbca275c004" include("Optional/Gadfly.jl") @require Tracker="9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" begin include("Optional/Tracker.jl") end