How can i update the ColumnDataSource by an "selected.on_change()" event? - bokeh

First, I created a scatter plot out of geogr. coordinates. If i click on one of these circles a second line-plot next to that scatter plot shows further informations depending on what circle i've clicked. That means i have to update the current ColumnDataSource shown in the line-plot by a new one. But if i click on one of those circles the current Source will not be updated. The line-plot still shows the dataset of the old Source.
I'll try to give you a short example of what i've done so far:
def callback(attr, old, new):
# Depending on what circle i've clicked i start a SQL request
# to gain my dataset i want to plot and the new title of the diagram.
# To change the title actually works:
line_plot.title.text = 'new_title'
# "source_new_values" is a ColumnDataSource created out of a
# SQL-request of my database.
# To change the current source doesn't work. The line-plot is still
# showing the old dataset.
source_current_values = source_new_values
scatter_plot = figure(x_axis_label='lat', y_axis_label='lon')
scatter_plot.circle(x='long', y='lat', source=source_coordinates)
# I use the indices to identify what circle was clicked.
source_coordinates.selected.on_change('indices', callback)
line_plot = figure(x_axis_label='time', x_axis_type='datetime',
y_axis_label='values', title='title')
line_plot.line(x='date', y='value', source=source_current_values)

The solution for tat Problem is I'm not able to update the source by a ColumnDataSource, but by a Dictionary using:
source_current_values.data = Dict("some content")

Related

Markers in Holoviews

The following script produces a nice scatterplot as in the picture below
from holoviews import extension, dim, opts, Scatter
from pandas import read_csv
extension('bokeh')
url = 'https://raw.githubusercontent.com/mwaskom/seaborn-data/master/penguins.csv'
df = read_csv(url)
scatterplot = Scatter(df, 'flipper_length_mm', ['body_mass_g','island'] )
scatterplot.opts( color=dim('island').str(), cmap=['red','green','blue'] )
Now, suppose I want to use markers in place of colors for island.
Is there something equivalent to cmap (as in the last line of the script above) for marker?
You can update the code as below to add markers. I have left the colors as is. If you don't need it, can remove that and just keep the markers alone... You can use markers from here
scatterplot.opts( color=dim('island').str(), cmap=['red','green','blue'],
marker=dim('island').categorize({'Torgersen':'circle', 'Biscoe':'diamond', 'Dream':'dash'}) )

Reverse a client-side table in Shiny to click on graph and output

https://yihui.shinyapps.io/DT-rows/
In this example, user clicks the row and it bubbles in on the plot. Is there a way to reverse that - user clicks on the plot point, and the table information outputs?
Your input needs a click event like click or hover. like this:
plotOutput("PlateMap", click = "PlateMap_click", hover = "PlateMap_hover")
Then you need to handle the event with nearpoints() to know what datapoint was clicked or hovered.
res <- nearPoints(datafr, input$PlateMap_click}, allRows = TRUE)
setting allrows to true will add an additional column on res to show what has been selected.
This will provide you with the datapoints then you just need to select them on the table.
To do this you need to call selectrows on a data table proxy. You will need to look at the help for nearpoints and selectrows to get the exact syntax but it would be something like:
selectRows(dataTableProxy("RawData"), res$selected_)

How to change the extent and position of an existing image in bokeh?

