Skip to content

Commit 5c89187

Browse files
committed
almost final version of tutorial material
0 parents  commit 5c89187

File tree

11 files changed

+819
-0
lines changed

11 files changed

+819
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
__pycache__
2+
*.pyc
3+
*~

00-explore.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import matplotlib.pyplot as plt
2+
import numpy as np
3+
plt.ion()
4+
5+
ev = None
6+
7+
8+
def event_printer(event):
9+
"""Helper function for exploring events.
10+
11+
Prints all public attributes +
12+
"""
13+
global ev
14+
ev = event
15+
for k, v in sorted(vars(event).items()):
16+
print('{k}: {v!r}'.format(k=k, v=v))
17+
print('-'*25)
18+
19+
th = np.linspace(0, 2*np.pi, 64)
20+
fig, ax = plt.subplots()
21+
ax.plot(th, np.sin(th), 'o-', picker=5)
22+
23+
cid = fig.canvas.mpl_connect('button_press_event', event_printer)
24+
# fig.canvas.mpl_disconnect(cid)
25+
26+
27+
# EXERCISE
28+
# - Try all 'active' events
29+
# ['button_press_event', 'button_release_event', 'scroll_event',
30+
# 'key_press_event', 'key_release_event', 'pick_event']
31+
# - tweak the print line
32+
# - remove a callback
33+
# - add more than one callback to the canvas

01-callable.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from collections import deque
2+
import matplotlib as mpl
3+
import matplotlib.pyplot as plt
4+
import numpy as np
5+
plt.ion()
6+
7+
# disable the built in key bindings
8+
for k in ['keymap.all_axes',
9+
'keymap.back',
10+
'keymap.forward',
11+
'keymap.fullscreen',
12+
'keymap.grid',
13+
'keymap.home',
14+
'keymap.pan',
15+
'keymap.save',
16+
'keymap.xscale',
17+
'keymap.yscale',
18+
'keymap.zoom']:
19+
mpl.rcParams[k] = []
20+
21+
22+
class EventCollector:
23+
def __init__(self, maxlen=12):
24+
self.event_deque = deque([], maxlen=maxlen)
25+
26+
def __call__(self, event):
27+
print('called {} at ({}, {})'.format(event.name,
28+
event.xdata,
29+
event.ydata))
30+
self.event_deque.append(event)
31+
32+
33+
fig, ax = plt.subplots()
34+
35+
th = np.linspace(0, 2*np.pi, 64)
36+
ln, = ax.plot(th, np.sin(th), 'o-', picker=5)
37+
38+
ec = EventCollector()
39+
cid = fig.canvas.mpl_connect('key_press_event', ec)
40+
41+
42+
# EXERCISE
43+
# - Try connecting the same object to events calls
44+
# - add helper function to manage event buffer

02-event_filter.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import matplotlib.pyplot as plt
2+
from itertools import cycle
3+
plt.ion()
4+
5+
6+
class LineMaker:
7+
def __init__(self, ln):
8+
# stash the current data
9+
self.xdata = list(ln.get_xdata())
10+
self.ydata = list(ln.get_ydata())
11+
# stash the Line2D artist
12+
self.ln = ln
13+
self.color_cyle = cycle(['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728',
14+
'#9467bd', '#8c564b', '#e377c2', '#7f7f7f',
15+
'#bcbd22', '#17becf'])
16+
self.button_cid = ln.figure.canvas.mpl_connect('button_press_event',
17+
self.on_button)
18+
self.key_cid = ln.figure.canvas.mpl_connect('key_press_event',
19+
self.on_key)
20+
21+
def on_button(self, event):
22+
# only consider events from the lines Axes
23+
if event.inaxes is not self.ln.axes:
24+
return
25+
26+
# if not the left mouse button or a modifier key
27+
# is held down, bail
28+
if event.button != 1 or event.key is not None:
29+
print('key+button: {!r}+{!r}'.format(event.key, event.button))
30+
return
31+
32+
# get the event location in data-space
33+
self.xdata.append(event.xdata)
34+
self.ydata.append(event.ydata)
35+
36+
# update the artist data
37+
self.ln.set_data(self.xdata, self.ydata)
38+
39+
# ask the GUI to re-draw the next time it can
40+
self.ln.figure.canvas.draw_idle()
41+
42+
def on_key(self, event):
43+
# This is _super_ useful for debugging!
44+
# print(event.key)
45+
46+
# if the key is c (any case)
47+
if event.key.lower() == 'c':
48+
# change the color
49+
self.ln.set_color(next(self.color_cyle))
50+
51+
# ask the GUI to re-draw the next time it can
52+
self.ln.figure.canvas.draw_idle()
53+
54+
fig, ax = plt.subplots()
55+
ln, = ax.plot([], [], '-o')
56+
line_maker = LineMaker(ln)
57+
58+
# EXERCISE
59+
# - modify to remove the closest point on button == 3 or key == 'shift'
60+
# - change the line width for [1-9]
61+
# - clear the line when event.key == 'escape'

