-
-
Notifications
You must be signed in to change notification settings - Fork 295
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding dotplots #1950
Comments
In general, I would say yes. The first constraint can be addressed by having marker sizes in pixelspace; I'm not clear on the second constraint, but you may want to dynamically update markersize depending on the plot's parent Scene's limits. For the third constraint, a similar consideration applies. Knowing the marker's position in "input space", or even the Scene's transformed space if you're so inclined, you can project that into pixel space. Knowing the marker size in pixel space means that you can just continuously add that to the y-axis. If you want to plot values directly in pixel space, simply use For the fourth constraint - again, just recalculate when the relevant aspects of the Scene (transformation, px_area) change. |
Here's one example implementation. I think px_area you can get inside a plotting function, but not ax.finallimits. But there was a way to extract it from projection matrices I think, even if that's not the cleanest way. @ffreyer showed it to me somewhere but I forgot. using Random
Random.seed!(123)
f = Figure()
ax = Axis(f[1, 1])
xs = 1:15
binwidth = step(xs)
ms = lift(ax.scene.px_area, ax.finallimits) do pxa, lims
widths(pxa)[1] / widths(lims)[1] * binwidth
end
dots = lift(ax.scene.px_area, ax.finallimits) do pxa, lims
counts = rand(1:7, length(xs))
points = Point2f[]
for (x, count) in zip(xs, counts)
for i in 1:count
push!(
points,
Point2f(
(x - lims.origin[1]) / (lims.widths[1]) * pxa.widths[1],
(i - 0.5) * ms[],
)
)
end
end
points
end
scatter!(ax, dots, markersize = ms, space = :pixel)
xlims!(ax, xs.start - 1, xs.stop + 1)
hideydecorations!(ax)
# lines(f[1, 2], 1:10) # add other content to figure
f |
In general these kinds of plot are always a bit brittle because if the aspect ratio changes too much the dots have to flow out of the scene. |
Thanks @jkrumbiegel and @asinghvi17 for the suggestions!
This seems to work: finallimits = lift(px_area, transformation(scene).transform_func) do pxa, tfunc
orig = project(camera(scene), :pixel, :data, apply_transform(tfunc, zero(origin(pxa))))
corn = project(camera(scene), :pixel, :data, apply_transform(tfunc, widths(pxa)))
wid = corn - orig
Rect2(Vec2(orig[1:2]), Vec2(wid[1:2]))
end
Yes, that kind of brittleness is unavoidable. |
|
Thanks, @ffreyer! This worked for getting data limits: finallimits = lift(scene.camera.projectionview) do pv
xmin, xmax = minmax((((-1, 1) .- pv[1, 4]) ./ pv[1, 1])...)
ymin, ymax = minmax((((-1, 1) .- pv[2, 4]) ./ pv[2, 2])...)
origin = Makie.Vec2(xmin, ymin)
Makie.Rect2(origin, Makie.Vec2(xmax, ymax) - origin)
end
@jkrumbiegel (how) can this be done within a recipe (with no access to axis)? |
It currently can't be done from within recipes, we need either axis hints in recipes or a step above the current pipeline that can control Axis / Legend etc. Maybe you can overload how data limits are determined for this plot type so you get meaningful x limits. |
That's what |
This kind of plot would need to trigger the axis to reset limits after its calculation is done. Maybe we could place a hook in a Scene's attributes, that an Axis can pick up on when it's updated and react to it? |
I'd like to revive a subset of JuliaPlots/StatsMakie.jl#107 to add a
dotplot
function that constructs Wilkinson dot plots (a laggplot2::geom_dotplot
). This consists ofstacks
recipe for constructing stacks of markers, given the position of each stack in the data dimension, the number of markers in each stack, and the width of the stack in the data dimensiondotplot
recipe that calls the function in (1) and passes the data to (2) for plotting(1) and (3) are trivial. (2) is a little tricky because the stacks must satisfy 4 constraints:
There are a few ways to do this, but they generally require some information about the axis (e.g. limits, aspect ratio). Can this information be accessed within a recipe?
The text was updated successfully, but these errors were encountered: