Issue Controlling Size of Holoviews + Datashader with Matplotlib Backend - python

I'm currently trying to use holoviews+datashader with the matplotlib backend. The data I'm using has very different x and y ranges and the result is that the datashader plots are stretched unhelpfully. The opts and output keywords I've tried using can solve the problem with the holoviews only plots but not once datashade is applied.
For example:
import holoviews as hv
hv.extension('matplotlib')
import numpy as np
from holoviews.operation.datashader import datashade
np.random.seed(1)
positions = np.random.multivariate_normal((0,0),[[0.1,0.1], [0.1,50.0]], (1000000,))
positions2 = np.random.multivariate_normal((0,0),[[0.1,0.1], [0.1,50]], (1000,))
points = hv.Points(positions,label="Points")
points2 = hv.Points(positions2,label="Points2")
plot = datashade(points) + points2
plot
Generates:
datashader and points output
I can control the size of the points only plot using the fig_size opts keyword
e.g. points2(plot=dict(fig_size=200))
but the same doesn't work for datashader plots. Any advice for changing the size of such datashader figures with matplotlib would be greatly appreciated. Ideally, I'd like to use functions and not cell magic keywords so the code can be ported to a script.
Thanks!

Changing the size of matplotlib plots in HoloViews is always controlled by the outer container, so when you have a Layout you can change the size on that object, e.g. in your example that would be:
plot = datashade(points) + points2
plot.opts(plot=dict(fig_size=200))
The other part that might be confusing is that RGB elements (which is what datashade operation returns) uses aspect='equal' by default. You can change that by setting aspect to 'square' or an explicit aspect ratio:
datashade(points).opts(plot=dict(fig_size=200, aspect='square'))
Putting that together you might want to do something like this:
plot = datashade(points).opts(plot=dict(aspect='square')) + points2
plot.opts(plot=dict(fig_size=200))

Related

Plotting from array to geoviews/holoviews. Converting to xarray needed?

First of all, if anyone has a link to a good tutorial to creating colomaps with geoviews or holoviews and transporting that to a dashbooard please send a link. I am trying to mimick what they did at the timestamp in the video here . Also having a hard time finding good documentation of geoviews other than the few examples on their website, so a point to the full docs would be great.
Anyways, I have a pretty basic plot I think. It a mesh of x a mesh of y and a mesh of a z value. I want to plot this in geoviews. It contains interpolated motions from GPS stations basically and I want to make a colormap of the z value. I can plot this really easily with matplotlib with a simple
plot = plt.scatter(mesh_x, mesh_y, c = z1, cmap = cm.hsv)
but trying to get this into geoviews makes a really funky dataframe.
running print(np.shape(mesh_x),np.shape(mesh_y), np.shape(z1)) shows the shape of all of these are (41,348). If I try to put them into a single array with a = np.array((mesh_x,mesh_y,z1)) I get an array of shape (3,41,348) as expected. From here I am really just guessing on what to do. When I try to put this into a geoviews points data frame with
points = [a[0], a[1], a[2]]
df = gv.Points(points)
df.dframe()
and then run df.dframe() it shows two columns, longitude and lattitude with incorrect values, here is a screenshot of what it shows if its helpful
I have tried converting to an xarray because it seems that is preferred in all the examples shown on geoviews website but that looks funky as well. When I try xrtest = xr.DataArray((mesh_x,mesh_y,z1)) I get a xarray that looks like this
At this point I have no idea what to do. I have tried a few different ways that I though may work but I can't remember all of them. This is where I am at now. I am sure I am doing something completely wrong, I just have no idea how to do it correctly. Thank you
Assuming you want a points plot as you are using in Matplotlib, the HoloViews equivalent to plt.scatter is hv.Points. hv.Points accepts a tidy data format that you can get by transposing the data compared to Matplotlib:
import matplotlib.pyplot as plt
from matplotlib import cm
%matplotlib inline
mesh_x = [1,2,3,6]
mesh_y = [6,2,8,0]
z1 = [0.5, 4, 6,2]
plot = plt.scatter(mesh_x, mesh_y, c = z1, cmap = cm.hsv)
import holoviews as hv
hv.extension('matplotlib')
hv.Points(zip(mesh_x,mesh_y,z1), kdims=["x","y"], vdims=["z"]).opts(color='z', cmap="hsv")
Here kdims=["x","y"], is optional but is explicit about the key dimensions you want. You may also want to consider hvPlot, which handles the same data format as plt.scatter:
import pandas as pd
df = pd.DataFrame(dict(x=mesh_x,y=mesh_y,z=z1))
import hvplot.pandas
df.hvplot.scatter(x="x", y="y", c="z", cmap="hsv")

imagesc like feature with non-rectangular grids [MATLAB]

