diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ee5bbe..703c607 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [1.17.0] - 2026-01-09 +- Add `:symlog` axis scaling for symmetric logarithmic axis scaling, see, e.g. [matplotlib symlog](https://matplotlib.org/stable/gallery/scales/symlog_demo.html) +- Add `:symlog_threshold` (default = 10.0) to determine when to switch from linear to log scaling in case of `:symlog` scaling + ## [1.16.3] - 2026-01-07 - Add `title`, `xlabel`, and `ylabel` to 1D and 2D `gridplot!` with `GLMakie` - Add `title`, `xlabel`, and `ylabel` to 1D and 2D `gridplot!` with `Py[thon]Plot` diff --git a/Project.toml b/Project.toml index fc72edc..c710144 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "GridVisualize" uuid = "5eed8a63-0fb0-45eb-886d-8d5a387d12b8" authors = ["Juergen Fuhrmann ", "Patrick Jaap "] -version = "1.16.3" +version = "1.17.0" [deps] ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4" diff --git a/ext/GridVisualizeMakieExt.jl b/ext/GridVisualizeMakieExt.jl index 1a5ac2f..bdbd896 100644 --- a/ext/GridVisualizeMakieExt.jl +++ b/ext/GridVisualizeMakieExt.jl @@ -474,12 +474,28 @@ function scalarplot!(ctx, TP::Type{MakieType}, ::Type{Val{1}}, grids, parentgrid if !haskey(ctx, :scene) ctx[:xtitle] = Observable(ctx[:title]) + if ctx[:xscale] == :log + xscale = log10 + elseif ctx[:xscale] == :symlog + xscale = XMakie.Makie.Makie.Symlog10(ctx[:symlog_threshold]) + else + xscale = identity + end + + if ctx[:yscale] == :log + yscale = log10 + elseif ctx[:yscale] == :symlog + yscale = XMakie.Makie.Makie.Symlog10(ctx[:symlog_threshold]) + else + yscale = identity + end + # Axis ctx[:scene] = XMakie.Axis( ctx[:figure]; title = map(a -> a, ctx[:xtitle]), - xscale = ctx[:xscale] == :log ? log10 : identity, - yscale = ctx[:yscale] == :log ? log10 : identity, + xscale, + yscale, xlabel = ctx[:xlabel], ylabel = ctx[:ylabel], scenekwargs(ctx)..., diff --git a/ext/GridVisualizePlotsExt.jl b/ext/GridVisualizePlotsExt.jl index 3e2b45d..4e2580f 100644 --- a/ext/GridVisualizePlotsExt.jl +++ b/ext/GridVisualizePlotsExt.jl @@ -260,6 +260,13 @@ function scalarplot!(ctx, TP::Type{PlotsType}, ::Type{Val{1}}, grids, parentgrid ymax = ylimits[2] end + for key in (:xscale, :yscale) + if ctx[key] == :symlog + @warn "Plots.jl does not support symlog axis scaling for $key." + ctx[key] = :identity + end + end + ctx[:xscale] == :log ? ctx[:xscale] = :log10 : nothing ctx[:yscale] == :log ? ctx[:yscale] = :log10 : nothing diff --git a/ext/GridVisualizePlutoVistaExt.jl b/ext/GridVisualizePlutoVistaExt.jl index 327e5d6..9ec4a77 100644 --- a/ext/GridVisualizePlutoVistaExt.jl +++ b/ext/GridVisualizePlutoVistaExt.jl @@ -221,6 +221,13 @@ function scalarplot!( PlutoVista = ctx[:Plotter] PlutoVista.backend!(ctx[:figure]; backend = ctx[:backend], datadim = 1) + for key in (:xscale, :yscale) + if ctx[key] == :symlog + @warn "Plutovista.jl does not support symlog axis scaling for $key." + ctx[key] = :identity + end + end + for ifunc in 1:nfuncs func = funcs[ifunc] grid = grids[ifunc] diff --git a/src/dispatch.jl b/src/dispatch.jl index dd54279..6560e7a 100644 --- a/src/dispatch.jl +++ b/src/dispatch.jl @@ -386,6 +386,7 @@ function default_plot_kwargs() :spacing => Pair(nothing, "Removed from API"), :species => Pair(1, "Number of species to plot or number of species in regions"), :subplot => Pair((1, 1), "Private: Actual subplot"), + :symlog_threshold => Pair(10.0, ":symlog threshold for switching from linear to log scaling. Only relevant for :symlog axis scaling."), :title => Pair("", "Plot title"), :tetxplane_tol => Pair(0.0, "tolerance for tet-plane intersection in 3D"), :vconstant => Pair(false, "Set all arrow length constant in vector plot"), @@ -395,11 +396,11 @@ function default_plot_kwargs() :xlimits => Pair((1, -1), "x axis limits"), :xplanes => Pair([prevfloat(Inf)], "3D x plane positions or number thereof"), :xlabel => Pair("x", "x axis label"), - :xscale => Pair(:identity, "x axis scale: one of [:log, :identity]"), + :xscale => Pair(:identity, "x axis scale: one of [:log, :identity, :symlog]"), :ylimits => Pair((1, -1), "y axis limits"), :ylabel => Pair("y", "y axis label"), :yplanes => Pair([prevfloat(Inf)], "3D y plane positions or number thereof"), - :yscale => Pair(:identity, "y axis scale: one of [:log, :identity]"), + :yscale => Pair(:identity, "y axis scale: one of [:log, :identity, :symlog]"), :zlimits => Pair((1, -1), "z axis limits"), :zplanes => Pair([prevfloat(Inf)], "3D z plane positions or number thereof"), :zlabel => Pair("z", "z axis label"), diff --git a/src/pycommon.jl b/src/pycommon.jl index 8155754..0eaa282 100644 --- a/src/pycommon.jl +++ b/src/pycommon.jl @@ -436,21 +436,14 @@ function scalarplot!(ctx, TP::Type{T}, ::Type{Val{1}}, grids, parentgrid, funcs) ax = ctx[:ax] fig = ctx[:figure] + # activate log scaling + ctx[:xscale] == :log && ax.set_xscale("log") + ctx[:xscale] == :symlog && ax.set_xscale("symlog", linthresh = ctx[:symlog_threshold]) + ctx[:yscale] == :log && ax.set_yscale("log") + ctx[:yscale] == :symlog && ax.set_yscale("symlog", linthresh = ctx[:symlog_threshold]) + pplot = ax.plot - if ctx[:xscale] == :log - if ctx[:yscale] == :log - pplot = ax.loglog - else - pplot = ax.semilogx - end - end - if ctx[:yscale] == :log - if ctx[:xscale] == :log - pplot = ax.loglog - else - pplot = ax.semilogy - end - end + gridscale = ctx[:gridscale] if ctx[:cellwise] # not checked, outdated for icell in 1:num_cells(grid)