I am displaying 2d data as images of varying shapes in a bokeh server, and therefore need to dynamically update not only the image's data source, but also its dw, dh, x, and y properties. In the dummy example below, these changes are made in a callback function which is connected to a Button widget.
I've figured out that I need to access the glyph attribute of the image's GlyphRenderer object, and I can do so through its update() method (see code). But the changes don't take effect until I click the toolbar's Reset button. I've noticed that the changes also mysteriously take effect the second time I activate the callback() function. What is the proper way to make these changes?
import bokeh.plotting
import bokeh.models
import bokeh.layouts
import numpy as np
# set up the interface
fig1 = bokeh.plotting.figure(x_range=(0, 10), y_range=(0, 10))
im1 = fig1.image([], dw=5, dh=5)
button = bokeh.models.Button(label='scramble')
# add everything to the document
bokeh.plotting.curdoc().add_root(bokeh.layouts.column(button, fig1))
# define a callback and connect it
def callback():
# this always works:
im1.data_source.data = {'image': [np.random.random((100,100))]}
# these changes only take effect after pressing the "Reset"
# button, or after triggering this callback function twice:
im1.glyph.update(x=1, y=1, dw=9, dh=9)
button.on_click(callback)
I don't immediately see why you code isn't work. I can suggest explicitly using a ColumnDataSource and linking all of the Image glyph properties to columns in that source. Then you should be able to update the source.data in a single line and have all of the updates apply.
Here's some incomplete sample code to suggest how to do that:
from bokeh.models import Image, ColumnDataSource
from bokeh.plotting import figure
# the plotting code
plot = figure()
source = ColumnDataSource(data=dict(image=[], x=[], y=[], dw=[], dh=[]))
image = Image(data='image', x='x', y='y', dw='dw', dh=dh)
plot.add_glyph(source, glyph=image)
# the callback
def callback():
source.data = {'image': [np.random.random((100,100))], 'x':[1], 'y':[1], 'dw':[9], 'dh':[9]}
button.on_click(callback)

How to set a "formatted value" in googleVis?

I am using googleVis and shiny to (automatically) create a Organizational Chart.
Similar to this question:
Google Visualization: Organizational Chart with fields named the same, I want to use formatted values in googleVis to be able to create fields in an organizational chart, which have the same name. I suspect it has something to do with roles but I cannot figure the correct syntax out.
The help page for gvisOrgChart mentiones formatted values but does not say how to set them:
"You can specify a formatted value to show on the chart instead, but the unformatted value is still used as the ID."
## modified example from help page
library(googleVis)
Regions[7,1] = Regions[8,1] # artificially create duplicated name in another parent node
Org <- gvisOrgChart(Regions)
plot(Org)
In the above example the duplicated name (Mexico) is only shown once in the chart. I want both of them to be drawn (One in the Europe and one in the America parent node).
Thank you for your help
cateraner
After talking to one of the developers of the googleVis package I got the solution to the problem now. The formatted value contains extra speak marks, which have to be removed before the text is usable as HTML.
## modified example from help page
library(googleVis)
# add new entry
levels(Regions$Region) = c(levels(Regions$Region), "{v: 'Germany.2', f: 'Germany'}")
Regions[8,1] = "{v: 'Germany.2', f: 'Germany'}"
Org <- gvisOrgChart(Regions)
# remove extra speak marks
Org$html$chart <- gsub("\"\\{v", "\\{v", Org$html$chart)
Org$html$chart <- gsub("\\}\"", "\\}", Org$html$chart)
plot(Org)
In the resulting graph you have two times "Germany", one under node "America" and one under "Europe". The same way you could add HTML formations to your text (color, font, etc.).
Thanks too Markus Gesmann for helping me on that.

Plotting images but holding visualization until instruction in R

I want to load two jpeg images in R consecutively but they are quite large (4000X3000 pixels)
So simply doing
library(biOps)
x <- readJpeg("image.jpg")
plot(x)
Takes a while. When the first image is displayed the user would have to fill in some observations on the image. I wanted to know if it was possible to plot the image but pause the actual visualization so as to take advantage of the time the user is filling in the data I mentioned only to display the image later, maybe upon an instruction of the user like pressing the enter key.
Can this be done?
One option is to use animation package. saveHTML will create a html file animated by SciAnimator library. You can show the first plot and stop the visualisation, go to the next, use a timer,...
ll.imgs <- list.files(Imgs_folder,patt='jpg',full=TRUE)
saveHTML({
for(i in seq_along(ll.imgs)){
x <- readJpeg("image.jpg")
plot(x) ##maybe you should try grid.raster(x) from grid package
}
}, img.name = "plots", imgdir = "plots_dir",
htmlfile = "random.html", autobrowse = FALSE,
title = "Plotting images but holding visualization until instruction",
outdir=getwd())

Resources