Can I constrain 1 axis in bokeh? - bokeh

I'm using bokeh to display events over a long period of time. The events are binary, so there's no requirement to be able to scale the y-axis, and in fact it looks quite odd when panning and zooming that the height of the events changes.
This is particularly a problem with zooming, since it zooms in both axes.
Is there a way I can constrain the axes, so there's no way to pan and zoom in y, while still being able to pan and zoom in x?

Turns out the pan and zoom tools have dimensions which can be independently specified:
plot = bk.figure(tools="reset,hover,wheel_zoom,pan")
pan_tool = plot.select(dict(type=PanTool))
pan_tool.dimensions=["width"]
zoom_tool = plot.select(dict(type=WheelZoomTool))
zoom_tool.dimensions=["width"]

Related

How to get the width in pixels of a Y Axis and/or set the width explicitly

I am trying to perform my own logic for hit testing and have dynamic Y Axis that exist within my lightningchart JS charts. At the moment I am off by the amount of pixels that the axis is taking up, but have not found a way to determine this value.
Axis documentation shows the use of Axis.getHeight() which returns the height in pixels for the X Axis.
Is there a way to set/read the width of Y Axis in LightningCharts JS?
Thanks
Edit: As requested for more information.
I am using pointer down/move/end/out to detect finger/pointer/mouse position over the charts.
This particular chart presents for example the following data
[x: 0, y: 20]
[x: 3600, y: 21]
[x: 86400, y: 19]
Where x is time in seconds and y is temperature in Celsius.
This will be represented as a lineseries for visual but also a point series for interaction. Users will be able to drag the points up/down based on an interval of say 0.5C and left/right based on a time interval of say 600 (5 minutes).
On tablet, this interaction must be performed by first tapping on the point (to activate it, and present a tooltip) and then dragging the point. This is to prevent conflict with panning/zooming the chart.
All of the above has been developed and is working for the exception of when the YAxes are visible and impact the chart spacing.
I need a way to calculate very specifically the width of all yAxes collectively to support the manual hit testing logic.
Could you elaborate what kind of hit testing you are doing? It is possible that there is a better way to do it than something based on Axis height, hence I am asking.
The getHeight() method is available for both X and Y axis. To use it for Y axis, just do chart.getDefaultAxisY().getHeight(). However, this method is a bit unreliable - the result can be a frame behind. For example, if you use it immediately when the chart is created, it might return a wrong value. A possible workaround is to use it after a timeout.
Another way to know for sure the width of Y axis is to explicitly configure it yourself with Axis.setThickness(100). This would make the Axis 100 pixels wide always.

ILNumerics V5: 3d plot gets distorted when rotate or pan

I have an problem: My 3d plot gets distorted, if I rotate or pan the plot. I know this behaviour is intended to show the user the most at all times, but it looks silly, so I want an orthogonal view or Axes which are equally long.
Earth distorted.
I have an WPF Application, where the ILN Form/Control is hosted via WindowsFormsHost.
I tried every possibility regarding Plotcube.Projection, have set Plotcube.Limits, changed ILN_Panel autosize etc. My next idea was that maybe I need to configure the WPF and/or Forms window itself.
Thanks!
I think that is not possible. At least not easy within PlotCube. If you do not need PlotCube just put the object into the Camera node and set Projection to Orthogonal. And you are done.
With PlotCube it is much more complicated. You must make sure that all containers have equal aspect ratio (width / height) WinformsHostControl, PlotCube, PlotCube.ScreenRect, PlotCube.DataScreenRect, PlotCube.Plots (data group), and its Limits. If you want to rotate everything free you must make sure to have equal aspect ration on all 3 dimensions wehere applicable.

How to get Bokeh to scale scatter plot size according to zoom

Some of the folks on my team, including myself, find it pretty disorienting that in a Bokeh scatter plot, say using the circle method, that for an initial autoscale fit of the data on the figure we can dial in a reasonable size for our data, using for example something like plot.circle( x , y , size=3 )
However when we interactively zoom into our data the glyph sizes as displayed are invariant to the zoom. Is there a way to have them scale proportionally to the zoom we've dialed into? Something akin to an vector graphics interaction (eg svg). If memory serves me right matlab figures and matplotlib figures should maintain zoom proportionality behavior. To demonstrate the behavior we're seeing consider the first image and the red box I approximately zoom into on the second image.
Just as a quick demo using Powerpoint to illustrate the sort of desired behavior...
For circles, set the radius kwarg instead of the size value. (There similar, glyph-specific values for the other glyph-types).
i.e.:
plot.circle(x=[1,2,3], y=[1,2,3], radius=0.5)
size is always rendered in screen coordinates (pixels), but radius and the related properties are computed in data coordinates and should change in magnitude with zooming.
Here's a good demo by Bryan Van de Ven showing the difference between pixel coordinates (size) and data coordinates (radius) given in this conference talk:
Intro to Data Visualization with Bokeh - Part 2 - Strata Hadoop San Jose 2016
... the point is all of these attributes can be vectorized. We could
for instance say size equals you know 2, 4, 6, 8, 10, and now the size
is modulated right. So we have one that has size 2 and one that has
size 4. Size is usually in pixels, radius is usually in data dimension
units. But all the other ones here as well all the colors, all the
visual attributes can be vectorized in this way. You can either give
them a single value as we've done for instance with the line fill
color, or you can give them a vector of values in which case all of
the things are different.
So next exercise here you go to this
notebook this is that second notebook "02 - plotting" it is to try to
create the same example but now set the radius instead of the size and
sort of see what's the difference if you set if you set radius instead
of size.

