Tip

Download this tutorial as a Jupyter notebook, or as a python script with code cells. We highly recommend using Visual Studio Code to execute this tutorial.

Tutorial 8: Action Potential DurationΒΆ

Warning

This tutorial is currently and APD computation functionality in preparation. We will add more information soon.

This tutorial discusses how to compute action potential durations (APDs) and APD maps from cardiac optical mapping data using optimap. The routines include detecting action potential upstrokes and repolarization times and can also be used to compute calcium transient durations (CaTDs) or CaTD maps. In addition, we will also compute APD and CaTD histograms.

First, we will load a voltage- and calcium-sensitive optical mapping recording, see Example Data Files for more information, and extract the two channels/videos from the recording:

import optimap as om

filename = om.download_example_data("Dualchannel_1.npy")

video_voltage = om.load_video(filename, start_frame=0, step=2)  # even frames
video_calcium = om.load_video(filename, start_frame=1, step=2)  # odd frames

You can plot optical traces interactively as follows:

om.compare_traces([video_voltage, video_calcium], labels=["Voltage", "Calcium"], size=3, fps=1000)

image.png

or define a position (or multiple positions):

position = [(51, 61)]
# positions = [(51, 61), (50, 70)]

and then display the corresponding optical traces manually. The corresponding action potential trace looks as follows:

trace_v = om.extract_traces(video_voltage, position, size=3, show=True, fps=1000)
../../_images/247503f87a7fbca80fbf284beddf1caef737ac6f9f483149e64c03b333ea54db.png

and the corresponding calcium trace looks as follows:

trace_ca = om.extract_traces(video_calcium, position, size=3, show=True, fps=1000, colors=['orange'])
../../_images/0ca978c4433f9e6d7eb26d1e8288aba6f176b51ffe1a04f8abd70e211d2e8cba.png

In order to plot the voltage and calcium traces in the same graph, we need to normalize the data:

video_voltage_norm = om.video.normalize_pixelwise(video_voltage)
# switch the polarity of the voltage data
video_voltage_norm = 1.0 - video_voltage_norm

# Scale Ca signal to [0, 0.65] to match the voltage potentials (there is no absolute value of the signals)
video_calcium_norm = om.video.normalize_pixelwise(video_calcium, ymax=0.65)

The comparison reveals a slight delay in the calcium transient:

t1 = 50
t2 = 350
om.compare_traces([video_voltage_norm, video_calcium_norm], position, size=3, fps=1000)
om.compare_traces([video_voltage_norm[t1:t2], video_calcium_norm[t1:t2]], position, size=3)
../../_images/b92a17af4d77b6e109726c28c6b70cbaf7ece48d58fb0a01eb791f8fe2070602.png ../../_images/18c8775e4c8c569a12f843f8db31e73e36dc0104f4a2c982cd6d218844ba9b6c.png

In this recording, the action potential exhibits the characteristic notch during the depolarization phase. The notch is often not visible in cardiac optical mapping data and optimap will by default assume that there is no notch. This is relevant when computing action potential durations (APDs) for certain heights of the action potential (e.g. APD50 at 50% of the height of the action potential). Here, we normalize the trace with clipping (vmax=0.58) to remove the notch:

trace_v_norm = om.trace.normalize(trace_v)
trace_v_norm = om.trace.normalize(1-trace_v_norm,vmax=0.58)

om.show_traces(trace_v_norm)
om.show_traces(trace_v_norm[t1:t2])
../../_images/91586f94a2aa317a5af18ef18885597e02f02647b6fcd36a17c023652d746869.png ../../_images/ec36e151ed22c43f423c856cb631ed8e469eeb1424936911983121926885f7c0.png
<Axes: xlabel='Frame', ylabel='Intensity'>