If i want to color a square grid with different color in each grid cells, then it is possible in MATLAB with a simple call to imagesc command like here.
What if i want to color different cells in a grid like this:
Is this functionality available by default in either python or Matlab? I tried discretizing this grid with very small square cells. And then color each cell. That works. But it seems ordinary. Is there a smarter way to get his done?
In python, there is the builtin polar projection for the axes. This projection allows you to automatically use almost every plotting method in polar coordinates. In particular, you need to you pcolor or pcolormesh as follows
import numpy as np
from matplotlib import pyplot as plt
r = np.linspace(0,4,5)
theta = np.linspace(0,2*np.pi,10)
theta,r = np.meshgrid(theta,r)
values = np.random.rand(*(theta.shape))
ax = plt.subplot(111,polar=True)
ax.pcolor(theta,r,values)
plt.show()
Note that this will produce a plot like this
which is almost what you want. The obvious problem is that the patch vertices are joined by straight lines and not lines that follow the circle arc. You can solve this by making the angles array denser. Here is a posible way to do it.
import numpy as np
from matplotlib import pyplot as plt
r = np.linspace(0,4,5)
theta = np.linspace(0,2*np.pi,10)
values = np.random.rand(r.size,theta.size)
dense_theta = np.linspace(0,2*np.pi,100)
v_indeces = np.zeros_like(dense_theta,dtype=np.int)
i = -1
for j,dt in enumerate(dense_theta):
if dt>=theta[i+1]:
i+=1
v_indeces[j] = i
T,R = np.meshgrid(dense_theta,r)
dense_values = np.zeros_like(T)
for i,v in enumerate(values):
for j,ind in enumerate(v_indeces):
dense_values[i,j] = v[ind]
ax = plt.subplot(111,polar=True)
ax.pcolor(T,R,dense_values)
plt.show()
Which would produce
I am not aware of a way to do this in matlab but I googled around and found this that says it can produce pcolor plots in polar coordinates. You should check it out.

Python Matplotlib: plotting histogram with overlapping boundaries removed

I am plotting a histogram using Matplotlib in Python with the matplotlib.bar() function. This gives me plots that look like this:
I am trying to produce a histogram that only plots the caps of each bar and the sides that don't directly share space with the border of another bar, more like this: (I edited this using gimp)
How can I achieve this using Python? Answers using matplotlib are preferable since that is what I have the most experience with but I am open to anything that works using Python.
For what it's worth, here's the relevant code:
import numpy as np
import matplotlib.pyplot as pp
bin_edges, bin_values = np.loadtxt("datafile.dat",unpack=True)
bin_edges = np.append(bin_edges,500.0)
bin_widths = []
for j in range(len(bin_values)):
bin_widths.append(bin_edges[j+1] - bin_edges[j])
pp.bar(bin_edges[:-1],bin_values,width=bin_widths,color="none",edgecolor='black',lw=2)
pp.savefig("name.pdf")
I guess the easiest way is to use the step function instead of bar:
http://matplotlib.org/examples/pylab_examples/step_demo.html
Example:
import numpy as np
import matplotlib.pyplot as pp
# Simulate data
bin_edges = np.arange(100)
bin_values = np.exp(-np.arange(100)/5.0)
# Prepare figure output
pp.figure(figsize=(7,7),edgecolor='k',facecolor='w')
pp.step(bin_edges,bin_values, where='post',color='k',lw=2)
pp.tight_layout(pad=0.25)
pp.show()
If your bin_edges given represent the left edge use where='post'; if they are the rightern side use where='pre'. The only issue I see is that step doesn't really plot the last (first) bin correctly if you use post (pre). But you could just add another 0 bin before/after your data to make it draw everything properly.
Example 2 - If you want to bin some data and draw a histogram you could do something like this:
# Simulate data
data = np.random.rand(1000)
# Prepare histogram
nBins = 100
rng = [0,1]
n,bins = np.histogram(data,nBins,rng)
x = bins[:-1] + 0.5*np.diff(bins)
# Prepare figure output
pp.figure(figsize=(7,7),edgecolor='k',facecolor='w')
pp.step(x,n,where='mid',color='k',lw=2)
pp.show()

1D plot matplotlib

I would like to plot in a single line ticks according to an array (up to 1000 elements). I would rather not to use something like:
plt.xticks(energies[i][j])
because each sample value is written up below tick. I have looked extensively at Matplotlib documentation but didn't find nothing besides hist(). If you guys know other way to visualize 1D arrays into a single line I would very much appreciate, especially if it involves colors representing density of values.
I'm using Spyder 2.2.5, Python 2.7.6 | 64-bit in OSX 10.7.4
Edit
As #tcaswell mentions in comments, eventplot is a good way to do this. Here is an example:
from matplotlib import pyplot as plt
import numpy as np
plt.figure()
a = [1,2,5,6,9,11,15,17,18]
plt.hlines(1,1,20) # Draw a horizontal line
plt.eventplot(a, orientation='horizontal', colors='b')
plt.axis('off')
plt.show()
Or you can use vertical line markers? The example below has the basic idea. You could change the color of the markers to represent density.
from matplotlib import pyplot as plt
import numpy as np
a = [1,2,5,6,9,11,15,17,18]
plt.hlines(1,1,20) # Draw a horizontal line
plt.xlim(0,21)
plt.ylim(0.5,1.5)
y = np.ones(np.shape(a)) # Make all y values the same
plt.plot(a,y,'|',ms = 40) # Plot a line at each location specified in a
plt.axis('off')
plt.show()

How to make an uneven sized 3d bar plot in mayavi

I am using matplotlib to create a 3d bar plot like this one.
Unfortunately matplotlib 3d plotting capabilities are very limiting and have a few bugs (e.g. it can't render properly some viewing angles).
MayaVI2 offers a solution to this problem but I have not found a way to make the size of the bars uneven. In matplotlib you can just give the bar edges as an array using the bar3d function.
Has anyone tried this with mayavi2?
I tried to use barchart from mayavi.
from pylab import *
from mayavi.mlab import *
#define bin edges
x = [1,2,3,5,7,12]
y = [1,2,3,5,7,12]
X, Y = np.meshgrid(x,y)
S = rand(len(x), len(y))
#boxplot(X,Y,S)
barchart(X,Y,S)
Which resulted in all bins with the same width.

Categories