Load Data
The following python script can be used to load and plot the data produced by the NeuropixelsV1e Headstage example workflow.
# Import necessary packages
import os
import numpy as np
import matplotlib.pyplot as plt
import spikeinterface.extractors as se
import probeinterface
import probeinterface.plotting
#%% Set parameters for loading data
suffix = 0 # Change to match filenames' suffix
data_directory = 'C:/Users/open-ephys/Documents/data/np1e' # Change to match files' directory
plot_num_channels = 10 # Number of channels to plot
ap_gain = 1000 # Change to the ap band gain used
lfp_gain = 50 # Change to the lfp band gain used
start_t = 3.0 # Plot start time (seconds)
dur = 2.0 # Plot time duration (seconds)
# Neuropixels 1.0 constants
fs_hz_ap = 30e3
fs_hz_lfp = fs_hz_ap / 12
sample_offset = 512
sample_gain = 1171.875
num_channels = 384
#%% Load acquisition session data
dt = {'names': ('time', 'acq_clk_hz', 'block_read_sz', 'block_write_sz'),
'formats': ('datetime64[us]', 'u4', 'u4', 'u4')}
meta = np.genfromtxt(os.path.join(data_directory, f'start-time_{suffix}.csv'), delimiter=',', dtype=dt, skip_header=1)
print(f'Recording was started at {meta["time"]} GMT')
print(f'Acquisition clock rate was {meta["acq_clk_hz"] / 1e6 } MHz')
#%% Load Neuropixels 1.0 probe data
np1 = {}
# Load Neuropixels 1.0 AP clock data and convert clock cycles to seconds
np1['ap_time'] = np.fromfile(os.path.join(data_directory, f'np1-clock_{suffix}.raw'), dtype=np.uint64).astype(np.double) / meta['acq_clk_hz']
# Load and scale Neuropixels 1.0 AP data
gain_to_uV_ap = sample_gain / ap_gain
offset_to_uV_ap = -sample_offset * gain_to_uV_ap
ap_rec = se.read_binary(os.path.join(data_directory, f'np1-spike_{suffix}.raw'),
sampling_frequency=fs_hz_ap,
dtype=np.uint16,
num_channels=num_channels,
gain_to_uV=gain_to_uV_ap,
offset_to_uV=offset_to_uV_ap)
np1['ap_uV'] = ap_rec.get_traces(return_scaled=True, channel_ids=np.arange(plot_num_channels))
ap_time_mask = np.bitwise_and(np1['ap_time'] >= start_t, np1['ap_time'] < start_t + dur)
# Load Neuropixels 1.0 LFP clock data. The LFP is sampled every at 1/12th the rate of AP data
np1['lfp_time'] = np1['ap_time'][::12]
# Load and scale Neuropixels 1.0 LFP data
gain_to_uV_lfp = sample_gain / lfp_gain
offset_to_uV_lfp = -sample_offset * gain_to_uV_lfp
lfp_rec = se.read_binary(os.path.join(data_directory, f'np1-lfp_{suffix}.raw'),
sampling_frequency=fs_hz_lfp,
dtype=np.uint16,
num_channels=num_channels,
gain_to_uV=gain_to_uV_lfp,
offset_to_uV=offset_to_uV_lfp)
np1['lfp_uV'] = lfp_rec.get_traces(return_scaled=True, channel_ids=np.arange(plot_num_channels))
lfp_time_mask = np.bitwise_and(np1['lfp_time'] >= start_t, np1['lfp_time'] < start_t + dur)
#%% Load BNO055 data
dt = {'names': ('clock', 'euler', 'quat', 'is_quat_id', 'accel', 'grav', 'temp'),
'formats': ('u8', '(1,3)f8', '(1,4)f8', '?', '(1,3)f8', '(1,3)f8', 'f8')}
bno055 = np.genfromtxt(os.path.join(data_directory, f'bno055_{suffix}.csv'), delimiter=',', dtype=dt)
# Convert clock cycles to seconds
bno055_time = bno055['clock'] / meta['acq_clk_hz']
bno055_time_mask = np.bitwise_and(bno055_time >= start_t, bno055_time < start_t + dur)
#%% Plot time series
fig = plt.figure(figsize=(12, 8))
# Plot scaled Neuropixels 1.0 AP data
plt.subplot(611)
plt.plot(np1['ap_time'][ap_time_mask], np1['ap_uV'][ap_time_mask])
plt.xlabel('Time (seconds)')
plt.ylabel('µV')
plt.title('AP Band Voltage')
# Plot scaled Neuropixels 1.0 LFP data
plt.subplot(612)
plt.plot(np1['lfp_time'][lfp_time_mask], np1['lfp_uV'][lfp_time_mask])
plt.xlabel('Time (seconds)')
plt.ylabel('µV')
plt.title('LFP Band Voltage')
# Plot BNO055 data
plt.subplot(613)
plt.plot(bno055_time[bno055_time_mask], bno055['euler'].squeeze()[bno055_time_mask])
plt.xlabel('Time (seconds)')
plt.ylabel('degrees')
plt.title('Euler Angles')
plt.legend(['Yaw', 'Pitch', 'Roll'])
plt.subplot(614)
plt.plot(bno055_time[bno055_time_mask], bno055['quat'].squeeze()[bno055_time_mask])
plt.xlabel('Time (seconds)')
plt.title('Quaternion')
plt.legend(['X', 'Y', 'Z', 'W'])
plt.subplot(615)
plt.plot(bno055_time[bno055_time_mask], bno055['accel'].squeeze()[bno055_time_mask])
plt.xlabel('Time (seconds)')
plt.ylabel('m/s\u00b2')
plt.title('Linear Acceleration')
plt.legend(['X', 'Y', 'Z'])
plt.subplot(616)
plt.plot(bno055_time[bno055_time_mask], bno055['grav'].squeeze()[bno055_time_mask])
plt.xlabel('Time (seconds)')
plt.ylabel('m/s\u00b2')
plt.title('Gravity Vector')
plt.legend(['X', 'Y', 'Z'])
fig.tight_layout()
#%% Load and plot Neuropixels 1.0 probeinterface probe group
np1_config = probeinterface.io.read_probeinterface(os.path.join(data_directory, f'np1-config.json'))
probeinterface.plotting.plot_probegroup(np1_config, show_channel_on_click=True)
plt.show()
Note
- To plot probeinterface data, save the probe configuration file into the same directory of your data.
- This script will attempt to load entire files into arrays. For long recordings, data will need to
be split into more manageable chunks by:
- Modifying this script to partially load files
- Modifying the workflow to cyclically create new files after a certain duration