Skip to content

Commit

Permalink
improved PyPlot backend: (#17)
Browse files Browse the repository at this point in the history
* better fontsize recognition

* correct fig sizes

* tight_layout() also for SubVisualizer reveal

* fixed rare clipping of last colorlevel in scalarplot

* coordinate limits (xlimits etc.) are used in vectorsample (such that scaling only is applied to vectors in the clipped area)

* new vector scaling method vconstant that scales all arrows equally

* repaired streamplot (U and V arguments needed transposition)

* added density argument to streamplot

* version bump

---------

Co-authored-by: Christian Merdon <[email protected]>
  • Loading branch information
chmerdon and chmerdon authored Sep 11, 2023
1 parent df19c60 commit 4f7a851
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 12 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "GridVisualize"
uuid = "5eed8a63-0fb0-45eb-886d-8d5a387d12b8"
authors = ["Juergen Fuhrmann <[email protected]>"]
version = "1.1.4"
version = "1.1.5"

[deps]
ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
Expand Down
28 changes: 25 additions & 3 deletions src/common.jl
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ streamlines.
The code is 3D ready.
"""
function vectorsample(grid::ExtendableGrid{Tv, Ti}, v; offset = :default,
spacing = :default, reltol = 1.0e-10) where {Tv, Ti}
spacing = :default, reltol = 1.0e-10, xlimits = (1,-1), ylimits = (1,-1), zlimits = (1,-1)) where {Tv, Ti}
coord = grid[Coordinates]
cn = grid[CellNodes]
ncells::Int = num_cells(grid)
Expand All @@ -172,6 +172,15 @@ function vectorsample(grid::ExtendableGrid{Tv, Ti}, v; offset = :default,

# coordinate window
cminmax = extrema(coord; dims = (2,))
if xlimits[1] < xlimits[2]
cminmax[1] = xlimits[:]
end
if ylimits[1] < ylimits[2]
cminmax[2] = ylimits[:]
end
if zlimits[1] < zlimits[2]
cminmax[3] = zlimits[:]
end

if offset == :default
offset = [cminmax[i][1] for i = 1:dim]
Expand Down Expand Up @@ -255,8 +264,17 @@ function vectorsample(grid::ExtendableGrid{Tv, Ti}, v; offset = :default,
# If so, obtain P1 interpolated raster data and
# assign them to rasterflux
for I[1] Imin[1]:Imax[1] # 0 alloc
if I[1] <= 0 || I[1] > length(rastercoord[1])
continue
end
for I[2] Imin[2]:Imax[2]
if I[2] <= 0 || I[2] > length(rastercoord[2])
continue
end
for I[3] Imin[3]:Imax[3]
if dim == 3 && (I[3] <= 0 || I[3] > length(rastercoord[3]))
continue
end

# Fill raster point to be tested
for idim = 1:dim
Expand Down Expand Up @@ -315,7 +333,7 @@ is scaled by vscale
Result data are meant to be ready for being passed to calls to `quiver`.
"""
function quiverdata(rastercoord, rasterflux; vscale = 1.0, vnormalize = true)
function quiverdata(rastercoord, rasterflux; vscale = 1.0, vnormalize = true, vconstant = false)
dim = length(rastercoord)

imax = length(rastercoord[1])
Expand Down Expand Up @@ -355,7 +373,11 @@ function quiverdata(rastercoord, rasterflux; vscale = 1.0, vnormalize = true)
qv = reshape(reinterpret(Float32, qvvalues), (2, length(qvvalues)))

# Normalize vectors to raster point spacing
if vnormalize
if vconstant
for j = 1 : size(qv,2)
view(qv,:,j) ./= norm(view(qv,:,j))
end
elseif vnormalize
@views vmax = maximum(norm, (qv[:, i] for i = 1:length(qvvalues)))
vscale = vscale * min(spacing...) / vmax
end
Expand Down
19 changes: 11 additions & 8 deletions src/pyplot.jl
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
function initialize!(p, ::Type{PyPlotType})
PyPlot = p.context[:Plotter]
PyPlot.PyObject(PyPlot.axes3D)# see https://github.com/JuliaPy/PyPlot.jl/issues/351
PyPlot.rc("font", size = p.context[:fontsize])
if !haskey(p.context, :figure)
res = p.context[:size]
if !isdefined(Main, :PlutoRunner)
p.context[:figure] = PyPlot.figure(p.context[:fignumber]; dpi = 50)
p.context[:figure] = PyPlot.figure(p.context[:fignumber]; dpi = 50, figsize=res./50)
else
p.context[:figure] = PyPlot.figure(p.context[:fignumber]; dpi = 100)
p.context[:figure] = PyPlot.figure(p.context[:fignumber]; dpi = 100, figsize=res./100)
end
p.context[:figure].set_size_inches(res[1] / 100, res[2] / 100; forward = true)
#p.context[:figure].set_size_inches(res[1] / 100, res[2] / 100, forward = true)
for ctx in p.subplots
ctx[:figure] = p.context[:figure]
end
Expand Down Expand Up @@ -43,6 +44,7 @@ function reveal(ctx::SubVisualizer, TP::Type{PyPlotType})
if ctx[:show] || ctx[:reveal]
reveal(ctx[:GridVisualizer], TP)
end
ctx[:GridVisualizer].Plotter.tight_layout()
end

#translate Julia attribute symbols to pyplot-speak
Expand Down Expand Up @@ -552,6 +554,7 @@ function scalarplot!(ctx, TP::Type{PyPlotType}, ::Type{Val{2}}, grids, parentgri
crange = (crange[1] - eps, crange[1] + eps)
colorlevels = collect(crange[1]:((crange[2]-crange[1])/(1)):crange[2])
else
crange = (crange[1] - 1e-16, crange[2] + 1e-16) # avoids rare clipping of last color level
colorlevels =
collect(crange[1]:((crange[2]-crange[1])/(ctx[:colorlevels]-1)):crange[2])
end
Expand Down Expand Up @@ -716,10 +719,10 @@ function vectorplot!(ctx, TP::Type{PyPlotType}, ::Type{Val{2}}, grid, func)
ax.set_aspect(ctx[:aspect])
ax.set_title(ctx[:title])

rc, rv = vectorsample(grid, func; spacing = ctx[:spacing], offset = ctx[:offset])
qc, qv = quiverdata(rc, rv; vscale = ctx[:vscale], vnormalize = ctx[:vnormalize])
rc, rv = vectorsample(grid, func; spacing = ctx[:spacing], offset = ctx[:offset], xlimits = ctx[:xlimits], ylimits = ctx[:ylimits])
qc, qv = quiverdata(rc, rv; vscale = ctx[:vscale], vnormalize = ctx[:vnormalize], vconstant = ctx[:vconstant])

ax.quiver(qc[1, :], qc[2, :], qv[1, :], qv[2, :])
ax.quiver(qc[1, :], qc[2, :], qv[1, :], qv[2, :]; color = ctx[:color])
ax.set_xlabel(ctx[:xlabel])
ax.set_ylabel(ctx[:ylabel])

Expand Down Expand Up @@ -769,11 +772,11 @@ function streamplot!(ctx, TP::Type{PyPlotType}, ::Type{Val{2}}, grid, func)
xout, yout
end

rc, rv = vectorsample(grid, func; spacing = ctx[:spacing], offset = ctx[:offset])
rc, rv = vectorsample(grid, func; spacing = ctx[:spacing], offset = ctx[:offset], xlimits = ctx[:xlimits], ylimits = ctx[:ylimits])

X, Y = meshgrid(rc)

ax.streamplot(X, Y, rv[1, :, :, 1], rv[2, :, :, 1]; color = ctx[:color])
ax.streamplot(X, Y, rv[1, :, :, 1]', rv[2, :, :, 1]'; color = ctx[:color], density = ctx[:density])
ax.set_xlabel(ctx[:xlabel])
ax.set_ylabel(ctx[:ylabel])

Expand Down

2 comments on commit 4f7a851

@j-fu
Copy link
Member

@j-fu j-fu commented on 4f7a851 Sep 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/91185

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v1.1.5 -m "<description of version>" 4f7a851269ece9208d57b75c3c8d33595fa36293
git push origin v1.1.5

Please sign in to comment.