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()
