Skip to content

Instantly share code, notes, and snippets.

@mdboom
Last active April 23, 2020 10:59
Show Gist options
  • Save mdboom/048aa35df685fe694330764894f0e40a to your computer and use it in GitHub Desktop.
Save mdboom/048aa35df685fe694330764894f0e40a to your computer and use it in GitHub Desktop.
The absolute bare minimum to get datashader working in matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import datashader as ds
import datashader.transfer_functions as tf
from datashader.colors import Hot
time_period = 60
def bin_data():
global time_period, grouped, group_count, counter, times, groups
grouped = df.groupby([times.hour, times.minute // time_period])
groups = sorted(grouped.groups.keys(), key=lambda r: (r[0], r[1]))
group_count = len(groups)
counter = 0
class LiveImageDisplay(object):
def __init__(self, h=500, w=500, niter=50, radius=2., power=2):
self.height = h
self.width = w
def __call__(self, xstart, xend, ystart, yend):
canvas = ds.Canvas(plot_width=self.width,
plot_height=self.height,
x_range=(xstart, xend),
y_range=(ystart, yend))
agg = canvas.points(df, 'dropoff_x', 'dropoff_y',
ds.count('trip_distance'))
img = tf.interpolate(agg, cmap=Hot, how='log')
print(img.data.shape, img.data.dtype)
return img.data
def ax_update(self, ax):
ax.set_autoscale_on(False) # Otherwise, infinite loop
# Get the number of points from the number of pixels in the window
dims = ax.axesPatch.get_window_extent().bounds
self.width = int(dims[2] + 0.5)
self.height = int(dims[2] + 0.5)
# Get the range for the new area
xstart, ystart, xdelta, ydelta = ax.viewLim.bounds
xend = xstart + xdelta
yend = ystart + ydelta
# Update the image object with our new data and extent
im = ax.images[-1]
im.set_data(self.__call__(xstart, xend, ystart, yend))
im.set_extent((xstart, xend, ystart, yend))
ax.figure.canvas.draw_idle()
path = './nyc_taxi.csv'
datetime_field = 'tpep_dropoff_datetime'
cols = ['dropoff_x', 'dropoff_y', 'trip_distance', datetime_field]
df = pd.read_csv(path, usecols=cols, parse_dates=[datetime_field]).dropna(axis=0)
times = pd.DatetimeIndex(df[datetime_field])
group_count = grouped = groups = None
bin_data()
xmin = -8240227.037
ymin = 4974203.152
xmax = -8231283.905
ymax = 4979238.441
img = LiveImageDisplay()
Z = img(xmin, xmax, ymin, ymax)
fig1, ax2 = plt.subplots(1, 1)
ax2.imshow(Z, origin='lower', extent=(xmin, xmax, ymin, ymax))
# Connect for changing the view limits
ax2.callbacks.connect('xlim_changed', img.ax_update)
ax2.callbacks.connect('ylim_changed', img.ax_update)
plt.show()
@poleguy
Copy link

poleguy commented Oct 7, 2016

The colors of the output look totally broken. It looks like you are passing int32 rgba data into matplotlib which is interpreting it as straight colormap data. I tried to convert it with some code like this, but I'm still having trouble getting it to display right. Something is weird.

    # img.data is rgba as an int32 I think.
    # convert to [r,g,b,a]
    mn4 = np.zeros((self.height,self.width,4),dtype='uint8')
    mn4[:,:,3] = np.bitwise_and(np.right_shift(img.data,24),0xff) # red
    mn4[:,:,2] = np.bitwise_and(np.right_shift(img.data,16),0xff) # green
    mn4[:,:,1] = np.bitwise_and(np.right_shift(img.data,8),0xff) # blue
    mn4[:,:,0] = np.bitwise_and(img.data,0xff) # alpha
    #return img.data
    return mn4

I'm also wondering how this example compares to something like this: holoviz/datashader#200

@dionhaefner
Copy link

This worked for me:

img_rgba = img.data.view(np.uint8).reshape(img.shape + (4,))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment