possible to set colorbar limits for meshviz?
tanged123 opened this issue · comments
currently, I have some code that visualizes a solved CFD mesh. I was wondering if it was possible to set a "color axis limit" in the meshviz to be consistent to the colorbar limits in makie.
begin
fig = mke.Figure()
rangeval = [0,1]
#line to change below?
#M = mach = range[0-0.7], want to convert to [0-1] for colors
ax,plotobj= viz(fig[1,1],turbine_mesh, colorscheme = :turbo, color = M)
cbar = mke.Colorbar(fig[1,2],label="Mach", width=25, limits = Float64.(rangeval),colormap = :turbo)
fig
@tanged123 can you give an example of what you are trying to achieve? In theory all the recipes in MeshViz.jl are normal Makie recipes, so you should be able to compose visualizations with colorbars. Perhaps you are asking to forward some keyword argument that is currently not used in the final plot calls?
Alright, the code below is utilizing one of the test cases in meshviz.
import CairoMakie as mke
using Meshes, MeshViz
fig = mke.Figure()
rangeval = (0,1)
d = CartesianGrid(10,10)
ax,plotobj = viz(fig[1,1],d, color = 1:1:100, colorscheme = :turbo)
cbar = mke.Colorbar(fig[1,2],label="Colorbar Range", width=25, limits = Float64.(rangeval),colormap = :turbo)
fig
Say for example that I want to limit the colors shown in the mesh viz to only 70% of the color bar, such that the highest value in colors = 1:1:100 (i.e 100) displays a color equivalent to 0.7 on the color bar scale. A comparable use case in Makie would be setting clims for a heatmap.
Thank you for clarifying the issue. So the feature request consists of adding a new clims
argument to the recipe and forward it to the underlying Makie call, correct? I am happy to review a PR.
We now have a different function called viewer
where we add other elements to the scene such as colorbars, etc. The function automatically picks color schemes, etc. Please try to use it instead and report a new issue if something is not ideal. :)
Currently, what is the recommended way to plot static graphs with colorbars? I expected that something like the following would work:
import CairoMakie: CairoMakie, save, Figure, Axis
using Meshes, MeshViz
gd = meshdata(CartesianGrid(10,10), etable = (;id = rand(100)))
fig, ax, hm = viz(gd.geometry, color = gd.id)
CairoMakie.Colorbar(fig[1, 2], hm)
but it complains because the :colormap
key is not provided.
ERROR: KeyError: key :colormap not found
Stacktrace:
[1] getindex(h::Dict{Symbol, Observables.Observable}, key::Symbol)
@ Base ./dict.jl:498
[2] getindex
@ ~/.julia/packages/MakieCore/6sckc/src/attributes.jl:91 [inlined]
[3] getindex(x::MakieCore.Combined{MeshViz.viz, Tuple{CartesianGrid{2, Float64}}}, key::Symbol)
@ MakieCore ~/.julia/packages/MakieCore/6sckc/src/attributes.jl:187
[4] getproperty
@ ~/.julia/packages/MakieCore/6sckc/src/attributes.jl:78 [inlined]
[5] Makie.Colorbar(fig_or_scene::GridLayoutBase.GridPosition, plot::MakieCore.Combined{MeshViz.viz, Tuple{CartesianGrid{2, Float64}}}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ Makie ~/.julia/packages/Makie/Iqcri/src/makielayout/blocks/colorbar.jl:29
[6] Makie.Colorbar(fig_or_scene::GridLayoutBase.GridPosition, plot::MakieCore.Combined{MeshViz.viz, Tuple{CartesianGrid{2, Float64}}})
@ Makie ~/.julia/packages/Makie/Iqcri/src/makielayout/blocks/colorbar.jl:21
[7] top-level scope
@ REPL[303]:1
Setting up all the atributes of Colorbar
work, but it does not feel right that we need to define colormap
and limits
on Colorbar.
gd = meshdata(CartesianGrid(10,10), etable = (;id = rand(100)))
fig, ax, hm = viz(gd.geometry, color = gd.id, colorscheme = :viridis)
CairoMakie.Colorbar(fig[1, 2], colormap = :viridis, limits = extrema(df_grid.id))
Also, It would be great if we can pass a colorscheme using Reverse
something like Reverse(:viridis)
.
I think the viewer has the colorbar set, but I remember it was a limitation of Makie.jl with recipes. Regarding the reverse colorscheme, can you double check how it is done in ColorSchemes.jl?
I can check both features. Both are useful for my use case.
@juliohm I was experimenting with MeshViz.jl
and how to setup a Colorbar
for heatmaps using Makie
code and I wanted to show that doing some few modifications we get a very flexible result where we can easily add a Colorbar
, and get all the features of heatmap
(set limits, transparency, color for values that are not inside the desired range, Reverse(:colormap), and so on):
@Makie.recipe(Viz, object) do scene
Makie.Attributes(;
Makie.default_theme(scene, Makie.Heatmap)...,
size = Makie.theme(scene, :markersize),
color = :slategray3,
alpha = 1.0,
colorscheme = nothing,
facetcolor = :gray30,
showfacets = false,
decimation = 0.0,
)
end
function vizgrid2D!(plot)
Makie.replace_automatic!(plot, :colorrange) do
map(extrema, plot[:color])
end
grid = plot[:object]
color = plot[:color]
alpha = plot[:alpha]
colorscheme = plot[:colorscheme]
attr = copy(Makie.Attributes(plot))
cparams = Makie.@lift let
nd = embeddim($grid)
or = coordinates(minimum($grid))
sp = spacing($grid)
sz = size($grid)
xs, ys = cartesiancenters(or, sp, sz, nd)
C = reshape($color, sz)
xs, ys, C
end
# unpack observable of parameters
xs = Makie.@lift $cparams[1]
ys = Makie.@lift $cparams[2]
C = Makie.@lift $cparams[3]
Makie.heatmap!(plot, attr, xs, ys, C)
end
using Revise
import CairoMakie: CairoMakie as MK, save, Figure, Axis
using Meshes, MeshViz
gd = meshdata(CartesianGrid(10,10), etable = (;id = 1:100))
# colormap
fig = Figure()
ax = Axis(fig[1,1])
hm = viz!(ax, gd.geometry, color = gd.id, colormap = :RdBu,
showfacets = true)
MK.Colorbar(fig[1, 2], hm)
# transparency
fig = Figure()
ax = Axis(fig[1,1])
hm = viz!(ax, gd.geometry, color = gd.id, colormap = (:RdBu, 0.5),
showfacets = true)
MK.Colorbar(fig[1, 2], hm)
save("transparency.png", fig)
# limits
fig = Figure()
ax = Axis(fig[1,1])
hm = viz!(ax, gd.geometry, color = gd.id, colormap = (:RdBu, 0.5),
showfacets = true, colorrange = (40,100), lowclip = :black)
MK.Colorbar(fig[1, 2], hm)
save("limits.png", fig)
# reverse and transparency
fig = Figure()
ax = Axis(fig[1,1])
hm = viz!(ax, gd.geometry, color = gd.id, colormap = (MK.Reverse(:RdBu), 0.9),
showfacets = true, colorrange = (40,100), lowclip = :black)
MK.Colorbar(fig[1, 2], hm)
save("reverse.png", fig)
Of course, this modification is probably causing problems for other graphic types because of Makie.default_theme(scene, Makie.Heatmap)...
, but maybe we can do a specific function for CartessianGrids
to start with. Also, is there any reason you need to use Colorant
and obtain the colors by ourselves? Will you be interested in a PR related to this issue, this is just a simple example?
@juliohm. Could you please explain why we need to preprocess the colors when Makie
can do that?
With respect to other graph types, I think I can generalize passing the main attributes that are important for Colorbar
like colorrange
, colormap
, lowclip
, highclip
, and also some arguments that will be added to Makie.jl
. For example there is a pull request to include colorscale
to show the colorbar in log
scale or any other desired transformations. If we procces the colors by ourselves, I think we miss all these features and probably new features.
For specific plots we could use convert_arguments
. For example for CartesianGrid
, we know that we would like to plot a heatmap
. Definining something like:
function MK.convert_arguments(::Type{<:MK.Heatmap}, grid::CartesianGrid, values)
....
(xs, ys, C)
end
would allow us to call heatmap
for CartesianGrid
and use all existing features, would make really easy to add colorbars. I just tested it and works nice.
heatmap(grid, values, ...)
Sorry if I am making to much noise and it is out of the scope, but I am just throwing some ideas with the goal of having full compatibility with other Makie
elements.
Testing heatmap
, I can see that it accepts CategoricalValues
without problems, and Colorbar
works over this as well.
I like the idea of using only one commant (viz
) for the plots, but I am not yet convinced that we need to preprocess the colors.
Just tested with other graph types, and it does not work for them.