71 Commits

Author SHA1 Message Date
b48270f475 fix branches 2023-01-24 17:59:22 +01:00
d629948c52 adjusted kernel width slightly 2023-01-24 17:57:12 +01:00
1a0770f86f implemented individual recording plots 2023-01-24 17:57:12 +01:00
ad513f180e implemented plots for all recordings incl bootstrapping, std is over 9000 2023-01-24 17:57:12 +01:00
fda6821211 implemented recording loop 2023-01-24 17:57:12 +01:00
f68630974f corrected zorder in plots, q5 and physical problems okay 2023-01-24 17:57:12 +01:00
ced7f6f1ad something weird 2023-01-24 17:57:12 +01:00
a96a638c31 winner vs loser plot, winner physical strange 2023-01-24 17:57:12 +01:00
b1b9d9d3f1 implemented bootstrapping, q5 of physical still weird 2023-01-24 17:57:12 +01:00
5a0853a023 all event triggered chirps + chirprate with gaussian kernel 2023-01-24 17:57:12 +01:00
8b327fdcbf start implementing gammakernel 2023-01-24 17:57:12 +01:00
5d8c41c899 new plotfile for CTC and PTC 2023-01-24 17:57:12 +01:00
a8171814dd Fish loop needs debugging 2023-01-24 17:57:12 +01:00
7652663fb7 setup 2023-01-24 17:57:12 +01:00
weygoldt
a2960b87a4 Merge branch 'master' of https://whale.am28.uni-tuebingen.de/git/raab/GP2023_chirp_detection 2023-01-24 17:47:48 +01:00
weygoldt
23f5035a59 plot subset 2023-01-24 17:47:43 +01:00
wendtalexander
0aba24e6aa Merge branch 'master' of https://whale.am28.uni-tuebingen.de/git/raab/GP2023_chirp_detection 2023-01-24 17:38:42 +01:00
wendtalexander
39b46221bd plot_event_timepline 2023-01-24 17:38:39 +01:00
a264f96d1f adjusted kernel width slightly 2023-01-24 17:31:28 +01:00
weygoldt
dda0d645f3 Merge branch 'master' of https://whale.am28.uni-tuebingen.de/git/raab/GP2023_chirp_detection 2023-01-24 17:27:43 +01:00
weygoldt
70c4b012be new poster template 2023-01-24 17:27:37 +01:00
wendtalexander
ccc60a8354 adding chirp differences 2023-01-24 16:09:17 +01:00
babcf984e6 implemented individual recording plots 2023-01-24 15:49:17 +01:00
wendtalexander
01f74a471e adding size differences 2023-01-24 15:32:52 +01:00
d3e77d20cc implemented plots for all recordings incl bootstrapping, std is over 9000 2023-01-24 15:22:40 +01:00
wendtalexander
08fbb67163 Merge branch 'master' of https://whale.am28.uni-tuebingen.de/git/raab/GP2023_chirp_detection 2023-01-24 14:19:43 +01:00
wendtalexander
33fa9f92bc chirp body changes 2023-01-24 14:19:42 +01:00
weygoldt
fe41f8f59c Merge branch 'master' of https://whale.am28.uni-tuebingen.de/git/raab/GP2023_chirp_detection 2023-01-24 14:08:11 +01:00
weygoldt
632e0d5fd8 new poster template 2023-01-24 14:08:07 +01:00
wendtalexander
a371755b1c adding variable for scatter plot 2023-01-24 14:07:38 +01:00
wendtalexander
726301c593 adding plot to poster 2023-01-24 14:04:44 +01:00
wendtalexander
ea98a20a68 adding plotstyle boxplots 2023-01-24 13:56:41 +01:00
wendtalexander
4e7bd40ea4 Merge branch 'master' into chirp_bodylength 2023-01-24 13:24:26 +01:00
wendtalexander
fd2207c8c5 finishing plot chirp_body length 2023-01-24 13:23:12 +01:00
wendtalexander
ce560bf939 export functions in modules, plot chirp 2023-01-24 12:06:29 +01:00
weygoldt
ab263d26a2 Merge branch 'master' of https://whale.am28.uni-tuebingen.de/git/raab/GP2023_chirp_detection 2023-01-24 11:43:15 +01:00
wendtalexander
2a32a29d4e plot winner loser chirp counts 2023-01-24 11:43:14 +01:00
weygoldt
5763e807d0 better chirpdetector 2023-01-24 11:43:10 +01:00
dc2074222c Merge branch 'master' into eventtriggeredchirps
zsh:1: command not found: q
2023-01-24 11:08:21 +01:00
b83d3518cc implemented recording loop 2023-01-24 11:07:52 +01:00
fc8b15901c corrected zorder in plots, q5 and physical problems okay 2023-01-24 09:15:36 +01:00
wendtalexander
f36f8606d8 Merge branch 'master' into chirp_bodylength 2023-01-24 09:12:51 +01:00
wendtalexander
fce3503049 finished scp script 2023-01-24 09:11:54 +01:00
wendtalexander
1064261385 Merge branch 'master' of https://whale.am28.uni-tuebingen.de/git/raab/GP2023_chirp_detection 2023-01-24 09:05:58 +01:00
wendtalexander
fc27fabdb3 scp files 2023-01-24 09:05:57 +01:00
weygoldt
6193dab97d added recs 2023-01-24 09:04:57 +01:00
wendtalexander
c967a4e5a9 save plot 2023-01-24 08:14:31 +01:00
weygoldt
87d66dfc2f searchf works and debug mode 2023-01-23 20:27:16 +01:00
b44a346097 Merge branch 'master' into eventtriggeredchirps 2023-01-23 18:06:58 +01:00
782fb60e7a something weird 2023-01-23 18:03:01 +01:00
1bdb7e721a winner vs loser plot, winner physical strange 2023-01-23 17:49:07 +01:00
weygoldt
6159121d76 Merge branch 'master' of https://whale.am28.uni-tuebingen.de/git/raab/GP2023_chirp_detection 2023-01-23 16:09:43 +01:00
weygoldt
a3ddd49040 all broken 2023-01-23 16:09:16 +01:00
e7b9d239d2 implemented bootstrapping, q5 of physical still weird 2023-01-23 15:58:22 +01:00
wendtalexander
c6facd6f0c adding mask for bodylength 2023-01-23 14:51:36 +01:00
wendtalexander
9bfbe8df5e Merge branch 'master' into plot_event_timeline 2023-01-23 13:53:40 +01:00
wendtalexander
9fcdcfe019 adding coment of spectogramm 2023-01-23 13:52:22 +01:00
7fd98743b0 all event triggered chirps + chirprate with gaussian kernel 2023-01-23 13:48:40 +01:00
wendtalexander
d754013aba finishing event_time 2023-01-23 12:04:33 +01:00
b4bc49e366 start implementing gammakernel 2023-01-23 10:01:24 +01:00
e19ddcb391 merge master 2023-01-23 09:58:48 +01:00
c5b9d648e8 new plotfile for CTC and PTC 2023-01-23 09:49:19 +01:00
weygoldt
369f26123a Merge branch 'master' of https://whale.am28.uni-tuebingen.de/git/raab/GP2023_chirp_detection 2023-01-23 09:47:19 +01:00
weygoldt
13b63f4670 added kde functions 2023-01-23 09:47:15 +01:00
wendtalexander
b755fe8bf3 Merge branch 'master' into plot_event_timeline 2023-01-23 09:45:48 +01:00
wendtalexander
039a027108 adding plots 2023-01-23 09:33:47 +01:00
c6340e5a4d Fish loop needs debugging 2023-01-22 21:19:14 +01:00
wendtalexander
16e6003958 adding logger for csv file readout 2023-01-22 11:29:23 +01:00
wendtalexander
333bb045a6 wrong folder 2023-01-21 21:32:40 +01:00
wendtalexander
6c2e74a574 adding plot 2023-01-21 21:31:09 +01:00
b2a4d80d17 setup 2023-01-21 17:36:05 +01:00
32 changed files with 2334 additions and 314 deletions

View File

