JuliaGeometry / MeshViz.jl

Makie.jl recipes for visualization of Meshes.jl

Home Page:https://github.com/JuliaGeometry/Meshes.jl

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.

image

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)

colormap

# 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)

transparency

# 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)

limits

# 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)

reverse

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.