Database usage and fetching results#
Here we show how to retrieve the data generated by recording the electrical activity of the organoids from the database.
See also
Spike sorting : Utility to perform basic spike sorting on the data.
Connection to the database#
Simply create a database object, and then use the available methods to retrieve your data of interest.
Make sure to have the up-to-date token for the experiment you are interested in.
Every time we change the organoids on an MEA, we create a new fs ID such as "fs300"
.
This is accessible through your Experiment token, specifically the exp_name
attribute.
Make sure to record and recover the token you used during your experiment to perform the data analysis.
Example code#
from dateutil import parser
from datetime import timedelta
from neuroplatform import Database, Experiment
db = Database()
exp = Experiment("Your token here")
FS_NAME = (
exp.exp_name
) # FS ID for the MEA. This changes every time we change the organoids.
Tip
Please contact us if you need the fs ID for a specific MEA/time.
Database functions#
Note
All database times are in UTC.
Spike events#
A spike event is logged whenever the voltage from an electrode crosses a threshold of six times the standard deviation of the noise.
You can query a list of spike events with the timestamp, the amplitude (maximum absolute voltage of the peak across 3ms around the spike) and the channel number using get_spike_event
Caution
To avoid returning large amounts of data, keep the time window small.
We recommed starting with 5 minutes, and increasing/decreasing the window as needed.
start = parser.parse("2024-04-05T00:00:00.000Z")
stop = start + timedelta(minutes=5)
spike_event_df = db.get_spike_event(start, stop, FS_NAME)
Spike count per minute#
You can get the spike count per minute for all electrodes for a given experiment name using get_spike_count
to get a DataFrame with the spike count per minute for each electrode, with the timestamp.
spike_per_min_df = db.get_spike_count(start, stop, FS_NAME)
Raw spike events#
Every spike event is recorded for 3ms around the spike. You can get the raw signal for these 3ms of spike events using get_raw_spike_event
to get a DataFrame with the timestamp, the electrode number, and the amplitude values for each event in a long format.
Since the sampling rate is 30kHz, each spike event will have 90 samples.
Caution
Raw data is very memory-intensive. Make sure to query a small time window first, and increase/decrease as needed.
from tqdm import tqdm
df_spike_event = db.get_spike_event(start, start + timedelta(seconds=1), FS_NAME)
raws = []
for i, row in tqdm(df_spike_event.iterrows(), total=df_spike_event.shape[0]):
t = row["Time"]
t1 = t - timedelta(milliseconds=1)
t2 = t + timedelta(milliseconds=2)
raws.append(db.get_raw_spike(t1, t2, row["channel"]))
Example plot#
import numpy as np
from lets_plot import (
ggplot,
ggtitle,
geom_line,
aes,
ggsize,
gggrid,
)
def plot_raw_channel(channel: int):
df_chan = df_spike_event[df_spike_event["channel"] == channel]
# Start with an empty plot
p = ggplot()
p += ggtitle(f"Channel {channel}")
for i, row in df_chan.iterrows():
df_raw = raws[i]
if df_raw.shape[0] == 90:
df_raw["Time [ms]"] = np.linspace(-1, 2, 90)
p += geom_line(aes(x="Time [ms]", y="Amplitude"), data=df_raw)
return p
channels = df_spike_event["channel"].unique()
list_plot = []
for i, chan in enumerate(channels):
list_plot.append(plot_raw_channel(chan))
nbCol = 3
nbRow = len(list_plot) // nbCol
if len(list_plot) % nbCol != 0:
nbRow += 1
gggrid(list_plot, ncol=nbCol) + ggsize(800, 300 * nbRow)
Triggers#
You can obtain the triggers used for stimulation using get_triggers
to return a DataFrame with the timestamp, the trigger number, the status (up/down, which corresponds to the times where the trigger was enabled/disabled respectively) and the tag if any.
triggers_df = db.get_all_triggers(start, stop, FS_NAME)
Impedance#
When you have measured impedance using the Intan, you can get the recorded impedance values using get_impedance
to return a DataFrame with the timestamp, the electrode number, and the impedance values.
df_impedance = db.get_impedance(start, stop)
Miscellanous measurements#
We also provide access to various environmental measurements within the incubator hosting the MEAs :
CO2 levels
O2 levels
Temperature
Humidity
Pressure
Pump flowrate
Door opening/closing events
CO2, O2, Temperature, Humidity, Pressure#
Simply provide a start and stop time to obtain the recorded values.
co2_df = db.co2(start, stop)
o2_df = db.o2(start, stop)
temp_df = db.temperature(start, stop)
pressure_df = db.pressure(start, stop)
humidity_df = db.humidity(start, stop)
Flowrate#
There are 4 pumps, one for each MEA. You can access the flowrate values using :
port = 3 # port is the MEA number from 1 to 4
flow_df = db.flowrate(start, stop, port)
Door events#
There are currently two incubators:
Incubator 0 hosts the MEAs
Incubator 1 hosts the organoids in culture
Values of 0 or 1 indicate the door is being opened or closed respectively.
To access opening/closing events, use the following :
door_df = db.door(start, stop)