Programmatically update HoloViews Annotator - bokeh

I'm trying to create a HoloViews plot, where user can draw rectangular boxes above existing shapes and annotate them with free text in the table.
For that, I'm using the Annotator with BoxEdit tool as in the documentation:
boxes = hv.Rectangles([(0, 0, 1, 1), (1.5, 1.5, 2.5, 2.5)])
box_annotator = hv.annotate.instance()
layout = box_annotator(boxes.opts(width=800, height=400, responsive=False), annotations=['Label'])
This works fine for interactive mouse input.
How can I now add / remove / change the annotation rectangles programmatically? Python solution would be the best, but CustomJS is also the way to go.

Related

How can the font (size, boldness, name) be changed for a python-pptx graph

This question is for whoever is struggling to make sense of the python-pptx docs and has not found a way to directly change the fonts ( of the x-axis, y-axis labels and etc) of their python -pptx chart objects
I will be answering my own question
Once you've created a graph you can change its attributes as follows. I only changed the font size but you can change boldness,color, type...
chart = slide.shapes.add_chart(XL_CHART_TYPE.COLUMN_CLUSTERED, x, y, cx, cy, chart_data)
chart.chart_part.chart.font.size = Pt(11)
the .chart_part has many useful controls for python -pptx chart layout

R sf point Popups inaccessible after adding polygon via simplevis

I am trying to create an interactive map (using the simplevis and leaflet packages) to be used in an RMarkdown HTML presentation. The popups work fine when no polygon is added but as soon as the polygon is added the popups can no longer be accessed.
The purpose is to have popups for the sf point data and to only show the legend of the point data. The polygon is added to show the boundries.
How can I fix this?
Sample data and code
library(sf)
library(leaflet)
library(simplevis)
leaf_sf_col(example_point,
col_var = trend_category,
popup = TRUE) %>%
leaflet::addPolygons(data = sf::st_transform(example_borders, 4326),
color = "#35B779",
weight = 3,
fillOpacity = 0,
opacity = 1)
Use addPolylines instead of addPolygons, then the polygon feature won't be capturing the click events (which is what I think is happening) because its only lines instead of an area-covering polygon.

How to display the hover information based on a given x-value?

I would like to display the hover information on a stocks plot based on a given x-value instead of the current mouse position.
EDIT: the x-value is set with a slider.
EDIT2:
I am running a folder app and use slider "on change" events. I want to pass the slider value to the plot. There are several plots and the slider just serves the function of highlighting a position simultaneously in all plots. Here is the relevant code:
slider.on_change('value', update_plots)
def update_plots(attr, old, new):
# some code involving 'slider.value'
# e.g. plot.set_hover_by_x_value(slider.value)
EDIT3:
A minimal example would be a single line plot and a slider that is used to highlight a point on the line:
p = figure(plot_width=400, plot_height=400)
p.line([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], line_width=2)
slider = Slider(start=0, end=5, value=0, step=1, title='x-value')
slider.on_change('value', update_plots)
def update_plots(attr, old, new):
# magic code to highlight the point "slider.value" in "p"
As of Bokeh 1.1 there is no programmatic means to create hover tooltips. They are currently tied to explicit, actual UI interactions (e.g. a mouse moving and hitting a scatter point).
As an alternative, you could use a Label annotation to display information at a given location instead.
There are two kinds of tooltips in Bokeh:
#: Associated with columns in a ColumnDataSource object
$: Special fields such as coordinates of the mouse
In this case you should use #column_with_x_values in your tooltip list for your hovertool to show the given x-values.
More information on the hovertool and examples can be found on this page.

What are Bokeh's 'screen units'?

In Bokeh, what are 'screen units'?
The web isn't forthright on what these creatures are and I've had no luck gleaning their meaning from the (0.9.3) source code
The Bokeh source uses them in its examples, such as this from bokeh/_glyph_functions.py for 'rect':
from bokeh.plotting import figure, output_file, show
plot = figure(width=300, height=300)
plot.rect(x=[1, 2, 3], y=[1, 2, 3], width=10, height=20, color="#CAB2D6",
width_units="screen", height_units="screen")
show(plot)
but I don't see them defined anywhere. What other options would 'width_units' support?
Bokeh lets users set renderer locations either by screen units (related to the pixel distance from the origin of the plot) or data units (which uses the mapper that is used to calculate the plot ranges based on the input data)
This helps in cases like adding box annotations, where sometimes you want the box to be linked to screen (perhaps always in the middle of the screen) or linked to data values (having a box at x=10)
The docs:
https://github.com/bokeh/bokeh/blob/master/bokeh/enums.py#L46

How can I hide the axes in matplotlib 3d?

How can I make a 3D plot without showing the axes?
When plotting a 3d plot, Matplotlib not only draws the x, y, and z axes, it draws light gray grids on the x-y, y-z, and x-z planes. I would like to draw a "free-floating" 3D plot, with none of these elements.
Stuff I've tried:
# Doesn't work; this hides the plot, not the axes
my_3d_axes.set_visible(False)
# Doesn't do anything. Also, there's no get_zaxis() function.
my_3d_axes.get_xaxis().set_visible(False)
my_3d_axes.get_yaxis().set_visible(False)
Ben Root provided a patch that fixes this for 1.0.1. It can be found as an attachment to the last email of this thread. To quote Ben:
Ok, looks like the hiding of the 3d axes was a feature added after the v1.0 release (but before I started working on mplot3d). This patch should enable the basic feature without interfering with existing functions. To hide the axes, you would have to set the private member "_axis3don" to False, like so:
ax = plt.gca(projection='3d')
ax._axis3don = False
If you do it this way, then you will get what you want now, and your code will still be compatible with mplot3d when you upgrade (although the preferred method would be to call set_axis_on() or set_axis_off()).
I hope that helps!
Ben Root
ax.set_axis_off()
Just to provide a concrete and direct example of what was mentioned at https://stackoverflow.com/a/7363931/895245
#!/usr/bin/env python3
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
import mpl_toolkits.mplot3d.art3d as art3d
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_axis_off()
# Draw a circle on the x=0 'wall'
p = Circle((0, 0), 1, fill=False)
ax.add_patch(p)
art3d.pathpatch_2d_to_3d(p, zdir="x")
p = Circle((0, 0), 1, fill=False)
ax.add_patch(p)
art3d.pathpatch_2d_to_3d(p, zdir="z")
ax.set_xlim(-1.2, 1.2)
ax.set_ylim(-1.2, 1.2)
ax.set_zlim(-1.2, 1.2)
plt.savefig('main.png', format='png', bbox_inches='tight')
Output:
Without ax.set_axis_off() it would look like:
You will notice however that this produces an excessively large whitespace margin around the figure as it simply hides the axes but does not change the viewbox. I tried bbox_inches='tight' and it did not help as it does in 2D. How to solve that at: Remove white spaces in Axes3d (matplotlib)
Tested on matplotlib==3.2.2.

Resources