Data Processing Example¶
[15]:
from fibermagic.IO.NeurophotometricsIO import read_project_rawdata, read_project_logs
from pathlib import Path
import plotly.express as px
from fibermagic.core.demodulate import zdFF_airPLS, add_zdFF
from fibermagic.core.perievents import perievents
from fibermagic.utils.download_dataset import download
[16]:
download('arena-data')
Downloading started
Downloading Completed, Extracting...
The data was taken in two batches from different mice. Batch 1 consists of one recording per mouse (n=2). Batch 2 includes two recordings per mouse (n=7). Every mouse was recorded individually (no multiple mice per recording).
The experimental environment was a 1m x 1m sized arena. The mouse was able to move freely. Food pellets, a running wheel, and a novel object was placed in different locations of the arena. Sessions were 15 minutes long.
For behavioral evaluation, a video was recorded using a IR-camera. The video was used to determing the region in which the mouse was.
[17]:
PROJECT_PATH = Path(r'data')
df_idx = read_project_rawdata(PROJECT_PATH,
['Batch', 'Day', 'FP', 'Mouse_'], 'arena.csv', ignore_dirs=['meta', 'processed', 'processed.zip'])
data\Batch 1\Day1\FP\B9295\arena.csv
data\Batch 1\Day1\FP\B9296\arena.csv
data\Batch 2\Day1\FP\B9443\arena.csv
data\Batch 2\Day1\FP\B9670\arena.csv
data\Batch 2\Day1\FP\B9671\arena.csv
data\Batch 2\Day1\FP\B9888\arena.csv
data\Batch 2\Day1\FP\B9889\arena.csv
data\Batch 2\Day1\FP\B9890\arena.csv
data\Batch 2\Day1\FP\B9891\arena.csv
data\Batch 2\Day2\FP\B9443\arena.csv
data\Batch 2\Day2\FP\B9670\arena.csv
data\Batch 2\Day2\FP\B9671\arena.csv
data\Batch 2\Day2\FP\B9888\arena.csv
data\Batch 2\Day2\FP\B9889\arena.csv
data\Batch 2\Day2\FP\B9890\arena.csv
data\Batch 2\Day2\FP\B9891\arena.csv
A first spike into to investigate the raw data.¶
By changing values to different mice and days, you can see that mice B9671 and B9889 had bad signals.
[18]:
df = df_idx.reset_index()
df.Mouse.unique() # list recorded mice
[18]:
array(['B9295', 'B9296', 'B9443', 'B9670', 'B9671', 'B9888', 'B9889',
'B9890', 'B9891'], dtype=object)
[19]:
px.line(df[(df.Mouse=='B9890') & (df.Day=='Day2') & (df.Channel == 560)].Signal).show()
[20]:
px.line(df[(df.Mouse=='B9890') & (df.Day=='Day2') & (df.Channel == 560)].Reference)
[21]:
df_idx = add_zdFF(df_idx, smooth_win=10, remove=200, lambd=5e9).set_index('FrameCounter', append=True)
df_idx
[21]:
Signal | Reference | zdFF (airPLS) | |||||||
---|---|---|---|---|---|---|---|---|---|
Batch | Day | FP | Mouse_ | Mouse | Channel | FrameCounter | |||
Batch 1 | Day1 | FP | B9295 | B9295 | 470 | 201 | 0.006334 | 0.004026 | -0.138428 |
202 | 0.006327 | 0.004017 | -0.138428 | ||||||
203 | 0.006363 | 0.004003 | -0.258778 | ||||||
204 | 0.006339 | 0.004004 | -0.359795 | ||||||
205 | 0.006374 | 0.004003 | -0.461999 | ||||||
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
Batch 2 | Day2 | FP | B9891 | B9891 | 560 | 23482 | 0.005995 | 0.004768 | -0.297719 |
23483 | 0.005960 | 0.004758 | -0.276701 | ||||||
23484 | 0.006041 | 0.004695 | -0.097237 | ||||||
23485 | 0.005952 | 0.004757 | -0.187640 | ||||||
23486 | 0.006012 | 0.004762 | -0.384082 |
735342 rows × 3 columns
Look at eating behavior in the full session¶
[22]:
df = df_idx.reset_index()
subset = df[(df.Mouse=='B9890') & (df.Day=='Day2') ]
food_intake_9890 = [2277, 2516, 2692, 3234, 3548, 3712, 3936, 4315, 4483, 4671, 6323, 6418, 6589, 6659, 6853, 7590, 8890]
fig = px.line(x=(subset.FrameCounter - 297)/2.5, y=subset['zdFF (airPLS)'], color=subset.Channel)
for food in food_intake_9890:
fig = fig.add_vline(x=food)
fig.show()
[23]:
food_intake_9670 = [195, 289, 324, 362, 739, 781, 1262, 1330, 1454, 2130, 2190, 2310, 2366, 3075, 4022, 4080, 4180, 4240, 4350, 4480, 5140, 7410, 8094, 8150]
subset = df[(df.Mouse=='B9670') & (df.Day=='Day2') & (df.Channel==560) ]
fig = px.line(x=(subset.FrameCounter - 307)/2.5, y=subset['zdFF (airPLS)'])
for food in food_intake_9890:
fig = fig.add_vline(x=food)
fig.show()
Synchronize photometry recording with behavioral events from video recording¶
[24]:
import pandas as pd
def arena_sync(logs, path):
ttl = pd.read_csv(path/'input1.csv')
frame_times = pd.read_csv(path/'time.csv')
first_ttl = ttl.loc[0, 'Item2']
first_frame = ((first_ttl - frame_times.Item2).abs().idxmin())
framerate = 30
logs['Timestamp'] = logs.Frame / 30
logs['FrameCounter'] = logs.Timestamp * 25 // 1
logs['FrameCounter'] += first_frame
logs['FrameCounter'] = logs.FrameCounter.astype(int)
logs = logs.rename(columns={'ROI': 'Event'})
# ignore events that are too close to start or end of recording
logs = logs[(logs.Timestamp > 20) & (logs.Timestamp < max(logs.Timestamp) - 20)]
return logs.set_index('FrameCounter')
[25]:
import os
logs = read_project_logs(PROJECT_PATH,
['Batch', 'Day', 'FP', 'Mouse_'], sync_fun=arena_sync, ignore_dirs=['meta', 'processed', 'processed.zip'])
logs
[25]:
Frame | Event | Timestamp | ||||||
---|---|---|---|---|---|---|---|---|
Batch | Day | FP | Mouse_ | Mouse | FrameCounter | |||
Batch 1 | Day1 | FP | B9295 | B9295 | 2522 | 2717 | non_roi_out | 90.566667 |
2523 | 2718 | food_in | 90.600000 | |||||
2572 | 2777 | food_out | 92.566667 | |||||
2573 | 2778 | non_roi_in | 92.600000 | |||||
2578 | 2784 | non_roi_out | 92.800000 | |||||
... | ... | ... | ... | ... | ... | ... | ... | ... |
Batch 2 | Day2 | FP | B9891 | B9891 | 20104 | 23044 | non_roi_in | 768.133333 |
20118 | 23061 | non_roi_out | 768.700000 | |||||
20119 | 23062 | wheel_in | 768.733333 | |||||
20183 | 23139 | wheel_out | 771.300000 | |||||
20184 | 23140 | non_roi_in | 771.333333 |
3008 rows × 3 columns
Select appropriate events and calculate perievents¶
[26]:
# use only entries if mouse was more than x seconds in region
min_sec_in_region = 10
idxin = None
onset = 0
to_drop = list()
for index, row in logs.iterrows():
if '_in' in row.Event:
idxin = index
onset = row.Timestamp
elif '_out' in row.Event:
if row.Timestamp - onset < min_sec_in_region:
to_drop.append(idxin)
to_drop.append(index)
logs = logs.drop(index=to_drop)
[ ]:
peri = perievents(df_idx, logs, 15, 25)
peri
c:\users\georg\git\fibermagic\fibermagic\core\perievents.py:41: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
C:\Users\Georg\anaconda3\envs\fibermagic\lib\site-packages\pandas\core\frame.py:3678: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
c:\users\georg\git\fibermagic\fibermagic\core\perievents.py:58: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
Further Analysis¶
[ ]:
# save datastream, logs and perievents
output_path = PROJECT_PATH / 'processed'
# uncomment if you like to save the output files
# df.to_csv(output_path / 'datastream.csv')
# logs.to_csv(output_path / 'logs_time_criteria_synced.csv')
# peri.to_csv(output_path / 'perievents_time_criteria_synced.csv')
Now, you can use data analysis tools like Tableau or PowerBI or any data analysis technology like R, Matlab, Python (e.g. Seaborn) to visualize your data
[ ]: