1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
|
import numpy as np
import vispy.plot as vp
from vispy.color import get_colormap
# load example data
from vispy.io import load_data_file
data = np.load(load_data_file('electrophys/iv_curve.npz'))['arr_0']
data *= 1000 # V -> mV
dt = 1e-4 # this data is sampled at 10 kHz
# create figure with plot
fig = vp.Fig()
plt = fig[0, 0]
plt._configure_2d()
plt.title.text = 'Current Clamp Recording'
plt.ylabel.text = 'Membrane Potential (mV)'
plt.xlabel.text = 'Time (ms)'
selected = None
# plot data
cmap = get_colormap('hsl')
colors = cmap.map(np.linspace(0.1, 0.9, data.shape[0]))
t = np.arange(data.shape[1]) * (dt * 1000)
for i, y in enumerate(data):
line = plt.plot((t, y), color=colors[i])
line.interactive = True
line.unfreeze() # make it so we can add a new property to the instance
line.data_index = i
line.freeze()
# Build visuals used for cursor
cursor_text = vp.Text("", pos=(0, 0), anchor_x='left', anchor_y='center',
font_size=8, parent=plt.view.scene)
cursor_line = vp.Line(parent=plt.view.scene)
cursor_symbol = vp.Markers(pos=np.array([[0, 0]]), parent=plt.view.scene)
cursor_line.visible = False
cursor_symbol.visible = False
cursor_line.order = 10
cursor_symbol.order = 11
cursor_text.order = 10
@fig.connect
def on_mouse_press(event):
global selected, fig
if event.handled or event.button != 1:
return
if selected is not None:
selected.set_data(width=1)
selected = None
for v in fig.visuals_at(event.pos):
if isinstance(v, vp.LinePlot):
selected = v
break
if selected is not None:
selected.set_data(width=3)
update_cursor(event.pos)
@fig.connect
def on_mouse_move(event):
update_cursor(event.pos)
def update_cursor(pos):
global selected, cursor, data, dt, plt
if selected is None:
cursor_text.visible = False
cursor_line.visible = False
cursor_symbol.visible = False
else:
# get data for the selected trace
trace = data[selected.data_index]
# map the mouse position to data coordinates
tr = fig.scene.node_transform(selected)
pos = tr.map(pos)
# get interpolated y coordinate
x = min(max(pos[0], t[0]), t[-2])
ind = x / (dt * 1000)
i = int(np.floor(ind))
s = ind - i
y = trace[i] * (1 - s) + trace[i + 1] * s
# update cursor
cursor_text.text = "x=%0.2f ms, y=%0.2f mV" % (x, y)
offset = np.diff(tr.map([[0, 0], [10, 0]]), axis=0)[0, 0]
cursor_text.pos = x + offset, y
rect = plt.view.camera.rect
cursor_line.set_data(np.array([[x, rect.bottom], [x, rect.top]]))
cursor_symbol.set_data(pos=np.array([[x, y]]), symbol='+',
face_color='b')
cursor_text.visible = True
cursor_line.visible = True
cursor_symbol.visible = True
if __name__ == '__main__':
fig.app.run()
|