regl-scatterplot icon indicating copy to clipboard operation
regl-scatterplot copied to clipboard

Constant point size when zooming

Open kiledal opened this issue 1 year ago • 7 comments

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.

kiledal avatar Mar 01 '24 09:03 kiledal

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]

flekschas avatar Mar 01 '24 15:03 flekschas

Any thoughts @kiledal or is this not needed anymore?

flekschas avatar Mar 25 '24 13:03 flekschas

I think zooming with point sizes in data units would be very useful. I have two use-cases in mind:

  1. Making heatmaps. Using regl-scatterplot would be more light-weight than higlass.
  2. 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 avatar Apr 22 '24 13:04 danr

@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 :)

flekschas avatar Apr 23 '24 20:04 flekschas

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 avatar Apr 23 '24 20:04 flekschas

@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!

danr avatar Apr 23 '24 21:04 danr

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.

flekschas avatar Apr 24 '24 14:04 flekschas