Select data from a Datashader plot - holoviews

I'm using Datashader to make crossplots of different parameters due to the quantity of data I'm working with. My idea is to enable some kind of interaction that allows the user to select directly from the plot, the outliers based on the data's tendency showed these ones. I wonder if Holoviews Selection1D stream is compatible with datashader.
This code simulates what I meant:
import numpy as np
import holoviews as hv
from holoviews import opts
from holoviews import streams
from holoviews.operation.datashader import datashade
hv.extension('bokeh')
# Tools to select data
opts.defaults(opts.Points(tools=['box_select', 'lasso_select']))
# Random points to plot
random_points = hv.Points(np.random.randn(1000))
# Holoviews
selection = streams.Selection1D(source=random_points)
# Selected points by Holoviews selection stream
selected_box = hv.DynamicMap(lambda index: random_points.iloc[index],
kdims=[], streams=[selection])
# Final Overlay
Overlay = (random_points * selected_box).opts(padding = 0.01)
Overlay
So far so good, whenever I call selection I get a matrix compounded by the index of the selected points. After Calling the Datashader plot with datashade(Overlay) , the interaction between random_points and selected_box breaks, therefore I'm not sure if this stream is compatible with datashader or if the way I use the stream is wrong!
This is what inspired my idea:
http://holoviews.org/reference/apps/bokeh/selection_stream.html#bokeh-gallery-selection-stream

Helpful example to see the possibilities. Now I know it's not necessary to extract the data from the plot... I could just do another plot using Dynamic maps and streams, either by bounds or selection1D.

Related

different element sizes with matplotlib backend

I'm trying to accomplish a heatmap color bar to add extra info about the kdims in my heatmap. (Like the colSideColors option if you are familiar with R's heatmap.2 package.)
I can get a nice result with bokeh backend, but don't know how to get custom (different) element sizes when using matplotlib backend.
Can anyone tell me how to make the strip plot "shorter" (less "high") in the matplotlib backend example?
Setup
import pandas as pd
import numpy as np
import holoviews as hv
hv.extension('bokeh', 'matplotlib')
# dummy data
samples = ['sample{}'.format(x) for x in range(5)]
df = pd.DataFrame(np.random.rand(5, 5),columns=samples, index=samples).reset_index()
df = df.melt(id_vars='index', var_name='y').rename(columns={'index': 'x'})
# column means
df_strip = df.groupby('x').mean().reset_index()
df_strip['y'] = 'dummy'
# make plots
heatmap = hv.HeatMap(df, kdims=['x','y'])
strip = hv.HeatMap(df_strip, kdims=['x','y'])
Result with bokeh
%%output size=100 backend='bokeh'
(strip.options(xaxis=None, yaxis=None, height=50) +
heatmap.options(xrotation=90)).cols(1)
Result with matplotlib backend
%%output size=100 backend='matplotlib'
%%opts Layout [sublabel_format='' vspace=0.1]
(strip.options(xaxis=None, yaxis=None, aspect=1) +
heatmap.options(xrotation=90, aspect=1)).cols(1)
hv.__version__
'1.10.8'
The sizing unfortunately works very differently in the two backends, which means it can be somewhat difficult to get the same behavior. In this particular case you will want to set a larger aspect on the strip plot while also telling the Layout that it should weight the aspect when computing the size of the plots. Doing that looks something like this:
%%output size=100 backend='matplotlib'
%%opts Layout [sublabel_format='' vspace=0.1 aspect_weight=1]
(strip.options(xaxis=None, yaxis=None, aspect=5) +
heatmap.options(xrotation=90, aspect=1)).cols(1)

Custom art in NetworkX graph

Is anyone aware of a way to put in an image (vector or raster) in place of a text label for a node or edge in a NetworkX graph visualization?
I prefer a solution that uses the matplotlib plot engine rather than the graphviz, but will take either solution.
In principle, the below should work. I transform the points into pixel coordinates, and then use figimage to put the image at that point.
import networkx as nx
import matplotlib.pyplot as plt
import matplotlib.image as image
im = image.imread('Lower_case_a.png')
G=nx.fast_gnp_random_graph(2,1)
pos = nx.spring_layout(G)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.patch.set_alpha(0)
ax.axis(xmin=-1,xmax=2,ymin=-1,ymax=2)
for node in G.nodes():
x,y = pos[node]
trans_x, trans_y = ax.transData.transform((x,y))
fig.figimage(im,trans_x,trans_y) #could use custom image for each node
nx.draw_networkx_edges(G,pos)
plt.savefig('tmp.png')
It almost works for me. I get:
I think that's because of some weird issue on my computer. When I run the code provided at matplotlib.org to explain transData.transform, it should give me, but instead I get
So I feel like the offset I'm seeing may be a problem on my machine and I'd like to try another computer. At any rate, let me know if this works for you and hopefully it at least points you in the right direction.

Networkx; move edges in nx.MultiDiGraph plot

The question is very simple. However, neither official documentation or searching has helped much. I am looking to create something that (in a simple case) looks like this:
I am looking to plot a very simple directed graph, with one node, and two self-loops. This is what I got so far.
import networkx as nx
from nxpd import draw
G = nx.MultiDiGraph()
G.graph['dpi'] = 120
{'state': 'Low'}
G.add_nodes_from(range(1,2))
G.add_edges_from([(1,1),(1,1)])
pos=nx.get_node_attributes(G,'pos')
draw(G, show='ipynb')
Which produces
But, I would very much like that the other edge was on the left, and of equal size to the first one.
You are using Graphviz to draw the graph with the draw() command there. The attribute settings for Graphviz are documented at http://www.graphviz.org/content/attrs
In your case you want to use "headport" and "tailport" to set where the edges meet the node.
Try
import networkx as nx
G = nx.MultiDiGraph()
G.add_edge(1,1,headport='sw',tailport='nw')
G.add_edge(1,1,headport='se',tailport='ne')
nx.write_dot(G,'sl.dot')
# run dot -Tpng sl.dot >sl.png
The documentation

R + Import picture in a graph panel

I have a three-element (nrow=1, ncol=3) panel, with a single caption across, to illustrate a point. Two elements are graphs. The third one has to be a picture, which I need to import from public sources. Can you guide me on how to import this picture? Many thanks.

How to scale figure down to a particular size in inches in matplotlib

Suppose I prepare a PDF figure in matplotlib and let us say I have specified the original dimensions of the figure to be 10x10 inches. Would it be possible to produce essentially the same figure, but scaled down to 7x7in (so that all the fonts/point sizes, etc, would scale down appropriately)?
I do understand that I can open my 10x10 file in a vector graphics editor and perform the rescaling, but I was interested whether there is some simple switch that would do this directly from matplotlib.
Use set_size_inches, like so:
import matplotlib.pyplot as plt
fig=plt.figure()
ax=fig.add_subplot(111)
fig.set_size_inches([10,10])
ax.plot([1,3,2],[2,2,2],'ro-')
plt.savefig('10x10.png')
fig.set_size_inches([4,4])
plt.savefig('4x4.png')

Resources