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.
Database FAQ : Frequently asked questions about the database.
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.
Caution
By default, the threshold is dynamic, which means it is computed based on the standard deviation of the noise at a certain time interval.
During bursts or stimulation, this standard deviation may increase, which will overall lower the amount of events recorded.
See Variable threshold for more information.
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
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.
Note
The database will record stimulation events. See the relevant question in FAQ for more information.
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)
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)