Closed asinghvi17 closed 1 month ago
Volume plot of 3d function
using AbstractPlotting
AbstractPlotting.__init__();
xs = LinRange(-3, 3, 100);
ys = copy(xs);
zs = copy(xs);
ρ(x, y, z) = exp(-(abs(x)))
qs = [ρ(x, y , z) for x in xs, y in ys, z in zs];
sc = Scene(backgroundcolor = :black)
volume!(sc, xs, ys, zs, qs, algorithm = :mip)
this might be cool to show off the abilities of the plotter:
https://github.com/astronexus/HYG-Database
It's a dataset of stars with position, color and magnitude (as well as a host of other things).
Maybe we could replace the stars
scatter plot with real stars?
From the documentation of ColorSchemes.jl
(at https://juliagraphics.github.io/ColorSchemes.jl/stable/index.html):
How to use ColorSchemes
in Makie:
using Makie, ColorSchemes
N = 20
x = LinRange(-0.3, 1, N)
y = LinRange(-1, 0.5, N)
z = x .* y'
image(x, y, z, colormap = ColorSchemes.picasso.colors)
See all colormaps provided by ColorSchemes.jl
using Makie, ColorSchemes
h = 0.0 offset = 0.1 scene = Scene() cam2d!(scene) plot = map(collect(keys(colorschemes))) do cmap global h c = to_colormap(colorschemes[cmap].colors) cbar = image!( scene, range(0, stop = 10, length = length(c)), range(0, stop = 1, length = length(c)), reshape(c, (length(c), 1)), show_axis = false )[end] text!( scene, string(cmap, ":"), position = Point2f0(-0.1, 0.5 + h), align = (:right, :center), show_axis = false, textsize = 0.4 ) translate!(cbar, 0, h, 0) h -= (1 + offset) end scene
To document what a Theme
is and how it ties in with the Scene
(i.e., kwargs are passed from Scene
to Theme
), we must document what each of these does:
const minimal_default = Attributes(
palette = default_palettes,
font = "Dejavu Sans", # font, can be any in system
backgroundcolor = :white, # color of background
color = :black, ## color of what?
colormap = :viridis, # colormap, replicate docs from `Axis`
marker = Circle, ## what is allowed, what does this do?
markersize = 0.1, # size of marker
linestyle = nothing, # in [nothing, :dash, :dot, :dashdot, :dashdotdot], or?
resolution = reasonable_resolution(), # tuple of resolution, Int, auto determined
visible = true, ## what?
clear = true, ## what?
show_axis = true, # show axes or not
show_legend = false, ## what? can we manipulate legend?
scale_plot = true, ## to what?
center = true, ## what else?
axis = Attributes(), ## link to description
axis2d = Attributes(), ## link to description
axis3d = Attributes(), ## link to description
legend = Attributes(), ## what?
axis_type = automatic, ## 2d or 3d I guess?
camera = automatic, ## what else can it be? `campixel!`?
limits = automatic, # link to HyperRectangle docs
padding = Vec3f0(0.1), ## pads all around?
raw = false ## what does it do?
)
(everything with double hashtags needs explanation on what it does, everything with single comments we either have or can link to)
Speaking of publication quality plots, https://github.com/peterkovesi/PerceptualColourMaps.jl seems good. It would be interesting to see whether it can be made compatible with Makie
.
Documentation on recipes from AbstractPlotting
:
AbstractPlotting
There's two types of recipes. Type recipes define a simple mapping from a user defined type to an existing plot type. Full recipes can customize the theme and define a custom plotting function.
Type recipe are really simple and just overload the argument conversion pipeline. This can be done for all plot types or for a subset of plot types:
`convert_arguments(P::Type{<:AbstractPlot}, x::MyType) = convert_arguments(P, rand(10, 10))`
# Only for scatter plots
`convert_arguments(P::Type{<:Scatter}, x::MyType) = convert_arguments(P, rand(10, 10))`
Optionally you may define the default plot type so that plot(x::MyType)
will
use this:
plottype(::MyType) = Surface
@recipe
macroA full recipe for MyPlot
comes in two parts. First is the plot type name,
arguments and theme definition which are defined using the @recipe
macro.
Second is a custom plot!
for MyPlot
, implemented in terms of the atomic
plotting functions.
We use an example to show how this works:
# arguments (x, y, z) && theme are optional
@recipe(MyPlot, x, y, z) do scene
Theme(
plot_color => :red
)
end
This macro expands to several things. Firstly a type definition:
const MyPlot{ArgTypes} = Combined{myplot, ArgTypes}
The type parameter of Combined
contains the function instead of e.g. a
symbol. This way the mapping from MyPlot
to myplot
is safer and simpler.
(The downside is we always need a function myplot
- TODO: is this a problem?)
The following signatures are defined to make MyPlot
nice to use:
myplot(args...; kw_args...) = ...
myplot!(scene, args...; kw_args...) = ...
myplot(kw_args::Dict, args...) = ...
myplot!(scene, kw_args::Dict, args...) = ...
#etc
(not 100% settled what signatures there will be)
A specialization of argument_names
is emitted if you have an argument list
(x,y,z)
provided to the recipe macro:
argument_names(::Type{<: MyPlot}) = (:x, :y, :z)
This is optional but it will allow the use of plot_object[:x]
to
fetch the first argument from the call
plot_object = myplot(rand(10), rand(10), rand(10))
, for example.
Alternatively you can always fetch the i
th argument using plot_object[i]
,
and if you leave out the (x,y,z)
, the default version of argument_names
will provide plot_object[:arg1]
etc.
The theme given in the body of the @recipe
invocation is inserted into a
specialization of default_theme
which inserts the theme into any scene that
plots Myplot
:
function default_theme(scene, ::Myplot)
Theme(
plot_color => :red
)
end
As the second part of defining MyPlot
, you should implement the actual
plotting of the MyPlot
object by specializing plot!
:
function plot!(plot::MyPlot)
# normal plotting code, building on any previously defined recipes
# or atomic plotting operations, and adding to the combined `plot`:
lines!(plot, rand(10), color = plot[:plot_color])
plot!(plot, plot[:x], plot[:y])
plot
end
It's possible to add specializations here, depending on the argument types
supplied to myplot
. For example, to specialize the behavior of myplot(a)
when a
is a 3D array of floating point numbers:
const MyVolume = MyPlot{Tuple{<:AbstractArray{<: AbstractFloat, 3}}}
argument_names(::Type{<: MyVolume}) = (:volume,) # again, optional
function plot!(plot::MyVolume)
# plot a volume with a colormap going from fully transparent to plot_color
volume!(plot, plot[:volume], colormap = :transparent => plot[:plot_color])
plot
end
It'd be obvious to depend on ColorSchemes imho.
Thanks a lot for getting this started!
Maybe we could replace the stars scatter plot with real stars?
I actually started with that dataset - but took it out when putting it into the gallery :D
Large datasets are just so annoying to integrate... Maybe we should have a fetch_data
, that downloads or generates random data depending on the context
PerceptualColorMaps already works just fine:
surface(rand(10, 10), colormap = PerceptualColorMaps.cmap("R3"))
Thanks a lot for getting this started!
Maybe we could replace the stars scatter plot with real stars?
I actually started with that dataset - but took it out when putting it into the gallery :D Large datasets are just so annoying to integrate... Maybe we should have a
fetch_data
, that downloads or generates random data depending on the context
I see the issue now...maybe we could just generate random data with random RGBA values and glows? That might look too much like noise, though - maybe we could weight it a bit.
Here's an idea: why not try to replicate some of the Plots
examples in the Makie docs? That way Plots
users can transition more smoothly, and some of the more common features will become a bit more obvious.
Not sure if this is the right place for it but I have some silly little toy programs that might serve as useful beginner examples. E.g.: https://github.com/pbouffard/miniature-garbanzo/blob/master/robot.jl which looks like this: https://giphy.com/gifs/25JgIK6v56kKIi7CsG. Probably I have a bunch of rookie Julia mistakes in there. If you think it's useful as a demo then hopefully the PR will help me learn what those are! ;)
@pbouffard that is pretty awesome :) We should definitely make it part of the gallery!
The other one currently in that repo (earthmoon.jl) looks like this: https://giphy.com/gifs/348zy5r9Mnd34KEiro
@pbouffard you should make a PR to MakieGallery! If you take a look at examples/examples3d.jl
, you can put:
@block PatrickBouffard ["3d"] begin
@cell "Robot" [interaction, 3d, lines, slider] begin
... # put your code here
end
end
Can you update any attribute of a plot's Theme
by using scene[end][:something] = something else
?
what do you mean by theme? Just any attribute of a particular plot? If yes, yeah should be... but some attributes sadly don't update right now with GLMakie (e.g. if they change the underlying opengl shader)... Should invest some time at some point to make it consistent, even if it's inefficient
Do you have a list of which ones don't work?
attributes: shading, linestyle and then heatmap/image/surface xy ranges get unlifted (woops, that should be easy to fix)
Perfect, that should get integrated into the updating
docs whenever I get around to them.
@piever, could you give us a list of all the capabilities that StatsMakie has now? I'm not sure which ones are production ready or not. I'd like to flesh out the StatsMakie examples a bit more, with examples of box plots, OHLC, KDE et cetera like what Simon did in MakieThemes' example.
That'd be great! StatsMakie is definitely under-documented!
The tutorial includes the "grouping and data" aspect, then there are boxplot
and violin
(same interface as StatsPlots). corrplot
is broken (I was waiting forgrid!
to get fixed in Makie but maybe I should give up and implement it with hbox
and vbox
).
In terms of Analysis
(which are stats to do on your data before plotting) there are:
density
(KDE, 1 or 2D)histogram
(1, 2 or even 3D though it looks silly)frequency
(count occurrences of discrete variables, 1 or 2D)linear
(linear regression)smooth
(LOESS regression)You would basically write plot(density(bandwidth = 0.1), x, y)
or something analogous for other Analysis
.
In terms of "quality":
corrplot
is brokenx
or y
are vectors of strings (I think this is the major limitation at the moment, though it should be addressable now that it's fixed in Makie)Everything else should work well. Feel free to ping me if you open a documentation PR, I'd be happy to help!
From Slack, thanks to @briochemc:
I specifically struggled with rotating the the "scene" (I used Rotations.jl to make a quaternion to use with
rotate!
in the end) and zooming in and out (I did not figure that out but I did not need it badly in the end, so I just accepted life without zooming) I think the documentation is a bit sparse. Some functions could help with a bit of explanation. Maybe this could be done with "examples of modifying the existing examples" (like "Placing a title", or "moving a label" , or "Changing the camera angle", or "Zooming in and out", etc.) Also having all the examples in the form of a gallery of images rather than a long list of URLs, something like Tikz Examples (http://www.texample.net/tikz/examples/all/), would be better IMHO. (I think Makie.jl looks great BTW, I don't want to sound like I did not enjoy using it — It allowed me to create what I wanted! :smile:)
He was on the old docs, but this does bring up valid points about rotations and such. The 'gallery of images' thing we already have 😄 but there are still, of course, improvements to be made.
On the raw=true
attribute:
it just creates the plot object and adds it to the scene...and doesn't do any of the following; calculating limits, making sure that a camera exists, making sure that an axis exists, it doesn't center the view
Another Idea for addition to docs: I could never find a description for Point2f0() and Point3f0(). Scatter seems not the work with the latter... I don't really know how to use them (how are they understood by the plotting functions?) even though examples are full of them.
Scatter seems not the work with the latter
That must be a bug or wrong usage... Can you post a minimal example?
Let us assume you have located a plot, let's call this p
- this could come from p = plot!(...)
or p = scene.plots[i]
or some other way. There is a scene transfer_scene
which you want to transfer this plot to. You can simply do this by push!(transfer_scene, p)
, which takes care of all the backend features necessary to insert the plot. At worst, simply redisplay it.
Note that you should not do push!(transfer_scene.plots, p)
, since this does not tell the backend anything.
Major topics:
Scene
kwargs - resolution, background colour, etc.Scene
kwargs)update*!
functions as well as changing Themes and updating Axis)ColorSchemes.jl
andPerceptualColorSchemes.jl
in Makie (solved by JuliaPlots/MakieGallery.jl#11)Minor stuff:
Examples:
Please put more in the comments!