Centering Perspective Camera on two objects by panning

In Unity, I have a perspective camera, and I've got two transforms in my scene that I want the camera to perfectly center on screen. The camera will pan left/right/up/down to the appropriate location.
So far my approach has been to convert the transform positions to screen positions using Camera.WorldToScreenPoint, and taking their average to find the screen midpoint. From there, I know I want to pan the camera a certain number of units toward that midpoint. What I'm having trouble with is figuring out the formula for deciding how much to pan (or, maybe this isn't even the preferred way to determine this).
I think your approach is great. Let me expand the idea.
So this is your screen :D. Blue circle is where you want your objects to be. There are two scenarios. We will use green dots as an example of zooming scenario. Then red dots for panning scenario.
The trick is, you want to keep the dots as close as possible to circumference of blue circle.
Let's say you get red dots as your objects' screen position. You have to shift them towards the center. Let's calculate CenterOfDots. Then calculate it's difference to CenterOfBlueCircle. That's how much pan you need in screen coordinates.
So you have calculated the pan. Now you want to know how much you need to zoom. Let's say you get green dots this time. Calculate DistanceBetweenDots and compare it to DiameterOfBlueCircle. You want them to be the same. So their difference is how much zoom you need in screen coordinates.
There comes the tricky part. Now you know how much to pan and zoom in screen space. But you need to move the camera in world space. Trying to solve it using geometry magic is fine. But I hate headache :D
So instead, I would iteratively shift my camera using the data I calculated above. Just shift the camera in it's local x-y axes towards HowMuchPan, multiplied by a manually given coefficient PanSpeed. This will give a smooth transition to the camera. Same is for the zoom. This time you shift the camera in it's local z axis using HowMuchZoom multiplied by your manually given coefficient ZoomSpeed.
Hope it helps. Have fun :)
i figured out the mathy approach!
for panning, you want to figure out the average screen position of your objects (i.e. the middle). then you want to generate a couple world points against an arbitrary plane some distance away from the camera. the difference between these points is how much to pan the camera
center=Camera.ScreenToWorldPoint(Screen.width*0.5f, Screen.height*0.5f, 10f)
mid=Camera.ScreenToWorldPoint(averageScreenPoint.x, averageScreenPoint.y, 10f)
Camera.transform.Translate(mid-center)
zooming is a bit more complicated, but very similar to the panning approach. you want to use Camera.ScreenToWorldPoint against an arbitrary plane, but you want to do this for 4 points, which will help you figure out a scale to apply to your camera's z position. psuedocode -
screenMin = Camera.ScreenToWorldPoint(0f,0f,10f);
screenMax = Camera.ScreenToWorldPoint(Screen.width,Screen.height,10f);
objMin = Camera.ScreenToWorldPoint(screenPosMin.x, screenPosMin.y, 10f);
objMax = Camera.ScreenToWorldPoint(screenPosMax.x, screenPosMax.y, 10f);
screenDiff = screenMax-screenMin;
objDiff = objMax-objMin;
Vector3 scale = new Vector3(objDiff.x/screenDiff.x, objDiff.y/screenDiff.y, 0f);
ratio = scale.x < scale.y ? scale.y : scale.x;// pick the one that best puts fits on screen.
Camera.localPosition.z = Mathf.Min(ZoomMin, Camera.localPosition.z*ratio);

Antialiasing in Qt's QGraphicsScene make overlapping lines darker

When using anti-aliasing rendering in Qt's QGraphicsScene, there is a behavior that makes drawings appear not as expected: overlapping lines become darker. I could not see any description of this behavior in the documentation, and I cannot find a way to disable it.
For example if I want to draw such a polygon:
Because of the number of points, it is impossible not to have overlapping lines - fine. But because anti-aliasing is activated, some borders appear 'thicker' than others.
Is there any way to avoid this and have anti-aliased lines that can overlap and yet at the same time be rendered without getting darker?
I know of course that I can redefine the paint() function and draw manually individual lines that do not overlap, but this is what I want to avoid. I am using Pyside and this would significantly slow down the application, due to the high frequency at which paint() is being called.
EDIT Fixed by defining the object shape using QPainterPath / QGraphicsPathItem instead of QPolygon / QGraphicsPolygonItem. In that case the moveTo function allows to avoid lines that overlap.
Another thing you could try is adding half a pixel to your coordinates (not dimensions). This fixed the anti-aliasing issue for me.
XCoord = int(XValue) + 0.5
YCoord = int(XValue) + 0.5
Also make sure that before that you have integer pixel values.

Resources