@@ -1,4 +1,5 @@
import os
import os
import numpy as np
import matplotlib.pyplot as plt
@@ -6,6 +7,7 @@ import matplotlib.pyplot as plt
from IPython import embed
from pandas import read_csv
from modules.logger import makeLogger
from scipy.ndimage import gaussian_filter1d
logger = makeLogger(__name__)
@@ -106,7 +108,6 @@ def correct_chasing_events(
logger.info('Chasing events are equal')
return category, timestamps
# Correct the wrong chasing events; delete double events
wrong_ids = []
for i in range(len(longer_array)-(len_diff+1)):
@@ -123,6 +124,31 @@ def correct_chasing_events(
return category, timestamps
def event_triggered_chirps(
event: np.ndarray,
chirps:np.ndarray,
time_before_event: int,
time_after_event: int
)-> tuple[np.ndarray, np.ndarray]:
event_chirps = [] # chirps that are in specified window around event
centered_chirps = [] # timestamps of chirps around event centered on the event timepoint
for event_timestamp in event:
start = event_timestamp - time_before_event # timepoint of window start
stop = event_timestamp + time_after_event # timepoint of window ending
chirps_around_event = [c for c in chirps if (c >= start) & (c <= stop)] # get chirps that are in a -5 to +5 sec window around event
event_chirps.append(chirps_around_event)
if len(chirps_around_event) == 0:
continue
else:
centered_chirps.append(chirps_around_event - event_timestamp)
centered_chirps = np.concatenate(centered_chirps, axis=0) # convert list of arrays to one array for plotting
return event_chirps, centered_chirps
def main(datapath: str):
# behavior is pandas dataframe with all the data
@@ -144,11 +170,6 @@ def main(datapath: str):
chasing_offset = timestamps[category == 1]
physical_contact = timestamps[category == 2]
##### TODO Physical contact-triggered chirps (PTC) mit Rasterplot #####
# Wahrscheinlichkeit von Phys auf Ch und vice versa
# Chasing-triggered chirps (CTC) mit Rasterplot
# Wahrscheinlichkeit von Chase auf Ch und vice versa
# First overview plot
fig1, ax1 = plt.subplots()
ax1.scatter(chirps, np.ones_like(chirps), marker='*', color='royalblue', label='Chirps')
@@ -160,13 +181,50 @@ def main(datapath: str):
plt.close()
# Get fish ids
all_fish_ids = np.unique(chirps_fish_ids)
fish_ids = np.unique(chirps_fish_ids)
##### Chasing triggered chirps CTC #####
# Evaluate how many chirps were emitted in specific time window around the chasing onset events
# Iterate over chasing onsets (later over fish)
time_around_event = 5 # time window around the event in which chirps are counted, 5 = -5 to +5 sec around event
#### Loop crashes at concatenate in function ####
# for i in range(len(fish_ids)):
# fish = fish_ids[i]
# chirps = chirps[chirps_fish_ids == fish]
# print(fish)
chasing_chirps, centered_chasing_chirps = event_triggered_chirps(chasing_onset, chirps, time_around_event, time_around_event)
physical_chirps, centered_physical_chirps = event_triggered_chirps(physical_contact, chirps, time_around_event, time_around_event)
# Kernel density estimation ???
# centered_chasing_chirps_convolved = gaussian_filter1d(centered_chasing_chirps, 5)
# centered_chasing = chasing_onset[0] - chasing_onset[0] ## get the 0 timepoint for plotting; set one chasing event to 0
offsets = [0.5, 1]
fig4, ax4 = plt.subplots(figsize=(20 / 2.54, 12 / 2.54), constrained_layout=True)
ax4.eventplot(np.array([centered_chasing_chirps, centered_physical_chirps]), lineoffsets=offsets, linelengths=0.25, colors=['g', 'r'])
ax4.vlines(0, 0, 1.5, 'tab:grey', 'dashed', 'Timepoint of event')
# ax4.plot(centered_chasing_chirps_convolved)
ax4.set_yticks(offsets)
ax4.set_yticklabels(['Chasings', 'Physical \n contacts'])
ax4.set_xlabel('Time[s]')
ax4.set_ylabel('Type of event')
plt.show()
# Associate chirps to inidividual fish
fish1 = chirps[chirps_fish_ids == all_fish_ids[0]]
fish2 = chirps[chirps_fish_ids == all_fish_ids[1]]
fish1 = chirps[chirps_fish_ids == fish_ids[0]]
fish2 = chirps[chirps_fish_ids == fish_ids[1]]
fish = [len(fish1), len(fish2)]
### Plots:
# 1. All recordings, all fish, all chirps
# One CTC, one PTC
# 2. All recordings, only winners
# One CTC, one PTC
# 3. All recordings, all losers
# One CTC, one PTC
#### Chirp counts per fish general #####
fig2, ax2 = plt.subplots()
x = ['Fish1', 'Fish2']
@@ -196,22 +254,20 @@ def main(datapath: str):
fig3 , ax3 = plt.subplots()
ax3.bar(['Chirps in chasing events', 'Chasing events without Chirps'], [counts_chirps_chasings, chasings_without_chirps], width=width)
plt.ylabel('Count')
plt.show()
# plt.show()
plt.close()
# comparison between chasing events with and without chirps
# comparison between chasing events with and without chirps
embed()
exit()
if __name__ == '__main__':
# Path to the data
datapath = '../data/mount_data/2020-05-13-10_00/'
datapath = '../data/mount_data/2020-05-13-10_00/'
main(datapath)

View File

@@ -18,6 +18,7 @@ from modules.datahandling import (
purge_duplicates,
group_timestamps,
instantaneous_frequency,
minmaxnorm
)
logger = makeLogger(__name__)
@@ -26,7 +27,7 @@ ps = PlotStyle()
@dataclass
class PlotBuffer:
class ChirpPlotBuffer:
"""
Buffer to save data that is created in the main detection loop
@@ -83,6 +84,7 @@ class PlotBuffer:
q50 + self.search_frequency + self.config.minimal_bandwidth / 2,
q50 + self.search_frequency - self.config.minimal_bandwidth / 2,
)
print(search_upper, search_lower)
# get indices on raw data
start_idx = (self.t0 - 5) * self.data.raw_rate
@@ -94,12 +96,13 @@ class PlotBuffer:
self.time = self.time - self.t0
self.frequency_time = self.frequency_time - self.t0
chirps = np.asarray(chirps) - self.t0
if len(chirps) > 0:
chirps = np.asarray(chirps) - self.t0
self.t0_old = self.t0
self.t0 = 0
fig = plt.figure(
figsize=(14 / 2.54, 20 / 2.54)
figsize=(14 * ps.cm, 18 * ps.cm)
)
gs0 = gr.GridSpec(
@@ -130,8 +133,10 @@ class PlotBuffer:
data_oi,
self.data.raw_rate,
self.t0 - 5,
[np.max(self.frequency) - 200, np.max(self.frequency) + 200]
[np.min(self.frequency) - 300, np.max(self.frequency) + 300]
)
ax0.set_ylim(np.min(self.frequency) - 100,
np.max(self.frequency) + 200)
for track_id in self.data.ids:
@@ -145,45 +150,59 @@ class PlotBuffer:
# get tracked frequencies and their times
f = self.data.freq[window_idx]
t = self.data.time[
self.data.idx[self.data.ident == self.track_id]]
tmask = (t >= t0_track) & (t <= (t0_track + dt_track))
# t = self.data.time[
# self.data.idx[self.data.ident == self.track_id]]
# tmask = (t >= t0_track) & (t <= (t0_track + dt_track))
t = self.data.time[self.data.idx[window_idx]]
if track_id == self.track_id:
ax0.plot(t[tmask]-self.t0_old, f, lw=lw,
ax0.plot(t-self.t0_old, f, lw=lw,
zorder=10, color=ps.gblue1)
else:
ax0.plot(t[tmask]-self.t0_old, f, lw=lw,
zorder=10, color=ps.gray, alpha=0.5)
ax0.plot(t-self.t0_old, f, lw=lw,
zorder=10, color=ps.black)
ax0.fill_between(
np.arange(self.t0, self.t0 + self.dt, 1 / self.data.raw_rate),
q50 - self.config.minimal_bandwidth / 2,
q50 + self.config.minimal_bandwidth / 2,
color=ps.gblue1,
lw=1,
ls="dashed",
alpha=0.5,
)
# ax0.fill_between(
# np.arange(self.t0, self.t0 + self.dt, 1 / self.data.raw_rate),
# q50 - self.config.minimal_bandwidth / 2,
# q50 + self.config.minimal_bandwidth / 2,
# color=ps.gblue1,
# lw=1,
# ls="dashed",
# alpha=0.5,
# )
# ax0.fill_between(
# np.arange(self.t0, self.t0 + self.dt, 1 / self.data.raw_rate),
# search_lower,
# search_upper,
# color=ps.gblue2,
# lw=1,
# ls="dashed",
# alpha=0.5,
# )
ax0.axhline(q50 - self.config.minimal_bandwidth / 2,
color=ps.gblue1, lw=1, ls="dashed")
ax0.axhline(q50 + self.config.minimal_bandwidth / 2,
color=ps.gblue1, lw=1, ls="dashed")
ax0.axhline(search_lower, color=ps.gblue2, lw=1, ls="dashed")
ax0.axhline(search_upper, color=ps.gblue2, lw=1, ls="dashed")
ax0.fill_between(
np.arange(self.t0, self.t0 + self.dt, 1 / self.data.raw_rate),
search_lower,
search_upper,
color=ps.gblue2,
lw=1,
ls="dashed",
alpha=0.5,
)
# ax0.axhline(q50, spec_times[0], spec_times[-1],
# color=ps.gblue1, lw=2, ls="dashed")
# ax0.axhline(q50 + self.search_frequency,
# spec_times[0], spec_times[-1],
# color=ps.gblue2, lw=2, ls="dashed")
for chirp in chirps:
ax0.scatter(
chirp, np.median(self.frequency) + 150, c=ps.black, marker="v"
)
if len(chirps) > 0:
for chirp in chirps:
ax0.scatter(
chirp, np.median(self.frequency), c=ps.red, marker=".",
edgecolors=ps.red,
facecolors=ps.red,
zorder=10,
s=70,
)
# plot waveform of filtered signal
ax1.plot(self.time, self.baseline * waveform_scaler,
@@ -202,25 +221,31 @@ class PlotBuffer:
c=ps.gblue3, lw=lw, label="baseline inst. freq.")
# plot filtered and rectified envelope
ax4.plot(self.time, self.baseline_envelope, c=ps.gblue1, lw=lw)
ax4.plot(self.time, self.baseline_envelope *
waveform_scaler, c=ps.gblue1, lw=lw)
ax4.scatter(
(self.time)[self.baseline_peaks],
self.baseline_envelope[self.baseline_peaks],
(self.baseline_envelope*waveform_scaler)[self.baseline_peaks],
edgecolors=ps.red,
facecolors=ps.red,
zorder=10,
marker="o",
facecolors="none",
marker=".",
s=70,
# facecolors="none",
)
# plot envelope of search signal
ax5.plot(self.time, self.search_envelope, c=ps.gblue2, lw=lw)
ax5.plot(self.time, self.search_envelope *
waveform_scaler, c=ps.gblue2, lw=lw)
ax5.scatter(
(self.time)[self.search_peaks],
self.search_envelope[self.search_peaks],
(self.search_envelope*waveform_scaler)[self.search_peaks],
edgecolors=ps.red,
facecolors=ps.red,
zorder=10,
marker="o",
facecolors="none",
marker=".",
s=70,
# facecolors="none",
)
# plot filtered instantaneous frequency
@@ -230,16 +255,20 @@ class PlotBuffer:
self.frequency_time[self.frequency_peaks],
self.frequency_filtered[self.frequency_peaks],
edgecolors=ps.red,
facecolors=ps.red,
zorder=10,
marker="o",
facecolors="none",
marker=".",
s=70,
# facecolors="none",
)
ax0.set_ylabel("frequency [Hz]")
ax1.set_ylabel("a.u.")
ax2.set_ylabel("a.u.")
ax1.set_ylabel(r"$\mu$V")
ax2.set_ylabel(r"$\mu$V")
ax3.set_ylabel("Hz")
ax5.set_ylabel("a.u.")
ax4.set_ylabel(r"$\mu$V")
ax5.set_ylabel(r"$\mu$V")
ax6.set_ylabel("Hz")
ax6.set_xlabel("time [s]")
plt.setp(ax0.get_xticklabels(), visible=False)
@@ -318,7 +347,7 @@ def plot_spectrogram(
aspect="auto",
origin="lower",
interpolation="gaussian",
alpha=1,
# alpha=0.6,
)
# axis.use_sticky_edges = False
return spec_times
@@ -431,6 +460,28 @@ def window_median_all_track_ids(
return frequency_percentiles, track_ids
def array_center(array: np.ndarray) -> float:
"""
Return the center value of an array.
If the array length is even, returns
the mean of the two center values.
Parameters
----------
array : np.ndarray
Array to calculate the center from.
Returns
-------
float
"""
if len(array) % 2 == 0:
return np.mean(array[int(len(array) / 2) - 1:int(len(array) / 2) + 1])
else:
return array[int(len(array) / 2)]
def find_searchband(
current_frequency: np.ndarray,
percentiles_ids: np.ndarray,
@@ -464,15 +515,17 @@ def find_searchband(
# frequency window where second filter filters is potentially allowed
# to filter. This is the search window, in which we want to find
# a gap in the other fish's EODs.
current_median = np.median(current_frequency)
search_window = np.arange(
np.median(current_frequency) + config.search_df_lower,
np.median(current_frequency) + config.search_df_upper,
current_median + config.search_df_lower,
current_median + config.search_df_upper,
config.search_res,
)
# search window in boolean
search_window_bool = np.ones_like(len(search_window), dtype=bool)
bool_lower = np.ones_like(search_window, dtype=bool)
bool_upper = np.ones_like(search_window, dtype=bool)
search_window_bool = np.ones_like(search_window, dtype=bool)
# make seperate arrays from the qartiles
q25 = np.asarray([i[0] for i in frequency_percentiles])
@@ -480,7 +533,7 @@ def find_searchband(
# get tracks that fall into search window
check_track_ids = percentiles_ids[
(q25 > search_window[0]) & (
(q25 > current_median) & (
q75 < search_window[-1])
]
@@ -492,11 +545,10 @@ def find_searchband(
q25_temp = q25[percentiles_ids == check_track_id]
q75_temp = q75[percentiles_ids == check_track_id]
print(q25_temp, q75_temp)
search_window_bool[
(search_window > q25_temp) & (search_window < q75_temp)
] = False
bool_lower[search_window > q25_temp - config.search_res] = False
bool_upper[search_window < q75_temp + config.search_res] = False
search_window_bool[(bool_lower == False) &
(bool_upper == False)] = False
# find gaps in search window
search_window_indices = np.arange(len(search_window))
@@ -509,6 +561,9 @@ def find_searchband(
nonzeros = search_window_gaps[np.nonzero(search_window_gaps)[0]]
nonzeros = nonzeros[~np.isnan(nonzeros)]
if len(nonzeros) == 0:
return config.default_search_freq
# if the first value is -1, the array starst with true, so a gap
if nonzeros[0] == -1:
stops = search_window_indices[search_window_gaps == -1]
@@ -543,16 +598,14 @@ def find_searchband(
# the center of the search frequency band is then the center of
# the longest gap
search_freq = (
longest_search_window[-1] - longest_search_window[0]
) / 2
search_freq = array_center(longest_search_window) - current_median
return search_freq
return config.default_search_freq
def main(datapath: str, plot: str) -> None:
def chirpdetection(datapath: str, plot: str, debug: str = 'false') -> None:
assert plot in [
"save",
@@ -560,7 +613,17 @@ def main(datapath: str, plot: str) -> None:
"false",
], "plot must be 'save', 'show' or 'false'"
assert debug in [
"false",
"electrode",
"fish",
], "debug must be 'false', 'electrode' or 'fish'"
if debug != "false":
assert plot == "show", "debug mode only runs when plot is 'show'"
# load raw file
print('datapath', datapath)
data = LoadData(datapath)
# load config file
@@ -589,16 +652,16 @@ def main(datapath: str, plot: str) -> None:
raw_time = np.arange(data.raw.shape[0]) / data.raw_rate
# good chirp times for data: 2022-06-02-10_00
window_start_index = (3 * 60 * 60 + 6 * 60 + 43.5 + 5) * data.raw_rate
window_duration_index = 60 * data.raw_rate
# window_start_index = (3 * 60 * 60 + 6 * 60 + 43.5) * data.raw_rate
# window_duration_index = 60 * data.raw_rate
# t0 = 0
# dt = data.raw.shape[0]
# window_start_seconds = (23495 + ((28336-23495)/3)) * data.raw_rate
# window_duration_seconds = (28336 - 23495) * data.raw_rate
# window_start_index = 0
# window_duration_index = data.raw.shape[0]
window_start_index = 0
window_duration_index = data.raw.shape[0]
# generate starting points of rolling window
window_start_indices = np.arange(
@@ -612,7 +675,7 @@ def main(datapath: str, plot: str) -> None:
multiwindow_chirps = []
multiwindow_ids = []
for st, window_start_index in enumerate(window_start_indices):
for st, window_start_index in enumerate(window_start_indices[3175:]):
logger.info(f"Processing window {st+1} of {len(window_start_indices)}")
@@ -651,14 +714,14 @@ def main(datapath: str, plot: str) -> None:
# approximate sampling rate to compute expected durations if there
# is data available for this time window for this fish id
track_samplerate = np.mean(1 / np.diff(data.time))
expected_duration = (
(window_start_seconds + window_duration_seconds)
- window_start_seconds
) * track_samplerate
# track_samplerate = np.mean(1 / np.diff(data.time))
# expected_duration = (
# (window_start_seconds + window_duration_seconds)
# - window_start_seconds
# ) * track_samplerate
# check if tracked data available in this window
if len(current_frequencies) < expected_duration / 2:
if len(current_frequencies) < 3:
logger.warning(
f"Track {track_id} has no data in window {st}, skipping."
)
@@ -750,11 +813,11 @@ def main(datapath: str, plot: str) -> None:
baseline_envelope = -baseline_envelope
baseline_envelope = envelope(
signal=baseline_envelope,
samplerate=data.raw_rate,
cutoff_frequency=config.baseline_envelope_envelope_cutoff,
)
# baseline_envelope = envelope(
# signal=baseline_envelope,
# samplerate=data.raw_rate,
# cutoff_frequency=config.baseline_envelope_envelope_cutoff,
# )
# compute the envelope of the search band. Peaks in the search
# band envelope correspond to troughs in the baseline envelope
@@ -788,25 +851,25 @@ def main(datapath: str, plot: str) -> None:
# compute the envelope of the signal to remove the oscillations
# around the peaks
baseline_frequency_samplerate = np.mean(
np.diff(baseline_frequency_time)
)
# baseline_frequency_samplerate = np.mean(
# np.diff(baseline_frequency_time)
# )
baseline_frequency_filtered = np.abs(
baseline_frequency - np.median(baseline_frequency)
)
baseline_frequency_filtered = highpass_filter(
signal=baseline_frequency_filtered,
samplerate=baseline_frequency_samplerate,
cutoff=config.baseline_frequency_highpass_cutoff,
)
# baseline_frequency_filtered = highpass_filter(
# signal=baseline_frequency_filtered,
# samplerate=baseline_frequency_samplerate,
# cutoff=config.baseline_frequency_highpass_cutoff,
# )
baseline_frequency_filtered = envelope(
signal=-baseline_frequency_filtered,
samplerate=baseline_frequency_samplerate,
cutoff_frequency=config.baseline_frequency_envelope_cutoff,
)
# baseline_frequency_filtered = envelope(
# signal=-baseline_frequency_filtered,
# samplerate=baseline_frequency_samplerate,
# cutoff_frequency=config.baseline_frequency_envelope_cutoff,
# )
# CUT OFF OVERLAP ---------------------------------------------
@@ -847,25 +910,25 @@ def main(datapath: str, plot: str) -> None:
# normalize all three feature arrays to the same range to make
# peak detection simpler
baseline_envelope = normalize([baseline_envelope])[0]
search_envelope = normalize([search_envelope])[0]
baseline_frequency_filtered = normalize(
[baseline_frequency_filtered]
)[0]
# baseline_envelope = minmaxnorm([baseline_envelope])[0]
# search_envelope = minmaxnorm([search_envelope])[0]
# baseline_frequency_filtered = minmaxnorm(
# [baseline_frequency_filtered]
# )[0]
# PEAK DETECTION ----------------------------------------------
# detect peaks baseline_enelope
baseline_peak_indices, _ = find_peaks(
baseline_envelope, prominence=config.prominence
baseline_envelope, prominence=config.baseline_prominence
)
# detect peaks search_envelope
search_peak_indices, _ = find_peaks(
search_envelope, prominence=config.prominence
search_envelope, prominence=config.search_prominence
)
# detect peaks inst_freq_filtered
frequency_peak_indices, _ = find_peaks(
baseline_frequency_filtered, prominence=config.prominence
baseline_frequency_filtered, prominence=config.frequency_prominence
)
# DETECT CHIRPS IN SEARCH WINDOW ------------------------------
@@ -890,7 +953,7 @@ def main(datapath: str, plot: str) -> None:
or len(frequency_peak_timestamps) == 0
)
if one_feature_empty:
if one_feature_empty and (debug == 'false'):
continue
# group peak across feature arrays but only if they
@@ -911,25 +974,23 @@ def main(datapath: str, plot: str) -> None:
# check it there are chirps detected after grouping, continue
# with the loop if not
if len(singleelectrode_chirps) == 0:
if (len(singleelectrode_chirps) == 0) and (debug == 'false'):
continue
# append chirps from this electrode to the multilectrode list
multielectrode_chirps.append(singleelectrode_chirps)
# only initialize the plotting buffer if chirps are detected
chirp_detected = (
(el == config.number_electrodes - 1)
& (len(singleelectrode_chirps) > 0)
& (plot in ["show", "save"])
)
chirp_detected = (el == (config.number_electrodes - 1)
& (plot in ["show", "save"])
)
if chirp_detected:
if chirp_detected or (debug != 'elecrode'):
logger.debug("Detected chirp, ititialize buffer ...")
# save data to Buffer
buffer = PlotBuffer(
buffer = ChirpPlotBuffer(
config=config,
t0=window_start_seconds,
dt=window_duration_seconds,
@@ -954,6 +1015,11 @@ def main(datapath: str, plot: str) -> None:
logger.debug("Buffer initialized!")
if debug == "electrode":
logger.info(f'Plotting electrode {el} ...')
buffer.plot_buffer(
chirps=singleelectrode_chirps, plot=plot)
logger.debug(
f"Processed all electrodes for fish {track_id} for this"
"window, sorting chirps ..."
@@ -962,7 +1028,7 @@ def main(datapath: str, plot: str) -> None:
# check if there are chirps detected in multiple electrodes and
# continue the loop if not
if len(multielectrode_chirps) == 0:
if (len(multielectrode_chirps) == 0) and (debug == 'false'):
continue
# validate multielectrode chirps, i.e. check if they are
@@ -987,9 +1053,15 @@ def main(datapath: str, plot: str) -> None:
# if chirps are detected and the plot flag is set, plot the
# chirps, otheswise try to delete the buffer if it exists
if len(multielectrode_chirps_validated) > 0:
if debug == "fish":
logger.info(f'Plotting fish {track_id} ...')
buffer.plot_buffer(multielectrode_chirps_validated, plot)
if ((len(multielectrode_chirps_validated) > 0) &
(plot in ["show", "save"]) & (debug == 'false')):
try:
buffer.plot_buffer(multielectrode_chirps_validated, plot)
del buffer
except NameError:
pass
else:
@@ -1049,4 +1121,4 @@ if __name__ == "__main__":
datapath = "../data/2022-06-02-10_00/"
# datapath = "/home/weygoldt/Data/uni/efishdata/2016-colombia/fishgrid/2016-04-09-22_25/"
# datapath = "/home/weygoldt/Data/uni/chirpdetection/GP2023_chirp_detection/data/mount_data/2020-03-13-10_00/"
main(datapath, plot="save")
chirpdetection(datapath, plot="save", debug="false")

View File

@@ -1,47 +1,41 @@
# directory setup
dataroot: "../data/"
outputdir: "../output/"
# Path setup ------------------------------------------------------------------
# Duration and overlap of the analysis window in seconds
window: 10
overlap: 1
edge: 0.25
dataroot: "../data/" # path to data
outputdir: "../output/" # path to save plots to
# Number of electrodes to go over
number_electrodes: 3
minimum_electrodes: 2
# Rolling window parameters ---------------------------------------------------
# Search window bandwidth and minimal baseline bandwidth
minimal_bandwidth: 20
window: 5 # rolling window length in seconds
overlap: 1 # window overlap in seconds
edge: 0.25 # window edge cufoffs to mitigate filter edge effects
# Instantaneous frequency smoothing usint a gaussian kernel of this width
baseline_frequency_smoothing: 5
# Electrode iteration parameters ----------------------------------------------
# Baseline processing parameters
baseline_envelope_cutoff: 25
baseline_envelope_bandpass_lowf: 4
baseline_envelope_bandpass_highf: 100
baseline_envelope_envelope_cutoff: 4
number_electrodes: 2 # number of electrodes to go over
minimum_electrodes: 1 # mimumun number of electrodes a chirp must be on
# search envelope processing parameters
search_envelope_cutoff: 5
# Feature extraction parameters -----------------------------------------------
# Instantaneous frequency bandpass filter cutoff frequencies
baseline_frequency_highpass_cutoff: 0.000005
baseline_frequency_envelope_cutoff: 0.000005
search_df_lower: 20 # start searching this far above the baseline
search_df_upper: 100 # stop searching this far above the baseline
search_res: 1 # search window resolution
default_search_freq: 60 # search here if no need for a search frequency
minimal_bandwidth: 10 # minimal bandpass filter width for baseline
search_bandwidth: 10 # minimal bandpass filter width for search frequency
baseline_frequency_smoothing: 10 # instantaneous frequency smoothing
# peak detecion parameters
prominence: 0.005
# Feature processing parameters -----------------------------------------------
# search freq parameter
search_df_lower: 20
search_df_upper: 100
search_res: 1
search_bandwidth: 10
default_search_freq: 50
baseline_envelope_cutoff: 25 # envelope estimation cutoff
baseline_envelope_bandpass_lowf: 2 # envelope badpass lower cutoff
baseline_envelope_bandpass_highf: 100 # envelope bandbass higher cutoff
search_envelope_cutoff: 10 # search envelope estimation cufoff
# Peak detecion parameters ----------------------------------------------------
baseline_prominence: 0.00005 # peak prominence threshold for baseline envelope
search_prominence: 0.000004 # peak prominence threshold for search envelope
frequency_prominence: 2 # peak prominence threshold for baseline freq
# Classify events as chirps if they are less than this time apart
chirp_window_threshold: 0.05
chirp_window_threshold: 0.02

522
code/eventchirpsplots.py Normal file
View File

@@ -0,0 +1,522 @@
import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from tqdm import tqdm
from IPython import embed
from pandas import read_csv
from modules.logger import makeLogger
from modules.plotstyle import PlotStyle
from modules.datahandling import causal_kde1d, acausal_kde1d
logger = makeLogger(__name__)
ps = PlotStyle()
class Behavior:
"""Load behavior data from csv file as class attributes
Attributes
----------
behavior: 0: chasing onset, 1: chasing offset, 2: physical contact
behavior_type:
behavioral_category:
comment_start:
comment_stop:
dataframe: pandas dataframe with all the data
duration_s:
media_file:
observation_date:
observation_id:
start_s: start time of the event in seconds
stop_s: stop time of the event in seconds
total_length:
"""
def __init__(self, folder_path: str) -> None:
print(f'{folder_path}')
LED_on_time_BORIS = np.load(os.path.join(folder_path, 'LED_on_time.npy'), allow_pickle=True)
self.time = np.load(os.path.join(folder_path, "times.npy"), allow_pickle=True)
csv_filename = [f for f in os.listdir(folder_path) if f.endswith('.csv')][0] # check if there are more than one csv file
self.dataframe = read_csv(os.path.join(folder_path, csv_filename))
self.chirps = np.load(os.path.join(folder_path, 'chirps.npy'), allow_pickle=True)
self.chirps_ids = np.load(os.path.join(folder_path, 'chirp_ids.npy'), allow_pickle=True)
for k, key in enumerate(self.dataframe.keys()):
key = key.lower()
if ' ' in key:
key = key.replace(' ', '_')
if '(' in key:
key = key.replace('(', '')
key = key.replace(')', '')
setattr(self, key, np.array(self.dataframe[self.dataframe.keys()[k]]))
last_LED_t_BORIS = LED_on_time_BORIS[-1]
real_time_range = self.time[-1] - self.time[0]
factor = 1.034141
shift = last_LED_t_BORIS - real_time_range * factor
self.start_s = (self.start_s - shift) / factor
self.stop_s = (self.stop_s - shift) / factor
"""
1 - chasing onset
2 - chasing offset
3 - physical contact event
temporal encpding needs to be corrected ... not exactly 25FPS.
### correspinding python code ###
factor = 1.034141
LED_on_time_BORIS = np.load(os.path.join(folder_path, 'LED_on_time.npy'), allow_pickle=True)
last_LED_t_BORIS = LED_on_time_BORIS[-1]
real_time_range = times[-1] - times[0]
shift = last_LED_t_BORIS - real_time_range * factor
data = pd.read_csv(os.path.join(folder_path, file[1:-7] + '.csv'))
boris_times = data['Start (s)']
data_times = []
for Cevent_t in boris_times:
Cevent_boris_times = (Cevent_t - shift) / factor
data_times.append(Cevent_boris_times)
data_times = np.array(data_times)
behavior = data['Behavior']
"""
def correct_chasing_events(
category: np.ndarray,
timestamps: np.ndarray
) -> tuple[np.ndarray, np.ndarray]:
onset_ids = np.arange(
len(category))[category == 0]
offset_ids = np.arange(
len(category))[category == 1]
wrong_bh = np.arange(len(category))[category!=2][:-1][np.diff(category[category!=2])==0]
if onset_ids[0] > offset_ids[0]:
offset_ids = np.delete(offset_ids, 0)
help_index = offset_ids[0]
wrong_bh = np.append(wrong_bh[help_index])
category = np.delete(category, wrong_bh)
timestamps = np.delete(timestamps, wrong_bh)
# Check whether on- or offset is longer and calculate length difference
if len(onset_ids) > len(offset_ids):
len_diff = len(onset_ids) - len(offset_ids)
logger.info(f'Onsets are greater than offsets by {len_diff}')
elif len(onset_ids) < len(offset_ids):
len_diff = len(offset_ids) - len(onset_ids)
logger.info(f'Offsets are greater than onsets by {len_diff}')
elif len(onset_ids) == len(offset_ids):
logger.info('Chasing events are equal')
return category, timestamps
def event_triggered_chirps(
event: np.ndarray,
chirps:np.ndarray,
time_before_event: int,
time_after_event: int,
dt: float,
width: float,
)-> tuple[np.ndarray, np.ndarray, np.ndarray]:
event_chirps = [] # chirps that are in specified window around event
centered_chirps = [] # timestamps of chirps around event centered on the event timepoint
for event_timestamp in event:
start = event_timestamp - time_before_event
stop = event_timestamp + time_after_event
chirps_around_event = [c for c in chirps if (c >= start) & (c <= stop)]
event_chirps.append(chirps_around_event)
if len(chirps_around_event) == 0:
continue
else:
centered_chirps.append(chirps_around_event - event_timestamp)
time = np.arange(-time_before_event, time_after_event, dt)
# Kernel density estimation with some if's
if len(centered_chirps) == 0:
centered_chirps = np.array([])
centered_chirps_convolved = np.zeros(len(time))
else:
centered_chirps = np.concatenate(centered_chirps, axis=0) # convert list of arrays to one array for plotting
centered_chirps_convolved = (acausal_kde1d(centered_chirps, time, width)) / len(event)
return event_chirps, centered_chirps, centered_chirps_convolved
def main(datapath: str):
foldernames = [datapath + x + '/' for x in os.listdir(datapath) if os.path.isdir(datapath + x)]
nrecording_chirps = []
nrecording_chirps_fish_ids = []
nrecording_chasing_onsets = []
nrecording_chasing_offsets = []
nrecording_physicals = []
# Iterate over all recordings and save chirp- and event-timestamps
for folder in foldernames:
# exclude folder with empty LED_on_time.npy
if folder == '../data/mount_data/2020-05-12-10_00/':
continue
bh = Behavior(folder)
# Chirps are already sorted
category = bh.behavior
timestamps = bh.start_s
chirps = bh.chirps
nrecording_chirps.append(chirps)
chirps_fish_ids = bh.chirps_ids
nrecording_chirps_fish_ids.append(chirps_fish_ids)
fish_ids = np.unique(chirps_fish_ids)
# Correct for doubles in chasing on- and offsets to get the right on-/offset pairs
# Get rid of tracking faults (two onsets or two offsets after another)
category, timestamps = correct_chasing_events(category, timestamps)
# Split categories
chasing_onsets = timestamps[category == 0]
nrecording_chasing_onsets.append(chasing_onsets)
chasing_offsets = timestamps[category == 1]
nrecording_chasing_offsets.append(chasing_offsets)
physical_contacts = timestamps[category == 2]
nrecording_physicals.append(physical_contacts)
# Define time window for chirps around event analysis
time_before_event = 30
time_after_event = 60
dt = 0.01
width = 1.5 # width of kernel for all recordings, currently gaussian kernel
recording_width = 2 # width of kernel for each recording
time = np.arange(-time_before_event, time_after_event, dt)
##### Chirps around events, all fish, all recordings #####
# Centered chirps per event type
nrecording_centered_onset_chirps = []
nrecording_centered_offset_chirps = []
nrecording_centered_physical_chirps = []
# Bootstrapped chirps per recording and per event: 27[1000[n]] 27 recs, 1000 shuffles, n chirps
nrecording_shuffled_convolved_onset_chirps = []
nrecording_shuffled_convolved_offset_chirps = []
nrecording_shuffled_convolved_physical_chirps = []
nbootstrapping = 10
for i in range(len(nrecording_chirps)):
chirps = nrecording_chirps[i]
chasing_onsets = nrecording_chasing_onsets[i]
chasing_offsets = nrecording_chasing_offsets[i]
physical_contacts = nrecording_physicals[i]
# Chirps around chasing onsets
_, centered_chasing_onset_chirps, cc_chasing_onset_chirps = event_triggered_chirps(chasing_onsets, chirps, time_before_event, time_after_event, dt, recording_width)
# Chirps around chasing offsets
_, centered_chasing_offset_chirps, cc_chasing_offset_chirps = event_triggered_chirps(chasing_offsets, chirps, time_before_event, time_after_event, dt, recording_width)
# Chirps around physical contacts
_, centered_physical_chirps, cc_physical_chirps = event_triggered_chirps(physical_contacts, chirps, time_before_event, time_after_event, dt, recording_width)
nrecording_centered_onset_chirps.append(centered_chasing_onset_chirps)
nrecording_centered_offset_chirps.append(centered_chasing_offset_chirps)
nrecording_centered_physical_chirps.append(centered_physical_chirps)
## Shuffled chirps ##
nshuffled_onset_chirps = []
nshuffled_offset_chirps = []
nshuffled_physical_chirps = []
for j in tqdm(range(nbootstrapping)):
# Calculate interchirp intervals; add first chirp timestamp in beginning to get equal lengths
interchirp_intervals = np.append(np.array([chirps[0]]), np.diff(chirps))
np.random.shuffle(interchirp_intervals)
shuffled_chirps = np.cumsum(interchirp_intervals)
# Shuffled chasing onset chirps
_, _, cc_shuffled_onset_chirps = event_triggered_chirps(chasing_onsets, shuffled_chirps, time_before_event, time_after_event, dt, recording_width)
nshuffled_onset_chirps.append(cc_shuffled_onset_chirps)
# Shuffled chasing offset chirps
_, _, cc_shuffled_offset_chirps = event_triggered_chirps(chasing_offsets, shuffled_chirps, time_before_event, time_after_event, dt, recording_width)
nshuffled_offset_chirps.append(cc_shuffled_offset_chirps)
# Shuffled physical contact chirps
_, _, cc_shuffled_physical_chirps = event_triggered_chirps(physical_contacts, shuffled_chirps, time_before_event, time_after_event, dt, recording_width)
nshuffled_physical_chirps.append(cc_shuffled_physical_chirps)
rec_shuffled_q5_onset, rec_shuffled_median_onset, rec_shuffled_q95_onset = np.percentile(
nshuffled_onset_chirps, (5, 50, 95), axis=0)
rec_shuffled_q5_offset, rec_shuffled_median_offset, rec_shuffled_q95_offset = np.percentile(
nshuffled_offset_chirps, (5, 50, 95), axis=0)
rec_shuffled_q5_physical, rec_shuffled_median_physical, rec_shuffled_q95_physical = np.percentile(
nshuffled_physical_chirps, (5, 50, 95), axis=0)
#### Recording plots ####
fig, ax = plt.subplots(1, 3, figsize=(28*ps.cm, 16*ps.cm, ), constrained_layout=True, sharey='all')
ax[0].set_xlabel('Time[s]')
# Plot chasing onsets
ax[0].set_ylabel('Chirp rate [Hz]')
ax[0].plot(time, cc_chasing_onset_chirps, color=ps.yellow, zorder=2)
ax0 = ax[0].twinx()
ax0.eventplot(centered_chasing_onset_chirps, linelengths=0.2, colors=ps.gray, alpha=0.25, zorder=1)
ax0.vlines(0, 0, 1.5, ps.white, 'dashed')
ax[0].set_zorder(ax0.get_zorder()+1)
ax[0].patch.set_visible(False)
ax0.set_yticklabels([])
ax0.set_yticks([])
ax[0].fill_between(time, rec_shuffled_q5_onset, rec_shuffled_q95_onset, color=ps.gray, alpha=0.5)
ax[0].plot(time, rec_shuffled_median_onset, color=ps.black)
# Plot chasing offets
ax[1].set_xlabel('Time[s]')
ax[1].plot(time, cc_chasing_offset_chirps, color=ps.orange, zorder=2)
ax1 = ax[1].twinx()
ax1.eventplot(centered_chasing_offset_chirps, linelengths=0.2, colors=ps.gray, alpha=0.25, zorder=1)
ax1.vlines(0, 0, 1.5, ps.white, 'dashed')
ax[1].set_zorder(ax1.get_zorder()+1)
ax[1].patch.set_visible(False)
ax1.set_yticklabels([])
ax1.set_yticks([])
ax[1].fill_between(time, rec_shuffled_q5_offset, rec_shuffled_q95_offset, color=ps.gray, alpha=0.5)
ax[1].plot(time, rec_shuffled_median_offset, color=ps.black)
# Plot physical contacts
ax[2].set_xlabel('Time[s]')
ax[2].plot(time, cc_physical_chirps, color=ps.maroon, zorder=2)
ax2 = ax[2].twinx()
ax2.eventplot(centered_physical_chirps, linelengths=0.2, colors=ps.gray, alpha=0.25, zorder=1)
ax2.vlines(0, 0, 1.5, ps.white, 'dashed')
ax[2].set_zorder(ax2.get_zorder()+1)
ax[2].patch.set_visible(False)
ax2.set_yticklabels([])
ax2.set_yticks([])
ax[2].fill_between(time, rec_shuffled_q5_physical, rec_shuffled_q95_physical, color=ps.gray, alpha=0.5)
ax[2].plot(time, rec_shuffled_median_physical, ps.black)
fig.suptitle(f'Recording: {i}')
plt.show()
# plt.close()
nrecording_shuffled_convolved_onset_chirps.append(nshuffled_onset_chirps)
nrecording_shuffled_convolved_offset_chirps.append(nshuffled_offset_chirps)
nrecording_shuffled_convolved_physical_chirps.append(nshuffled_physical_chirps)
# vstack um 1. Dim zu cutten
nrecording_shuffled_convolved_onset_chirps = np.vstack(nrecording_shuffled_convolved_onset_chirps)
nrecording_shuffled_convolved_offset_chirps = np.vstack(nrecording_shuffled_convolved_offset_chirps)
nrecording_shuffled_convolved_physical_chirps = np.vstack(nrecording_shuffled_convolved_physical_chirps)
shuffled_q5_onset, shuffled_median_onset, shuffled_q95_onset = np.percentile(
nrecording_shuffled_convolved_onset_chirps, (5, 50, 95), axis=0)
shuffled_q5_offset, shuffled_median_offset, shuffled_q95_offset = np.percentile(
nrecording_shuffled_convolved_offset_chirps, (5, 50, 95), axis=0)
shuffled_q5_physical, shuffled_median_physical, shuffled_q95_physical = np.percentile(
nrecording_shuffled_convolved_physical_chirps, (5, 50, 95), axis=0)
# Flatten all chirps
all_chirps = np.concatenate(nrecording_chirps).ravel() # not centered
# Flatten event timestamps
all_onsets = np.concatenate(nrecording_chasing_onsets).ravel() # not centered
all_offsets = np.concatenate(nrecording_chasing_offsets).ravel() # not centered
all_physicals = np.concatenate(nrecording_physicals).ravel() # not centered
# Flatten all chirps around events
all_onset_chirps = np.concatenate(nrecording_centered_onset_chirps).ravel() # centered
all_offset_chirps = np.concatenate(nrecording_centered_offset_chirps).ravel() # centered
all_physical_chirps = np.concatenate(nrecording_centered_physical_chirps).ravel() # centered
# Convolute all chirps
# Divide by total number of each event over all recordings
all_onset_chirps_convolved = (acausal_kde1d(all_onset_chirps, time, width)) / len(all_onsets)
all_offset_chirps_convolved = (acausal_kde1d(all_offset_chirps, time, width)) / len(all_offsets)
all_physical_chirps_convolved = (acausal_kde1d(all_physical_chirps, time, width)) / len(all_physicals)
# Plot all events with all shuffled
fig, ax = plt.subplots(1, 3, figsize=(28*ps.cm, 16*ps.cm, ), constrained_layout=True, sharey='all')
# offsets = np.arange(1,28,1)
ax[0].set_xlabel('Time[s]')
# Plot chasing onsets
ax[0].set_ylabel('Chirp rate [Hz]')
ax[0].plot(time, all_onset_chirps_convolved, color=ps.yellow, zorder=2)
ax0 = ax[0].twinx()
nrecording_centered_onset_chirps = np.asarray(nrecording_centered_onset_chirps, dtype=object)
ax0.eventplot(np.array(nrecording_centered_onset_chirps), linelengths=0.5, colors=ps.gray, alpha=0.25, zorder=1)
ax0.vlines(0, 0, 1.5, ps.white, 'dashed')
ax[0].set_zorder(ax0.get_zorder()+1)
ax[0].patch.set_visible(False)
ax0.set_yticklabels([])
ax0.set_yticks([])
ax[0].fill_between(time, shuffled_q5_onset, shuffled_q95_onset, color=ps.gray, alpha=0.5)
ax[0].plot(time, shuffled_median_onset, color=ps.black)
# Plot chasing offets
ax[1].set_xlabel('Time[s]')
ax[1].plot(time, all_offset_chirps_convolved, color=ps.orange, zorder=2)
ax1 = ax[1].twinx()
nrecording_centered_offset_chirps = np.asarray(nrecording_centered_offset_chirps, dtype=object)
ax1.eventplot(np.array(nrecording_centered_offset_chirps), linelengths=0.5, colors=ps.gray, alpha=0.25, zorder=1)
ax1.vlines(0, 0, 1.5, ps.white, 'dashed')
ax[1].set_zorder(ax1.get_zorder()+1)
ax[1].patch.set_visible(False)
ax1.set_yticklabels([])
ax1.set_yticks([])
ax[1].fill_between(time, shuffled_q5_offset, shuffled_q95_offset, color=ps.gray, alpha=0.5)
ax[1].plot(time, shuffled_median_offset, color=ps.black)
# Plot physical contacts
ax[2].set_xlabel('Time[s]')
ax[2].plot(time, all_physical_chirps_convolved, color=ps.maroon, zorder=2)
ax2 = ax[2].twinx()
nrecording_centered_physical_chirps = np.asarray(nrecording_centered_physical_chirps, dtype=object)
ax2.eventplot(np.array(nrecording_centered_physical_chirps), linelengths=0.5, colors=ps.gray, alpha=0.25, zorder=1)
ax2.vlines(0, 0, 1.5, ps.white, 'dashed')
ax[2].set_zorder(ax2.get_zorder()+1)
ax[2].patch.set_visible(False)
ax2.set_yticklabels([])
ax2.set_yticks([])
ax[2].fill_between(time, shuffled_q5_physical, shuffled_q95_physical, color=ps.gray, alpha=0.5)
ax[2].plot(time, shuffled_median_physical, ps.black)
fig.suptitle('All recordings')
plt.show()
# plt.close()
embed()
# chasing_durations = []
# # Calculate chasing duration to evaluate a nice time window for kernel density estimation
# for onset, offset in zip(chasing_onsets, chasing_offsets):
# duration = offset - onset
# chasing_durations.append(duration)
# fig, ax = plt.subplots()
# ax.boxplot(chasing_durations)
# plt.show()
# plt.close()
# # Associate chirps to individual fish
# fish1 = chirps[chirps_fish_ids == fish_ids[0]]
# fish2 = chirps[chirps_fish_ids == fish_ids[1]]
# fish = [len(fish1), len(fish2)]
# Convolution over all recordings
# Rasterplot for each recording
# #### Chirps around events, winner VS loser, one recording ####
# # Load file with fish ids and winner/loser info
# meta = pd.read_csv('../data/mount_data/order_meta.csv')
# current_recording = meta[meta.index == 43]
# fish1 = current_recording['rec_id1'].values
# fish2 = current_recording['rec_id2'].values
# # Implement check if fish_ids from meta and chirp detection are the same???
# winner = current_recording['winner'].values
# if winner == fish1:
# loser = fish2
# elif winner == fish2:
# loser = fish1
# winner_chirps = chirps[chirps_fish_ids == winner]
# loser_chirps = chirps[chirps_fish_ids == loser]
# # Event triggered winner chirps
# _, winner_centered_onset, winner_cc_onset = event_triggered_chirps(chasing_onsets, winner_chirps, time_before_event, time_after_event, dt, width)
# _, winner_centered_offset, winner_cc_offset = event_triggered_chirps(chasing_offsets, winner_chirps, time_before_event, time_after_event, dt, width)
# _, winner_centered_physical, winner_cc_physical = event_triggered_chirps(physical_contacts, winner_chirps, time_before_event, time_after_event, dt, width)
# # Event triggered loser chirps
# _, loser_centered_onset, loser_cc_onset = event_triggered_chirps(chasing_onsets, loser_chirps, time_before_event, time_after_event, dt, width)
# _, loser_centered_offset, loser_cc_offset = event_triggered_chirps(chasing_offsets, loser_chirps, time_before_event, time_after_event, dt, width)
# _, loser_centered_physical, loser_cc_physical = event_triggered_chirps(physical_contacts, loser_chirps, time_before_event, time_after_event, dt, width)
# ########## Winner VS Loser plot ##########
# fig, ax = plt.subplots(2, 3, figsize=(50 / 2.54, 15 / 2.54), constrained_layout=True, sharey='row')
# offset = [1.35]
# ax[1][0].set_xlabel('Time[s]')
# ax[1][1].set_xlabel('Time[s]')
# ax[1][2].set_xlabel('Time[s]')
# # Plot winner chasing onsets
# ax[0][0].set_ylabel('Chirp rate [Hz]')
# ax[0][0].plot(time, winner_cc_onset, color='tab:blue', zorder=100)
# ax0 = ax[0][0].twinx()
# ax0.eventplot(np.array([winner_centered_onset]), lineoffsets=offset, linelengths=0.1, colors=['tab:green'], alpha=0.25, zorder=-100)
# ax0.set_ylabel('Event')
# ax0.vlines(0, 0, 1.5, 'tab:grey', 'dashed')
# ax[0][0].set_zorder(ax0.get_zorder()+1)
# ax[0][0].patch.set_visible(False)
# ax0.set_yticklabels([])
# ax0.set_yticks([])
# # Plot winner chasing offets
# ax[0][1].plot(time, winner_cc_offset, color='tab:blue', zorder=100)
# ax1 = ax[0][1].twinx()
# ax1.eventplot(np.array([winner_centered_offset]), lineoffsets=offset, linelengths=0.1, colors=['tab:purple'], alpha=0.25, zorder=-100)
# ax1.vlines(0, 0, 1.5, 'tab:grey', 'dashed')
# ax[0][1].set_zorder(ax1.get_zorder()+1)
# ax[0][1].patch.set_visible(False)
# ax1.set_yticklabels([])
# ax1.set_yticks([])
# # Plot winner physical contacts
# ax[0][2].plot(time, winner_cc_physical, color='tab:blue', zorder=100)
# ax2 = ax[0][2].twinx()
# ax2.eventplot(np.array([winner_centered_physical]), lineoffsets=offset, linelengths=0.1, colors=['tab:red'], alpha=0.25, zorder=-100)
# ax2.vlines(0, 0, 1.5, 'tab:grey', 'dashed')
# ax[0][2].set_zorder(ax2.get_zorder()+1)
# ax[0][2].patch.set_visible(False)
# ax2.set_yticklabels([])
# ax2.set_yticks([])
# # Plot loser chasing onsets
# ax[1][0].set_ylabel('Chirp rate [Hz]')
# ax[1][0].plot(time, loser_cc_onset, color='tab:blue', zorder=100)
# ax3 = ax[1][0].twinx()
# ax3.eventplot(np.array([loser_centered_onset]), lineoffsets=offset, linelengths=0.1, colors=['tab:green'], alpha=0.25, zorder=-100)
# ax3.vlines(0, 0, 1.5, 'tab:grey', 'dashed')
# ax[1][0].set_zorder(ax3.get_zorder()+1)
# ax[1][0].patch.set_visible(False)
# ax3.set_yticklabels([])
# ax3.set_yticks([])
# # Plot loser chasing offsets
# ax[1][1].plot(time, loser_cc_offset, color='tab:blue', zorder=100)
# ax4 = ax[1][1].twinx()
# ax4.eventplot(np.array([loser_centered_offset]), lineoffsets=offset, linelengths=0.1, colors=['tab:purple'], alpha=0.25, zorder=-100)
# ax4.vlines(0, 0, 1.5, 'tab:grey', 'dashed')
# ax[1][1].set_zorder(ax4.get_zorder()+1)
# ax[1][1].patch.set_visible(False)
# ax4.set_yticklabels([])
# ax4.set_yticks([])
# # Plot loser physical contacts
# ax[1][2].plot(time, loser_cc_physical, color='tab:blue', zorder=100)
# ax5 = ax[1][2].twinx()
# ax5.eventplot(np.array([loser_centered_physical]), lineoffsets=offset, linelengths=0.1, colors=['tab:red'], alpha=0.25, zorder=-100)
# ax5.vlines(0, 0, 1.5, 'tab:grey', 'dashed')
# ax[1][2].set_zorder(ax5.get_zorder()+1)
# ax[1][2].patch.set_visible(False)
# ax5.set_yticklabels([])
# ax5.set_yticks([])
# plt.show()
# plt.close()
# for i in range(len(fish_ids)):
# fish = fish_ids[i]
# chirps_temp = chirps[chirps_fish_ids == fish]
# print(fish)
#### Chirps around events, only losers, one recording ####
if __name__ == '__main__':
# Path to the data
datapath = '../data/mount_data/'
main(datapath)

51
code/extract_chirps.py Normal file
View File

@@ -0,0 +1,51 @@
import os
import pandas as pd
import numpy as np
from chirpdetection import chirpdetection
from IPython import embed
# check rec ../data/mount_data/2020-03-25-10_00/ starting at 3175
def main(datapaths):
for path in datapaths:
chirpdetection(path, plot='show')
if __name__ == '__main__':
dataroot = '../data/mount_data/'
datasets = sorted([name for name in os.listdir(dataroot) if os.path.isdir(
os.path.join(dataroot, name))])
valid_datasets = []
for dataset in datasets:
path = os.path.join(dataroot, dataset)
csv_name = '-'.join(dataset.split('-')[:3]) + '.csv'
if os.path.exists(os.path.join(path, csv_name)) is False:
continue
if os.path.exists(os.path.join(path, 'ident_v.npy')) is False:
continue
ident = np.load(os.path.join(path, 'ident_v.npy'))
number_of_fish = len(np.unique(ident[~np.isnan(ident)]))
if number_of_fish != 2:
continue
valid_datasets.append(dataset)
datapaths = [os.path.join(dataroot, dataset) +
'/' for dataset in valid_datasets]
recs = pd.DataFrame(columns=['recording'], data=valid_datasets)
recs.to_csv('../recs.csv', index=False)
datapaths = ['../data/mount_data/2020-03-25-10_00/']
main(datapaths)
# window 1524 + 244 in dataset index 4 is nice example

35
code/get_behaviour.py Normal file
View File

@@ -0,0 +1,35 @@
import os
from paramiko import SSHClient
from scp import SCPClient
from IPython import embed
from pandas import read_csv
ssh = SSHClient()
ssh.load_system_host_keys()
ssh.connect(hostname='kraken',
username='efish',
password='fwNix4U',
)
# SCPCLient takes a paramiko transport as its only argument
scp = SCPClient(ssh.get_transport())
data = read_csv('../recs.csv')
foldernames = data['recording'].values
directory = f'/Users/acfw/Documents/uni_tuebingen/chirpdetection/GP2023_chirp_detection/data/mount_data/'
for foldername in foldernames:
if not os.path.exists(directory+foldername):
os.makedirs(directory+foldername)
files = [('-').join(foldername.split('-')[:3])+'.csv','chirp_ids.npy', 'chirps.npy', 'fund_v.npy', 'ident_v.npy', 'idx_v.npy', 'times.npy', 'spec.npy', 'LED_on_time.npy', 'sign_v.npy']
for f in files:
scp.get(f'/home/efish/behavior/2019_tube_competition/{foldername}/{f}',
directory+foldername)
scp.close()

View File

@@ -0,0 +1,99 @@
import numpy as np
import os
import numpy as np
from IPython import embed
from pandas import read_csv
from modules.logger import makeLogger
logger = makeLogger(__name__)
class Behavior:
"""Load behavior data from csv file as class attributes
Attributes
----------
behavior: 0: chasing onset, 1: chasing offset, 2: physical contact
behavior_type:
behavioral_category:
comment_start:
comment_stop:
dataframe: pandas dataframe with all the data
duration_s:
media_file:
observation_date:
observation_id:
start_s: start time of the event in seconds
stop_s: stop time of the event in seconds
total_length:
"""
def __init__(self, folder_path: str) -> None:
LED_on_time_BORIS = np.load(os.path.join(folder_path, 'LED_on_time.npy'), allow_pickle=True)
csv_filename = [f for f in os.listdir(folder_path) if f.endswith('.csv')][0]
logger.info(f'CSV file: {csv_filename}')
self.dataframe = read_csv(os.path.join(folder_path, csv_filename))
self.chirps = np.load(os.path.join(folder_path, 'chirps.npy'), allow_pickle=True)
self.chirps_ids = np.load(os.path.join(folder_path, 'chirp_ids.npy'), allow_pickle=True)
self.ident = np.load(os.path.join(folder_path, 'ident_v.npy'), allow_pickle=True)
self.idx = np.load(os.path.join(folder_path, 'idx_v.npy'), allow_pickle=True)
self.freq = np.load(os.path.join(folder_path, 'fund_v.npy'), allow_pickle=True)
self.time = np.load(os.path.join(folder_path, "times.npy"), allow_pickle=True)
self.spec = np.load(os.path.join(folder_path, "spec.npy"), allow_pickle=True)
for k, key in enumerate(self.dataframe.keys()):
key = key.lower()
if ' ' in key:
key = key.replace(' ', '_')
if '(' in key:
key = key.replace('(', '')
key = key.replace(')', '')
setattr(self, key, np.array(self.dataframe[self.dataframe.keys()[k]]))
last_LED_t_BORIS = LED_on_time_BORIS[-1]
real_time_range = self.time[-1] - self.time[0]
factor = 1.034141
shift = last_LED_t_BORIS - real_time_range * factor
self.start_s = (self.start_s - shift) / factor
self.stop_s = (self.stop_s - shift) / factor
def correct_chasing_events(
category: np.ndarray,
timestamps: np.ndarray
) -> tuple[np.ndarray, np.ndarray]:
onset_ids = np.arange(
len(category))[category == 0]
offset_ids = np.arange(
len(category))[category == 1]
woring_bh = np.arange(len(category))[category!=2][:-1][np.diff(category[category!=2])==0]
if onset_ids[0] > offset_ids[0]:
offset_ids = np.delete(offset_ids, 0)
help_index = offset_ids[0]
woring_bh = np.append(woring_bh, help_index)
category = np.delete(category, woring_bh)
timestamps = np.delete(timestamps, woring_bh)
# Check whether on- or offset is longer and calculate length difference
if len(onset_ids) > len(offset_ids):
len_diff = len(onset_ids) - len(offset_ids)
logger.info(f'Onsets are greater than offsets by {len_diff}')
elif len(onset_ids) < len(offset_ids):
len_diff = len(offset_ids) - len(onset_ids)
logger.info(f'Offsets are greater than onsets by {len_diff}')
elif len(onset_ids) == len(offset_ids):
logger.info('Chasing events are equal')
return category, timestamps

View File

@@ -1,9 +1,10 @@
import numpy as np
from typing import List, Any
from scipy.ndimage import gaussian_filter1d
from scipy.stats import gamma, norm
def norm(data):
def minmaxnorm(data):
"""
Normalize data to [0, 1]
@@ -18,7 +19,7 @@ def norm(data):
Normalized data.
"""
return (2*((data - np.min(data)) / (np.max(data) - np.min(data)))) - 1
return (data - np.min(data)) / (np.max(data) - np.min(data))
def instantaneous_frequency(
@@ -167,6 +168,9 @@ def group_timestamps(
]
timestamps.sort()
if len(timestamps) == 0:
return []
groups = []
current_group = [timestamps[0]]
@@ -209,6 +213,117 @@ def flatten(list: List[List[Any]]) -> List:
return [item for sublist in list for item in sublist]
def causal_kde1d(spikes, time, width, shape=2):
"""
causalkde computes a kernel density estimate using a causal kernel (i.e. exponential or gamma distribution).
A shape of 1 turns the gamma distribution into an exponential.
Parameters
----------
spikes : array-like
spike times
time : array-like
sampling time
width : float
kernel width
shape : int, optional
shape of gamma distribution, by default 1
Returns
-------
rate : array-like
instantaneous firing rate
"""
# compute dt
dt = time[1] - time[0]
# time on which to compute kernel:
tmax = 10 * width
# kernel not wider than time
if 2 * tmax > time[-1] - time[0]:
tmax = 0.5 * (time[-1] - time[0])
# kernel time
ktime = np.arange(-tmax, tmax, dt)
# gamma kernel centered in ktime:
kernel = gamma.pdf(
x=ktime,
a=shape,
loc=0,
scale=width,
)
# indices of spikes in time array:
indices = np.asarray((spikes - time[0]) / dt, dtype=int)
# binary spike train:
brate = np.zeros(len(time))
brate[indices[(indices >= 0) & (indices < len(time))]] = 1.0
# convolution with kernel:
rate = np.convolve(brate, kernel, mode="same")
return rate
def acausal_kde1d(spikes, time, width):
"""
causalkde computes a kernel density estimate using a causal kernel (i.e. exponential or gamma distribution).
A shape of 1 turns the gamma distribution into an exponential.
Parameters
----------
spikes : array-like
spike times
time : array-like
sampling time
width : float
kernel width
shape : int, optional
shape of gamma distribution, by default 1
Returns
-------
rate : array-like
instantaneous firing rate
"""
# compute dt
dt = time[1] - time[0]
# time on which to compute kernel:
tmax = 10 * width
# kernel not wider than time
if 2 * tmax > time[-1] - time[0]:
tmax = 0.5 * (time[-1] - time[0])
# kernel time
ktime = np.arange(-tmax, tmax, dt)
# gamma kernel centered in ktime:
kernel = norm.pdf(
x=ktime,
loc=0,
scale=width,
)
# indices of spikes in time array:
indices = np.asarray((spikes - time[0]) / dt, dtype=int)
# binary spike train:
brate = np.zeros(len(time))
brate[indices[(indices >= 0) & (indices < len(time))]] = 1.0
# convolution with kernel:
rate = np.convolve(brate, kernel, mode="same")
return rate
if __name__ == "__main__":
timestamps = [

View File

@@ -3,6 +3,7 @@ import os
import yaml
import numpy as np
from thunderfish.dataloader import DataLoader
import matplotlib.pyplot as plt
class ConfLoader:

View File

@@ -23,16 +23,16 @@ def PlotStyle() -> None:
sky = "#89dceb"
teal = "#94e2d5"
green = "#a6e3a1"
yellow = "#f9e2af"
orange = "#fab387"
maroon = "#eba0ac"
red = "#f38ba8"
purple = "#cba6f7"
pink = "#f5c2e7"
yellow = "#f9d67f"
orange = "#faa472"
maroon = "#eb8486"
red = "#f37588"
purple = "#d89bf7"
pink = "#f59edb"
lavender = "#b4befe"
gblue1 = "#8cb8ff"
gblue2 = "#7cdcdc"
gblue3 = "#82e896"
gblue1 = "#89b4fa"
gblue2 = "#89dceb"
gblue3 = "#a6e3a1"
@classmethod
def lims(cls, track1, track2):
@@ -229,7 +229,7 @@ def PlotStyle() -> None:
plt.rc("legend", fontsize=SMALL_SIZE) # legend fontsize
plt.rc("figure", titlesize=BIGGER_SIZE) # fontsize of the figure title
plt.rcParams["image.cmap"] = 'cmo.haline'
plt.rcParams["image.cmap"] = "cmo.haline"
plt.rcParams["axes.xmargin"] = 0.05
plt.rcParams["axes.ymargin"] = 0.1
plt.rcParams["axes.titlelocation"] = "left"
@@ -261,31 +261,33 @@ def PlotStyle() -> None:
# plt.rcParams["axes.grid"] = True # display grid or not
# plt.rcParams["axes.grid.axis"] = "y" # which axis the grid is applied to
plt.rcParams["axes.labelcolor"] = white
plt.rcParams["axes.axisbelow"] = True # draw axis gridlines and ticks:
plt.rcParams["axes.axisbelow"] = True # draw axis gridlines and ticks:
plt.rcParams["axes.spines.left"] = True # display axis spines
plt.rcParams["axes.spines.bottom"] = True
plt.rcParams["axes.spines.top"] = False
plt.rcParams["axes.spines.right"] = False
plt.rcParams["axes.prop_cycle"] = cycler(
'color', [
'#b4befe',
'#89b4fa',
'#74c7ec',
'#89dceb',
'#94e2d5',
'#a6e3a1',
'#f9e2af',
'#fab387',
'#eba0ac',
'#f38ba8',
'#cba6f7',
'#f5c2e7',
])
"color",
[
"#b4befe",
"#89b4fa",
"#74c7ec",
"#89dceb",
"#94e2d5",
"#a6e3a1",
"#f9e2af",
"#fab387",
"#eba0ac",
"#f38ba8",
"#cba6f7",
"#f5c2e7",
],
)
plt.rcParams["xtick.color"] = gray # color of the ticks
plt.rcParams["ytick.color"] = gray # color of the ticks
plt.rcParams["grid.color"] = dark_gray # grid color
plt.rcParams["figure.facecolor"] = black # figure face color
plt.rcParams["figure.edgecolor"] = black # figure edge color
plt.rcParams["figure.facecolor"] = black # figure face color
plt.rcParams["figure.edgecolor"] = black # figure edge color
plt.rcParams["savefig.facecolor"] = black # figure face color when saving
return style
@@ -295,12 +297,11 @@ if __name__ == "__main__":
s = PlotStyle()
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import matplotlib.cm as cm
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
from matplotlib.path import Path
from matplotlib.patches import PathPatch
from matplotlib.path import Path
# Fixing random state for reproducibility
np.random.seed(19680801)
@@ -308,14 +309,20 @@ if __name__ == "__main__":
delta = 0.025
x = y = np.arange(-3.0, 3.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
Z1 = np.exp(-(X**2) - Y**2)
Z2 = np.exp(-((X - 1) ** 2) - (Y - 1) ** 2)
Z = (Z1 - Z2) * 2
fig1, ax = plt.subplots()
im = ax.imshow(Z, interpolation='bilinear', cmap=cm.RdYlGn,
origin='lower', extent=[-3, 3, -3, 3],
vmax=abs(Z).max(), vmin=-abs(Z).max())
im = ax.imshow(
Z,
interpolation="bilinear",
cmap=cm.RdYlGn,
origin="lower",
extent=[-3, 3, -3, 3],
vmax=abs(Z).max(),
vmin=-abs(Z).max(),
)
plt.show()
@@ -328,22 +335,21 @@ if __name__ == "__main__":
all_data = [np.random.normal(0, std, 100) for std in range(6, 10)]
# plot violin plot
axs[0].violinplot(all_data,
showmeans=False,
showmedians=True)
axs[0].set_title('Violin plot')
axs[0].violinplot(all_data, showmeans=False, showmedians=True)
axs[0].set_title("Violin plot")
# plot box plot
axs[1].boxplot(all_data)
axs[1].set_title('Box plot')
axs[1].set_title("Box plot")
# adding horizontal grid lines
for ax in axs:
ax.yaxis.grid(True)
ax.set_xticks([y + 1 for y in range(len(all_data))],
labels=['x1', 'x2', 'x3', 'x4'])
ax.set_xlabel('Four separate samples')
ax.set_ylabel('Observed values')
ax.set_xticks(
[y + 1 for y in range(len(all_data))], labels=["x1", "x2", "x3", "x4"]
)
ax.set_xlabel("Four separate samples")
ax.set_ylabel("Observed values")
plt.show()
@@ -355,24 +361,42 @@ if __name__ == "__main__":
theta = np.linspace(0.0, 2 * np.pi, N, endpoint=False)
radii = 10 * np.random.rand(N)
width = np.pi / 4 * np.random.rand(N)
colors = cmo.cm.haline(radii / 10.)
colors = cmo.cm.haline(radii / 10.0)
ax = plt.subplot(projection='polar')
ax = plt.subplot(projection="polar")
ax.bar(theta, radii, width=width, bottom=0.0, color=colors, alpha=0.5)
plt.show()
methods = [None, 'none', 'nearest', 'bilinear', 'bicubic', 'spline16',
'spline36', 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric',
'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc', 'lanczos']
methods = [
None,
"none",
"nearest",
"bilinear",
"bicubic",
"spline16",
"spline36",
"hanning",
"hamming",
"hermite",
"kaiser",
"quadric",
"catrom",
"gaussian",
"bessel",
"mitchell",
"sinc",
"lanczos",
]
# Fixing random state for reproducibility
np.random.seed(19680801)
grid = np.random.rand(4, 4)
fig, axs = plt.subplots(nrows=3, ncols=6, figsize=(9, 6),
subplot_kw={'xticks': [], 'yticks': []})
fig, axs = plt.subplots(
nrows=3, ncols=6, figsize=(9, 6), subplot_kw={"xticks": [], "yticks": []}
)
for ax, interp_method in zip(axs.flat, methods):
ax.imshow(grid, interpolation=interp_method)

View File

@@ -0,0 +1,160 @@
import numpy as np
import os
import numpy as np
import matplotlib.pyplot as plt
from thunderfish.powerspectrum import decibel
from IPython import embed
from pandas import read_csv
from modules.logger import makeLogger
from modules.plotstyle import PlotStyle
from modules.behaviour_handling import Behavior, correct_chasing_events
ps = PlotStyle()
logger = makeLogger(__name__)
def main(datapath: str):
foldernames = [
datapath + x + '/' for x in os.listdir(datapath) if os.path.isdir(datapath+x)]
path_order_meta = (
'/').join(foldernames[0].split('/')[:-2]) + '/order_meta.csv'
order_meta_df = read_csv(path_order_meta)
order_meta_df['recording'] = order_meta_df['recording'].str[1:-1]
path_id_meta = (
'/').join(foldernames[0].split('/')[:-2]) + '/id_meta.csv'
id_meta_df = read_csv(path_id_meta)
chirps_winner = []
size_diff = []
chirps_diff = []
chirps_loser = []
freq_diff = []
for foldername in foldernames:
# behabvior is pandas dataframe with all the data
if foldername == '../data/mount_data/2020-05-12-10_00/':
continue
bh = Behavior(foldername)
# chirps are not sorted in time (presumably due to prior groupings)
# get and sort chirps and corresponding fish_ids of the chirps
category = bh.behavior
timestamps = bh.start_s
# Correct for doubles in chasing on- and offsets to get the right on-/offset pairs
# Get rid of tracking faults (two onsets or two offsets after another)
category, timestamps = correct_chasing_events(category, timestamps)
folder_name = foldername.split('/')[-2]
winner_row = order_meta_df[order_meta_df['recording'] == folder_name]
winner = winner_row['winner'].values[0].astype(int)
winner_fish1 = winner_row['fish1'].values[0].astype(int)
winner_fish2 = winner_row['fish2'].values[0].astype(int)
groub = winner_row['group'].values[0].astype(int)
size_rows = id_meta_df[id_meta_df['group'] == groub]
if winner == winner_fish1:
winner_fish_id = winner_row['rec_id1'].values[0]
loser_fish_id = winner_row['rec_id2'].values[0]
size_winners = []
for l in ['l1', 'l2', 'l3']:
size_winner = size_rows[size_rows['fish']== winner_fish1][l].values[0]
size_winners.append(size_winner)
mean_size_winner = np.nanmean(size_winners)
size_losers = []
for l in ['l1', 'l2', 'l3']:
size_loser = size_rows[size_rows['fish']== winner_fish2][l].values[0]
size_losers.append(size_loser)
mean_size_loser = np.nanmean(size_losers)
size_diff.append(mean_size_winner - mean_size_loser)
elif winner == winner_fish2:
winner_fish_id = winner_row['rec_id2'].values[0]
loser_fish_id = winner_row['rec_id1'].values[0]
size_winners = []
for l in ['l1', 'l2', 'l3']:
size_winner = size_rows[size_rows['fish']== winner_fish2][l].values[0]
size_winners.append(size_winner)
mean_size_winner = np.nanmean(size_winners)
size_losers = []
for l in ['l1', 'l2', 'l3']:
size_loser = size_rows[size_rows['fish']== winner_fish1][l].values[0]
size_losers.append(size_loser)
mean_size_loser = np.nanmean(size_losers)
size_diff.append(mean_size_winner - mean_size_loser)
else:
continue
print(foldername)
all_fish_ids = np.unique(bh.chirps_ids)
chirp_winner = len(bh.chirps[bh.chirps_ids == winner_fish_id])
chirp_loser = len(bh.chirps[bh.chirps_ids == loser_fish_id])
freq_winner = np.nanmedian(bh.freq[bh.ident==winner_fish_id])
freq_loser = np.nanmedian(bh.freq[bh.ident==loser_fish_id])
chirps_winner.append(chirp_winner)
chirps_loser.append(chirp_loser)
chirps_diff.append(chirp_winner - chirp_loser)
freq_diff.append(freq_winner - freq_loser)
fish1_id = all_fish_ids[0]
fish2_id = all_fish_ids[1]
print(winner_fish_id)
print(all_fish_ids)
fig, (ax1, ax2, ax3) = plt.subplots(1,3, figsize=(10,5))
scatterwinner = 1.15
scatterloser = 1.85
bplot1 = ax1.boxplot(chirps_winner, positions=[
1], showfliers=False, patch_artist=True)
bplot2 = ax1.boxplot(chirps_loser, positions=[
2], showfliers=False, patch_artist=True)
ax1.scatter(np.ones(len(chirps_winner))*scatterwinner, chirps_winner, color='r')
ax1.scatter(np.ones(len(chirps_loser))*scatterloser, chirps_loser, color='r')
ax1.set_xticklabels(['winner', 'loser'])
ax1.text(0.9, 0.9, f'n = {len(chirps_winner)}', transform=ax1.transAxes, color= ps.white)
for w, l in zip(chirps_winner, chirps_loser):
ax1.plot([scatterwinner, scatterloser], [w, l], color='r', alpha=0.5, linewidth=0.5)
colors1 = ps.red
ps.set_boxplot_color(bplot1, colors1)
colors1 = ps.orange
ps.set_boxplot_color(bplot2, colors1)
ax1.set_ylabel('Chirpscounts [n]')
ax2.scatter(size_diff, chirps_diff, color='r')
ax2.set_xlabel('Size difference [mm]')
ax2.set_ylabel('Chirps difference [n]')
ax3.scatter(freq_diff, chirps_diff, color='r')
ax3.set_xlabel('Frequency difference [Hz]')
ax3.set_yticklabels([])
ax3.set
plt.savefig('../poster/figs/chirps_winner_loser.pdf')
plt.show()
if __name__ == '__main__':
# Path to the data
datapath = '../data/mount_data/'
main(datapath)

111
code/plot_event_timeline.py Normal file
View File

@@ -0,0 +1,111 @@
import numpy as np
import os
import numpy as np
import matplotlib.pyplot as plt
from thunderfish.powerspectrum import decibel
from IPython import embed
from pandas import read_csv
from modules.logger import makeLogger
from modules.plotstyle import PlotStyle
from modules.behaviour_handling import Behavior, correct_chasing_events
ps = PlotStyle()
logger = makeLogger(__name__)
def main(datapath: str):
foldernames = [datapath + x + '/' for x in os.listdir(datapath) if os.path.isdir(datapath+x)]
for foldername in foldernames:
if foldername == '../data/mount_data/2020-05-12-10_00/':
continue
# behabvior is pandas dataframe with all the data
bh = Behavior(foldername)
category = bh.behavior
timestamps = bh.start_s
# Correct for doubles in chasing on- and offsets to get the right on-/offset pairs
# Get rid of tracking faults (two onsets or two offsets after another)
category, timestamps = correct_chasing_events(category, timestamps)
# split categories
chasing_onset = (timestamps[category == 0]/ 60) /60
chasing_offset = (timestamps[category == 1]/ 60) /60
physical_contact = (timestamps[category == 2] / 60) /60
all_fish_ids = np.unique(bh.chirps_ids)
fish1_id = all_fish_ids[0]
fish2_id = all_fish_ids[1]
# Associate chirps to inidividual fish
fish1 = (bh.chirps[bh.chirps_ids == fish1_id] / 60) /60
fish2 = (bh.chirps[bh.chirps_ids == fish2_id] / 60) /60
fish1_color = ps.red
fish2_color = ps.orange
fig, ax = plt.subplots(4, 1, figsize=(10, 5), height_ratios=[0.5, 0.5, 0.5, 6], sharex=True)
# marker size
s = 200
ax[0].scatter(physical_contact, np.ones(len(physical_contact)), color='firebrick', marker='|', s=s)
ax[1].scatter(chasing_onset, np.ones(len(chasing_onset)), color='green', marker='|', s=s )
ax[2].scatter(fish1, np.ones(len(fish1))-0.25, color=fish1_color, marker='|', s=s)
ax[2].scatter(fish2, np.zeros(len(fish2))+0.25, color=fish2_color, marker='|', s=s)
freq_temp = bh.freq[bh.ident==fish1_id]
time_temp = bh.time[bh.idx[bh.ident==fish1_id]]
ax[3].plot((time_temp/ 60) /60, freq_temp, color=fish1_color)
freq_temp = bh.freq[bh.ident==fish2_id]
time_temp = bh.time[bh.idx[bh.ident==fish2_id]]
ax[3].plot((time_temp/ 60) /60, freq_temp, color=fish2_color)
#ax[3].imshow(decibel(bh.spec), extent=[bh.time[0]/60/60, bh.time[-1]/60/60, 0, 2000], aspect='auto', origin='lower')
# Hide grid lines
ax[0].grid(False)
ax[0].set_frame_on(False)
ax[0].set_xticks([])
ax[0].set_yticks([])
ps.hide_ax(ax[0])
ax[1].grid(False)
ax[1].set_frame_on(False)
ax[1].set_xticks([])
ax[1].set_yticks([])
ps.hide_ax(ax[1])
ax[2].grid(False)
ax[2].set_frame_on(False)
ax[2].set_yticks([])
ax[2].set_xticks([])
ps.hide_ax(ax[2])
ax[3].axvspan(3, 6, 0, 5, facecolor='grey', alpha=0.5)
ax[3].set_xticks(np.arange(0, 6.1, 0.5))
labelpad = 40
ax[0].set_ylabel('Physical contact', rotation=0, labelpad=labelpad)
ax[1].set_ylabel('Chasing events', rotation=0, labelpad=labelpad)
ax[2].set_ylabel('Chirps', rotation=0, labelpad=labelpad)
ax[3].set_ylabel('EODf')
ax[3].set_xlabel('Time [h]')
ax[0].set_title(foldername.split('/')[-2])
# 2020-03-31-9_59
plt.show()
embed()
# plot chirps
if __name__ == '__main__':
# Path to the data
datapath = '../data/mount_data/'
main(datapath)

View File

@@ -41,9 +41,9 @@ def main():
freqtime2, freq2 = instantaneous_frequency(
filtered2, data.raw_rate, smoothing_window=3)
ax1.plot(freqtime1*timescaler, freq1, color=ps.gblue1,
ax1.plot(freqtime1*timescaler, freq1, color=ps.red,
lw=2, label=f"fish 1, {np.median(freq1):.0f} Hz")
ax1.plot(freqtime2*timescaler, freq2, color=ps.gblue3,
ax1.plot(freqtime2*timescaler, freq2, color=ps.orange,
lw=2, label=f"fish 2, {np.median(freq2):.0f} Hz")
ax1.legend(bbox_to_anchor=(0, 1.02, 1, 0.2), loc="lower center",
mode="normal", borderaxespad=0, ncol=2)

Binary file not shown.

Binary file not shown.

Binary file not shown.

529
poster/figs/logo_all.pdf Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -1,4 +1,4 @@
\documentclass[25pt, a0paper, landscape, margin=0mm, innermargin=20mm,
\documentclass[25pt, a0paper, portrait, margin=0mm, innermargin=20mm,
blockverticalspace=2mm, colspace=20mm, subcolspace=0mm]{tikzposter} %Default values for poster format options.
\input{packages}
@@ -7,113 +7,84 @@ blockverticalspace=2mm, colspace=20mm, subcolspace=0mm]{tikzposter} %Default val
\begin{document}
\renewcommand{\baselinestretch}{1}
\title{\parbox{1900pt}{Pushing the limits of time-frequency uncertainty in the
detection of transient communication signals in weakly electric fish}}
\author{Sina Prause, Alexander Wendt, Patrick Weygoldt}
\institute{Supervised by Till Raab \& Jan Benda, Neurothology Group,
University of Tübingen}
\title{\parbox{1500pt}{Detection of transient communication signals in weakly electric fish}}
\author{Sina Prause, Alexander Wendt, and Patrick Weygoldt}
\institute{Supervised by Till Raab \& Jan Benda, Neuroethology Lab, University of Tuebingen}
\usetitlestyle[]{sampletitle}
\maketitle
\renewcommand{\baselinestretch}{1.4}
\begin{columns}
\column{0.5}
\column{0.4}
\myblock[TranspBlock]{Introduction}{
\begin{minipage}[t]{0.55\linewidth}
The time-frequency tradeoff makes reliable signal detecion and simultaneous
sender identification of freely interacting individuals impossible.
This profoundly limits our current understanding of chirps to experiments
with single - or physically separated - individuals.
\end{minipage} \hfill
\begin{minipage}[t]{0.40\linewidth}
\vspace{-1.5cm}
The time-frequency tradeoff makes reliable signal detecion and simultaneous
sender identification of freely interacting individuals impossible.
This profoundly limits our current understanding of chirps to experiments
with single - or physically separated - individuals.
% \begin{tikzfigure}[]
% \label{griddrawing}
% \includegraphics[width=1\linewidth]{figs/introplot}
% \end{tikzfigure}
}
\myblock[TranspBlock]{Chirp detection}{
\begin{tikzfigure}[]
\label{tradeoff}
\includegraphics[width=\linewidth]{figs/introplot}
\label{fig:example_a}
\includegraphics[width=1\linewidth]{figs/algorithm}
\end{tikzfigure}
\end{minipage}
\vspace{0cm}
}
\myblock[TranspBlock]{A chirp detection algorithm}{
\begin{tikzfigure}[]
\label{modulations}
\includegraphics[width=\linewidth]{figs/algorithm}
\end{tikzfigure}
\column{0.6}
\myblock[TranspBlock]{Chirps during competition}{
\begin{tikzfigure}[]
\label{fig:example_b}
\includegraphics[width=0.5\linewidth]{example-image-b}
\end{tikzfigure}
\noindent
}
\column{0.5}
\myblock[TranspBlock]{Chirps and diadic competitions}{
\begin{minipage}[t]{0.7\linewidth}
\myblock[TranspBlock]{Interactions at modulations}{
\vspace{-1.2cm}
\begin{tikzfigure}[]
\label{modulations}
\includegraphics[width=\linewidth]{figs/placeholder1}
\label{fig:example_c}
\includegraphics[width=0.5\linewidth]{example-image-c}
\end{tikzfigure}
\end{minipage} \hfill
\begin{minipage}[t]{0.25\linewidth}
\lipsum[3][1-3]
\end{minipage}
\begin{minipage}[t]{0.7\linewidth}
\begin{tikzfigure}[]
\label{modulations}
\includegraphics[width=\linewidth]{figs/placeholder1}
\end{tikzfigure}
\end{minipage} \hfill
\begin{minipage}[t]{0.25\linewidth}
\lipsum[3][1-3]
\end{minipage}
\begin{minipage}[t]{0.7\linewidth}
\begin{tikzfigure}[]
\label{modulations}
\includegraphics[width=\linewidth]{figs/placeholder1}
\end{tikzfigure}
\end{minipage} \hfill
\begin{minipage}[t]{0.25\linewidth}
\lipsum[3][1-3]
\end{minipage}
\begin{multicols}{2}
\begin{itemize}
\setlength\itemsep{0.5em}
\item $\Delta$EOD$f$ does not appear to decrease during synchronous modulations ().
\item Individuals that rise their EOD$f$ first appear to rise their frequency higher compared to reactors (\textbf{B}).
\vfill
\null
\columnbreak
\item Synchronized fish keep distances below 1 m (\textbf{C}) but distances over 3 m also occur (see \textbf{movie}).
\item Spatial interactions increase \textbf{after} the start of a synchronous modulation (\textbf{D}).
\end{itemize}
\end{multicols}
\vspace{-1cm}
}
\myblock[TranspBlock]{Conclusion}{
\lipsum[3][1-9]
}
\myblock[GrayBlock]{Conclusion}{
\begin{itemize}
\setlength\itemsep{0.5em}
\item Our analysis is the first to indicate that \textit{A. leptorhynchus} uses long, diffuse and synchronized EOD$f$ signals to communicate in addition to chirps and rises.
\item The recorded fish do not exhibit jamming avoidance behavior while close during synchronous modulations.
\item Synchronous signals \textbf{initiate} spatio-temporal interactions.
\end{itemize}
\vspace{0.2cm}
}
\end{columns}
% \column{0.3}
% \myblock[TranspBlock]{More Results}{
% \begin{tikzfigure}[]
% \label{results}
% \includegraphics[width=\linewidth]{example-image-a}
% \end{tikzfigure}
% \begin{multicols}{2}
% \lipsum[5][1-8]
% \end{multicols}
% \vspace{-1cm}
% }
% \myblock[TranspBlock]{Conclusion}{
% \begin{itemize}
% \setlength\itemsep{0.5em}
% \item \lipsum[1][1]
% \item \lipsum[1][1]
% \item \lipsum[1][1]
% \end{itemize}
% \vspace{0.2cm}
% }
\end{columns}
\node[
above right,
\node [above right,
text=white,
outer sep=45pt,
minimum width=\paperwidth,
align=center,
draw,
fill=boxes,
color=boxes,
] at (-0.51\paperwidth,-43.5) {
\textcolor{text}{\normalsize Contact: \{name\}.\{surname\}@student.uni-tuebingen.de}};
color=boxes] at (-43.6,-61) {
\textcolor{white}{
\normalsize Contact: \{name\}.\{surname\}@student.uni-tuebingen.de}};
\end{document}

View File

@@ -1,11 +1,10 @@
\usepackage[utf8]{inputenc}
\usepackage[scaled]{helvet}
\renewcommand\familydefault{\sfdefault}
\renewcommand\familydefault{\sfdefault}
\usepackage[T1]{fontenc}
\usepackage{wrapfig}
\usepackage{setspace}
\usepackage{multicol}
\setlength{\columnsep}{1.5cm}
\usepackage{xspace}
\usepackage{tikz}
\usepackage{lipsum}
\usepackage{tikz}

View File

@@ -16,10 +16,11 @@
\colorlet{notefgcolor}{background}
\colorlet{notebgcolor}{background}
% Title setup
\settitle{
% Rearrange the order of the minipages to e.g. center the title between the logos
\begin{minipage}[c]{0.6\paperwidth}
\begin{minipage}[c]{0.8\paperwidth}
% \centering
\vspace{2.5cm}\hspace{1.5cm}
\color{text}{\Huge{\textbf{\@title}} \par}
@@ -30,26 +31,28 @@
\vspace{2.5cm}
\end{minipage}
\begin{minipage}[c]{0.2\paperwidth}
% \centering
\vspace{1cm}\hspace{1cm}
\includegraphics[scale=1]{example-image-a}
\end{minipage}
\begin{minipage}[c]{0.2\paperwidth}
% \vspace{1cm}\hspace{1cm}
\centering
\includegraphics[scale=1]{example-image-a}
% \vspace{1cm}
\hspace{-10cm}
\includegraphics[width=\linewidth]{example-image-a}
\end{minipage}}
% \begin{minipage}[c]{0.2\paperwidth}
% \vspace{1cm}\hspace{1cm}
% \centering
% \includegraphics[width=\linewidth]{example-image-a}
% \end{minipage}}
% definie title style with background box
% define title style with background box (currently white)
\definetitlestyle{sampletitle}{
width=1189mm,
width=841mm,
roundedcorners=0,
linewidth=0pt,
innersep=15pt,
titletotopverticalspace=0mm,
titletoblockverticalspace=5pt
}{
\begin{scope}[line width=\titlelinewidth, rounded corners=\titleroundedcorners]
\begin{scope}[line width=\titlelinewidth,
rounded corners=\titleroundedcorners]
\draw[fill=text, color=boxes]
(\titleposleft,\titleposbottom)
rectangle

View File

Before

Width:  |  Height:  |  Size: 116 KiB

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 84 KiB

View File

Before

Width:  |  Height:  |  Size: 157 KiB

After

Width:  |  Height:  |  Size: 157 KiB

BIN
poster_old/main.pdf Normal file

Binary file not shown.

119
poster_old/main.tex Normal file
View File

@@ -0,0 +1,119 @@
\documentclass[25pt, a0paper, landscape, margin=0mm, innermargin=20mm,
blockverticalspace=2mm, colspace=20mm, subcolspace=0mm]{tikzposter} %Default values for poster format options.
\input{packages}
\input{style}
\begin{document}
\renewcommand{\baselinestretch}{1}
\title{\parbox{1900pt}{Pushing the limits of time-frequency uncertainty in the
detection of transient communication signals in weakly electric fish}}
\author{Sina Prause, Alexander Wendt, Patrick Weygoldt}
\institute{Supervised by Till Raab \& Jan Benda, Neurothology Group,
University of Tübingen}
\usetitlestyle[]{sampletitle}
\maketitle
\renewcommand{\baselinestretch}{1.4}
\begin{columns}
\column{0.5}
\myblock[TranspBlock]{Introduction}{
\begin{minipage}[t]{0.55\linewidth}
The time-frequency tradeoff makes reliable signal detecion and simultaneous
sender identification of freely interacting individuals impossible.
This profoundly limits our current understanding of chirps to experiments
with single - or physically separated - individuals.
\end{minipage} \hfill
\begin{minipage}[t]{0.40\linewidth}
\vspace{-1.5cm}
\begin{tikzfigure}[]
\label{tradeoff}
\includegraphics[width=\linewidth]{figs/introplot}
\end{tikzfigure}
\end{minipage}
}
\myblock[TranspBlock]{A chirp detection algorithm}{
\begin{tikzfigure}[]
\label{modulations}
\includegraphics[width=\linewidth]{figs/algorithm}
\end{tikzfigure}
}
\column{0.5}
\myblock[TranspBlock]{Chirps and diadic competitions}{
\begin{minipage}[t]{0.7\linewidth}
\begin{tikzfigure}[]
\label{modulations}
\includegraphics[width=\linewidth]{figs/placeholder1}
\end{tikzfigure}
\end{minipage} \hfill
\begin{minipage}[t]{0.25\linewidth}
\lipsum[3][1-3]
\end{minipage}
\begin{minipage}[t]{0.7\linewidth}
\begin{tikzfigure}[]
\label{modulations}
\includegraphics[width=\linewidth]{figs/placeholder1}
\end{tikzfigure}
\end{minipage} \hfill
\begin{minipage}[t]{0.25\linewidth}
\lipsum[3][1-3]
\end{minipage}
\begin{minipage}[t]{0.7\linewidth}
\begin{tikzfigure}[]
\label{modulations}
\includegraphics[width=\linewidth]{figs/placeholder1}
\end{tikzfigure}
\end{minipage} \hfill
\begin{minipage}[t]{0.25\linewidth}
\lipsum[3][1-3]
\end{minipage}
}
\myblock[TranspBlock]{Conclusion}{
\lipsum[3][1-9]
}
% \column{0.3}
% \myblock[TranspBlock]{More Results}{
% \begin{tikzfigure}[]
% \label{results}
% \includegraphics[width=\linewidth]{example-image-a}
% \end{tikzfigure}
% \begin{multicols}{2}
% \lipsum[5][1-8]
% \end{multicols}
% \vspace{-1cm}
% }
% \myblock[TranspBlock]{Conclusion}{
% \begin{itemize}
% \setlength\itemsep{0.5em}
% \item \lipsum[1][1]
% \item \lipsum[1][1]
% \item \lipsum[1][1]
% \end{itemize}
% \vspace{0.2cm}
% }
\end{columns}
\node[
above right,
text=white,
outer sep=45pt,
minimum width=\paperwidth,
align=center,
draw,
fill=boxes,
color=boxes,
] at (-0.51\paperwidth,-43.5) {
\textcolor{text}{\normalsize Contact: \{name\}.\{surname\}@student.uni-tuebingen.de}};
\end{document}

11
poster_old/packages.tex Normal file
View File

@@ -0,0 +1,11 @@
\usepackage[utf8]{inputenc}
\usepackage[scaled]{helvet}
\renewcommand\familydefault{\sfdefault}
\usepackage[T1]{fontenc}
\usepackage{wrapfig}
\usepackage{setspace}
\usepackage{multicol}
\setlength{\columnsep}{1.5cm}
\usepackage{xspace}
\usepackage{tikz}
\usepackage{lipsum}

119
poster_old/style.tex Normal file
View File

@@ -0,0 +1,119 @@
\tikzposterlatexaffectionproofoff
\usetheme{Default}
\definecolor{text}{HTML}{e0e4f7}
\definecolor{background}{HTML}{111116}
\definecolor{boxes}{HTML}{2a2a32}
\definecolor{unired}{HTML}{a51e37}
\colorlet{blocktitlefgcolor}{text}
\colorlet{backgroundcolor}{background}
\colorlet{blocktitlebgcolor}{background}
\colorlet{blockbodyfgcolor}{text}
\colorlet{innerblocktitlebgcolor}{background}
\colorlet{innerblocktitlefgcolor}{text}
\colorlet{notefrcolor}{text}
\colorlet{notefgcolor}{background}
\colorlet{notebgcolor}{background}
% Title setup
\settitle{
% Rearrange the order of the minipages to e.g. center the title between the logos
\begin{minipage}[c]{0.6\paperwidth}
% \centering
\vspace{2.5cm}\hspace{1.5cm}
\color{text}{\Huge{\textbf{\@title}} \par}
\vspace*{2em}\hspace{1.5cm}
\color{text}{\LARGE \@author \par}
\vspace*{2em}\hspace{1.5cm}
\color{text}{\Large \@institute}
\vspace{2.5cm}
\end{minipage}
\begin{minipage}[c]{0.2\paperwidth}
% \centering
\vspace{1cm}\hspace{1cm}
\includegraphics[scale=1]{example-image-a}
\end{minipage}
\begin{minipage}[c]{0.2\paperwidth}
% \vspace{1cm}\hspace{1cm}
\centering
\includegraphics[scale=1]{example-image-a}
\end{minipage}}
% definie title style with background box
\definetitlestyle{sampletitle}{
width=1189mm,
roundedcorners=0,
linewidth=0pt,
innersep=15pt,
titletotopverticalspace=0mm,
titletoblockverticalspace=5pt
}{
\begin{scope}[line width=\titlelinewidth, rounded corners=\titleroundedcorners]
\draw[fill=text, color=boxes]
(\titleposleft,\titleposbottom)
rectangle
(\titleposright,\titlepostop);
\end{scope}
}
% define coustom block style for visible blocks
\defineblockstyle{GrayBlock}{
titlewidthscale=1,
bodywidthscale=1,
% titlecenter,
titleleft,
titleoffsetx=0pt,
titleoffsety=-30pt,
bodyoffsetx=0pt,
bodyoffsety=-40pt,
bodyverticalshift=0mm,
roundedcorners=25,
linewidth=1pt,
titleinnersep=20pt,
bodyinnersep=38pt
}{
\draw[rounded corners=\blockroundedcorners, inner sep=\blockbodyinnersep,
line width=\blocklinewidth, color=background,
top color=boxes, bottom color=boxes,
]
(blockbody.south west) rectangle (blockbody.north east); %
\ifBlockHasTitle%
\draw[rounded corners=\blockroundedcorners, inner sep=\blocktitleinnersep,
top color=background, bottom color=background,
line width=2, color=background, %fill=blocktitlebgcolor
]
(blocktitle.south west) rectangle (blocktitle.north east); %
\fi%
}
\newcommand\myblock[3][GrayBlock]{\useblockstyle{#1}\block{#2}{#3}\useblockstyle{Default}}
% Define blockstyle for tranparent block
\defineblockstyle{TranspBlock}{
titlewidthscale=0.99,
bodywidthscale=0.99,
titleleft,
titleoffsetx=15pt,
titleoffsety=-40pt,
bodyoffsetx=0pt,
bodyoffsety=-40pt,
bodyverticalshift=0mm,
roundedcorners=25,
linewidth=1pt,
titleinnersep=20pt,
bodyinnersep=38pt
}{
\draw[rounded corners=\blockroundedcorners, inner sep=\blockbodyinnersep,
line width=\blocklinewidth, color=background,
top color=background, bottom color=background,
]
(blockbody.south west) rectangle (blockbody.north east); %
\ifBlockHasTitle%
\draw[rounded corners=\blockroundedcorners, inner sep=\blocktitleinnersep,
top color=background, bottom color=background,
line width=2, color=background, %fill=blocktitlebgcolor
]
(blocktitle.south west) rectangle (blocktitle.north east); %
\fi%
}
\renewcommand\myblock[3][TranspBlock]{\useblockstyle{#1}\block{#2}{#3}\useblockstyle{Default}}

29
recs.csv Normal file
View File

@@ -0,0 +1,29 @@
recording
2020-03-13-10_00
2020-03-16-10_00
2020-03-19-10_00
2020-03-20-10_00
2020-03-23-09_58
2020-03-24-10_00
2020-03-25-10_00
2020-03-31-09_59
2020-05-11-10_00
2020-05-12-10_00
2020-05-13-10_00
2020-05-14-10_00
2020-05-15-10_00
2020-05-18-10_00
2020-05-19-10_00
2020-05-21-10_00
2020-05-25-10_00
2020-05-27-10_00
2020-05-28-10_00
2020-05-29-10_00
2020-06-02-10_00
2020-06-03-10_10
2020-06-04-10_00
2020-06-05-10_00
2020-06-08-10_00
2020-06-09-10_00
2020-06-10-10_00
2020-06-11-10_00
1 recording
2 2020-03-13-10_00
3 2020-03-16-10_00
4 2020-03-19-10_00
5 2020-03-20-10_00
6 2020-03-23-09_58
7 2020-03-24-10_00
8 2020-03-25-10_00
9 2020-03-31-09_59
10 2020-05-11-10_00
11 2020-05-12-10_00
12 2020-05-13-10_00
13 2020-05-14-10_00
14 2020-05-15-10_00
15 2020-05-18-10_00
16 2020-05-19-10_00
17 2020-05-21-10_00
18 2020-05-25-10_00
19 2020-05-27-10_00
20 2020-05-28-10_00
21 2020-05-29-10_00
22 2020-06-02-10_00
23 2020-06-03-10_10
24 2020-06-04-10_00
25 2020-06-05-10_00
26 2020-06-08-10_00
27 2020-06-09-10_00
28 2020-06-10-10_00
29 2020-06-11-10_00