03-picking.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import matplotlib.pyplot as plt
2+
from pddc_helpers import (load_bwi_data, aggregate_by_day, extract_day_of_hourly,
3+
label_date)
4+
import uuid
5+
plt.ion()
6+
7+
bwi = load_bwi_data()
8+
bwi = bwi[bwi['year'] > 2014]
9+
bwi_daily = aggregate_by_day(bwi)
10+
11+
12+
class RowPrinter:
13+
def __init__(self, ln, df, picker=10):
14+
ln.set_picker(picker)
15+
self.uid = str(uuid.uuid4())
16+
ln.set_gid(self.uid)
17+
self.ln = ln
18+
self.df = df
19+
self.cid = None
20+
self.connect()
21+
22+
def connect(self):
23+
self.remove()
24+
self.cid = ln.figure.canvas.mpl_connect('pick_event',
25+
self)
26+
27+
def __call__(self, event):
28+
# ignore picks on not-our-artist
29+
if event.artist is not self.ln:
30+
return
31+
# for each hit index, print out the row
32+
for i in event.ind:
33+
print(self.df.iloc[i])
34+
35+
def remove(self):
36+
if self.cid is not None:
37+
self.ln.figure.canvas.mpl_disconnect(self.cid)
38+
self.cid = None
39+
40+
41+
fig, ax = plt.subplots()
42+
ln, = ax.plot('mean', '-o', data=bwi_daily)
43+
ax.set_xlabel('Date [UTC]')
44+
ax.set_ylabel('Air Temperature [℃]')
45+
ax.set_title('BWI')
46+
rp = RowPrinter(ln, bwi_daily)
47+
48+
one_day = extract_day_of_hourly(bwi, 2015, 10, 18)
49+
50+
# EXERCISE
51+
# - make the print out nicer looking
52+
# - make picking add a label with `label_data`
53+
# - use `get_gid` to filter instead of `is not`
54+
# - open a new window with plot of day temperature
55+
# - fig, ax = plt.subplots()
56+
# - one_day = extract_day_of_hourly(bwi, 2015, 10, 18)

04-custom_plotting.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import matplotlib.pyplot as plt
2+
from pddc_helpers import load_bwi_data, aggregate_by_month
3+
plt.ion()
4+
5+
6+
def plot_aggregated_errorbar(ax, gb, label, picker=None, **kwargs):
7+
kwargs.setdefault('capsize', 3)
8+
kwargs.setdefault('markersize', 5)
9+
kwargs.setdefault('marker', 'o')
10+
eb = ax.errorbar(gb.index, 'mean',
11+
yerr='std',
12+
data=gb,
13+
label=label,
14+
picker=picker,
15+
**kwargs)
16+
fill = ax.fill_between(gb.index, 'min', 'max', alpha=.5,
17+
data=gb, color=eb[0].get_color())
18+
ax.legend()
19+
ax.figure.canvas.draw_idle()
20+
return eb, fill
21+
22+
bwi = load_bwi_data()
23+
bwi_monthly = aggregate_by_month(bwi)
24+
25+
fig, ax = plt.subplots()
26+
ax.set_xlabel('Date [UTC]')
27+
ax.set_ylabel('Air Temperature [℃]')
28+
ax.set_title('BWI')
29+
30+
arts = plot_aggregated_errorbar(ax, bwi_monthly, 'bwi')

0 commit comments

Comments
 (0)