regl-scatterplot
regl-scatterplot copied to clipboard
Constant point size when zooming
Is there a way to fix the size of points, so that point sizes are unaffected by the zoom? I have an extremely dense plot which requires significant zooming to read meaningful information. But it seems that I have to choose between having very large points after zooming in, or very small points when zoomed out.
Unfortunately there is not at the moment. One feature that I've been working on that would probably help you a lot is https://github.com/flekschas/regl-scatterplot/pull/143 but I didn't have the dime to finish it yet.
We could introduce a property to control the point scaling. Right now the points are scaled using the inverse hyperbolic arcsin function which seems to work well in most cases but I can see extreme cases where one might want a different zoom scale factor. It should be trivial to add such a zoom scale factor. I would expect it to behave as follows. 0 means zoom-based scaling is turned off. 1 means zoom-based scaling works as it does today (this should be the default). And values above 1 should result in increased scaling. The factor would have to be added to https://github.com/flekschas/regl-scatterplot/blob/master/src/index.js#L1374C1-L1382C5
Maybe all we need is to change line 1377 as follows:
return (
(Math.asinh(max(1, ((camera.scaling[0] - 1) * pointScaleFactor) + 1)) / Math.asinh(1)) *
window.devicePixelRatio
)
Example:
pointScaleFactor = 1
Array.from({ length: 10 }, (_, cameraScaling) => Math.asinh(Math.max(1.0, (cameraScaling * pointScaleFactor) + 1)) / Math.asinh(1))
// => [1, 1.638, 2.063, 2.377, 2.624, 2.827, 3, 3.150, 3.283, 3.402]
pointScaleFactor = 0
Array.from({ length: 10 }, (_, cameraScaling) => Math.asinh(Math.max(1.0, (cameraScaling * pointScaleFactor) + 1)) / Math.asinh(1))
// => [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
pointScaleFactor = 2
Array.from({ length: 10 }, (_, cameraScaling) => Math.asinh(Math.max(1.0, (cameraScaling * pointScaleFactor) + 1)) / Math.asinh(1))
// => [1, 2.063, 2.624, 3, 3.283, 3.509, 3.698, 3.860, 4.001, 4.127]
Any thoughts @kiledal or is this not needed anymore?
I think zooming with point sizes in data units would be very useful. I have two use-cases in mind:
- Making heatmaps. Using regl-scatterplot would be more light-weight than higlass.
- Plotting multi-well plate layouts. My research group does biological experiments in 384-well plates and this would enable plotting datum based on the well positions on the plate.
Admittedly, for both of these use cases it would look better if the shape could be changed from circle to square, but that's besides this very issue. (Edit: I now see that squares are used in performance mode)
@danr Can you clarify what you mean by zooming with data units? Would my proposal be useful for your use cases or are you thinking of something else?
Implementing the above change should be quick but before I add the feature I want to be sure it's actually useful :)
Oh and yeah, the performance mode renders points as squares, which you might be able to use for rendering heatmaps (I haven't tried that yet but it sounds like a cool try)
@flekschas I used terminology from Bokeh, they use screen units and data units:
- screen unit points have a constant size when zooming (like 10 px)
- data unit points zoom with the data, aligned with the axis (like 1 data unit)
Defined here: https://docs.bokeh.org/en/latest/docs/user_guide/styling/visuals.html#screen-units-and-data-space-units
Interestingly, your asinh-sized points are neither of these!
Interesting! So screen units refer to constant CSS pixel point sizes and data units refer to data-driven point sizes.
The asinh transformation only transforms the camera scale, so regl-scatterplot effectively implements screen units with geometric zooming. There's no concept of rescaling the point size to the data domain at the moment.