all files for init commit added
This commit is contained in:
commit
a70ba50037
81
LED_detect.py
Normal file
81
LED_detect.py
Normal file
@ -0,0 +1,81 @@
|
||||
import os
|
||||
import cv2
|
||||
import argparse
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
def check_LED(cap, frame_count, x0, x1, y0, y1):
|
||||
fig, ax = plt.subplots()
|
||||
ax.plot([x0, x0], [y0, y1], 'r')
|
||||
ax.plot([x1, x1], [y0, y1], 'r')
|
||||
ax.plot([x0, x1], [y0, y0], 'r')
|
||||
ax.plot([x0, x1], [y1, y1], 'r')
|
||||
plt.ion()
|
||||
|
||||
cap.set(cv2.CAP_PROP_POS_FRAMES, int(frame_count / 2))
|
||||
f = None
|
||||
try:
|
||||
for i in np.arange(int(frame_count / 2), frame_count):
|
||||
ret, frame = cap.read()
|
||||
if f == None:
|
||||
f = ax.imshow(frame)
|
||||
else:
|
||||
f.set_data(frame)
|
||||
|
||||
sum_frame = np.sum(frame, axis=2)
|
||||
LED_v = np.mean(sum_frame[y0:y1, x0:x1])
|
||||
print('%.0f: %.1f \n' % (i, LED_v))
|
||||
plt.pause(0.001)
|
||||
except KeyboardInterrupt:
|
||||
plt.close()
|
||||
quit()
|
||||
quit()
|
||||
|
||||
def main(file_path, check, x, y):
|
||||
folder, filename = os.path.split(file_path)
|
||||
cap = cv2.VideoCapture(file_path)
|
||||
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
||||
|
||||
x0, x1 = x
|
||||
y0, y1 = y
|
||||
|
||||
if check:
|
||||
check_LED(cap, frame_count, x0, x1, y0, y1)
|
||||
|
||||
###############
|
||||
# cap.set(cv2.CAP_PROP_POS_FRAMES, int(frame_count / 2))
|
||||
# frame_count = 1000
|
||||
########################
|
||||
|
||||
light_th = 100
|
||||
LED_val = np.zeros(frame_count)
|
||||
print('Frame_count: %.0f' % frame_count)
|
||||
for i in range(frame_count):
|
||||
if i % 1000 == 0:
|
||||
print('progress: %.1f' % ((i/frame_count)*100) + '%')
|
||||
ret, frame = cap.read()
|
||||
|
||||
sum_frame = np.sum(frame, axis=2)
|
||||
LED_val[i] = np.mean(sum_frame[y0:y1, x0:x1])
|
||||
|
||||
np.save(os.path.join(folder, 'LED_val.npy'), LED_val)
|
||||
|
||||
LED_frames = np.arange(len(LED_val)-1)[(LED_val[:-1] < light_th) & (LED_val[1:] > light_th)]
|
||||
|
||||
np.save(os.path.join(folder, 'LED_frames.npy'), LED_frames)
|
||||
fig, ax = plt.subplots()
|
||||
ax.plot(np.arange(len(LED_val)), LED_val, color='k')
|
||||
ax.plot(LED_frames, np.ones(len(LED_frames))*light_th, 'o', color='firebrick')
|
||||
plt.show()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Detect frames of blinking LED in video recordings.')
|
||||
parser.add_argument('file', type=str, help='video file to be analyzed')
|
||||
parser.add_argument("-c", action="store_true", help="check if LED pos is correct")
|
||||
parser.add_argument('-x', type=int, nargs=2, default=[1272, 1282], help='x-borders of LED detect area (in pixels)')
|
||||
parser.add_argument('-y', type=int, nargs=2, default=[1500, 1516], help='y-borders of LED area (in pixels)')
|
||||
args = parser.parse_args()
|
||||
import glob
|
||||
|
||||
main(args.file, args.c, args.x, args.y)
|
53
README.md
Normal file
53
README.md
Normal file
@ -0,0 +1,53 @@
|
||||
# How to competition experiment
|
||||
__Workflow__ (Python-scripts/applications):
|
||||
1) wavetracker.trackingGUI
|
||||
2) wavetracker.EODsorter
|
||||
3) LED_detect.py
|
||||
4) eval_LED.py
|
||||
5) trial_analysis.py
|
||||
6) event_videos.py (optional)
|
||||
|
||||
## Raw data analysis using the wavetracker-modul
|
||||
|
||||
### trackingGUI.py
|
||||
__Frequency extraction and tracking__
|
||||
- open Raw-file (traces-grid1.raw)
|
||||
- 'Spectrogram'-settings:
|
||||
- overlap fraction: 0.8
|
||||
- frequency resolution: 1
|
||||
- check 'Auto-save'; press 'Run'
|
||||
|
||||
__Fine spectrogram__
|
||||
- repeat steps above but press 'Calc. fine spec' instead of Run
|
||||
- fine spec data saved in /home/"user"/analysis/"filename"
|
||||
|
||||
### EODsorter.py
|
||||
|
||||
- load dataset/folder
|
||||
- correct tracked EOD traces
|
||||
- fill EOD traces
|
||||
- fine spec data needs to be manually added to the dataset-folder
|
||||
|
||||
## Competition trial analysis
|
||||
|
||||
### trail_analysis.py
|
||||
|
||||
- Detection of winners, their EODf traces, rises, etc. Results stored in "data-path"/analysis.
|
||||
- (optional) Meta.csv file in base-path of analyzed data. Creates entries for each
|
||||
analyzed recording (index = file names) and stores Meta-data. Manual competation suggested.
|
||||
|
||||
## Video analysis
|
||||
|
||||
### LED_detect.py
|
||||
- Detect blinking LED (emitted by electric recording setup). Used for synchronization.
|
||||
- "-c" argument to identify correct detection area for LED
|
||||
- '-x' (tuple) borders of LED detection window on X-axis (in pixels)
|
||||
- '-y' (tuple) borders of LED detection window on Y-axis (in pixels)
|
||||
|
||||
### eval_LED.py
|
||||
- creates time vector to synchronize electric and video recording
|
||||
- for each frame contains a time-point (in s) that corresponds to the electric recordings.
|
||||
|
||||
## Rise videos (optional)
|
||||
- generates for each detected rise a short video showing the fish's behavior around the rise event.
|
||||
- sorted in 'base-path'/rise_video.
|
59
eval_LED.py
Normal file
59
eval_LED.py
Normal file
@ -0,0 +1,59 @@
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import sys
|
||||
import os
|
||||
import matplotlib.pyplot as plt
|
||||
from IPython import embed
|
||||
import cv2
|
||||
import glob
|
||||
|
||||
def main(folder):
|
||||
sr = 20000
|
||||
|
||||
video_path = glob.glob(os.path.join(folder, '2022*.mp4'))[0]
|
||||
cap = cv2.VideoCapture(video_path)
|
||||
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
||||
|
||||
times = np.load(os.path.join(folder, 'times.npy'))
|
||||
LED_idx = pd.read_csv(os.path.join(folder, 'led_idxs.csv'), sep=',')
|
||||
|
||||
led_idx = np.array(LED_idx).T[0]
|
||||
led_frame = np.load(os.path.join(folder, 'LED_frames.npy'))
|
||||
led_vals = np.load(os.path.join(folder, 'LED_val.npy'))
|
||||
|
||||
led_idx_span = led_idx[-1] - led_idx[0]
|
||||
led_frame_span = led_frame[-1] - led_frame[0]
|
||||
|
||||
led_frame_to_idx = ((led_frame-led_frame[0]) / led_frame_span) * led_idx_span + led_idx[0]
|
||||
|
||||
frame_idxs = np.arange(frame_count)
|
||||
frame_times = (((frame_idxs - led_frame[0]) / led_frame_span) * led_idx_span + led_idx[0]) / sr
|
||||
|
||||
if not os.path.exists(os.path.join(folder, 'analysis')):
|
||||
os.mkdir(os.path.join(folder, 'analysis'))
|
||||
np.save(os.path.join(folder, 'analysis', 'frame_times.npy'), frame_times)
|
||||
|
||||
########################################################################################
|
||||
fig, ax = plt.subplots()
|
||||
ax.plot(led_vals)
|
||||
ax.plot(led_frame, np.ones(len(led_frame))*100, '.', color='firebrick')
|
||||
|
||||
########################################################################################
|
||||
fig, ax = plt.subplots()
|
||||
ax.plot(led_idx / sr, np.ones(len(led_idx)), '.', color='k')
|
||||
ax.plot(led_frame_to_idx / sr, np.ones(len(led_frame_to_idx))+.1, '.', color='firebrick')
|
||||
ax.plot([times[0], times[0]], [0.5, 1.5], 'k', lw=1)
|
||||
ax.plot([times[-1], times[-1]], [0.5, 1.5], 'k', lw=1)
|
||||
|
||||
ax.plot(frame_times, np.ones(len(frame_times))*0.5)
|
||||
|
||||
ax.set_ylim(0, 2)
|
||||
|
||||
plt.show()
|
||||
|
||||
embed()
|
||||
quit()
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv[1])
|
110
event_videos.py
Normal file
110
event_videos.py
Normal file
@ -0,0 +1,110 @@
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.gridspec as gridspec
|
||||
import os
|
||||
import sys
|
||||
import cv2
|
||||
import glob
|
||||
import argparse
|
||||
from IPython import embed
|
||||
from tqdm import tqdm
|
||||
|
||||
def main(folder, dt):
|
||||
video_path = glob.glob(os.path.join(folder, '2022*.mp4'))[0]
|
||||
create_video_path = os.path.join(folder, 'rise_video')
|
||||
if not os.path.exists(create_video_path):
|
||||
os.mkdir(create_video_path)
|
||||
video = cv2.VideoCapture(video_path) # was 'cap'
|
||||
|
||||
fish_freqs = np.load(os.path.join(folder, 'analysis', 'fish_freq_interp.npy'))
|
||||
max_freq, min_freq = np.nanmax(fish_freqs), np.nanmin(fish_freqs)
|
||||
rise_idx = np.load(os.path.join(folder, 'analysis', 'rise_idx.npy'))
|
||||
frame_times = np.load(os.path.join(folder, 'analysis', 'frame_times.npy'))
|
||||
times = np.load(os.path.join(folder, 'times.npy'))
|
||||
#######################################
|
||||
for fish_nr in np.arange(2)[::-1]:
|
||||
|
||||
for idx_oi in tqdm(np.array(rise_idx[fish_nr][~np.isnan(rise_idx[fish_nr])], dtype=int)):
|
||||
# idx_oi = int(rise_idx[1][10])
|
||||
time_oi = times[idx_oi]
|
||||
|
||||
# embed()
|
||||
# quit()
|
||||
|
||||
HH = int((time_oi / 3600) // 1)
|
||||
MM = int((time_oi - HH * 3600) // 60)
|
||||
SS = int(time_oi - HH * 3600 - MM * 60)
|
||||
|
||||
frames_oi = np.arange(len(frame_times))[np.abs(frame_times - time_oi) <= dt]
|
||||
idxs_oi = np.arange(len(times))[np.abs(times - time_oi) <= dt*3]
|
||||
|
||||
fig = plt.figure(figsize=(20/2.54, 20/2.54))
|
||||
gs = gridspec.GridSpec(2, 1, left=0.1, bottom = 0.1, right=0.95, top=0.95, height_ratios=(4, 1))
|
||||
ax = []
|
||||
ax.append(fig.add_subplot(gs[0, 0]))
|
||||
ax.append(fig.add_subplot(gs[1, 0]))
|
||||
ax[1].plot(times[idxs_oi] - time_oi, fish_freqs[0][idxs_oi], marker='.', color='firebrick')
|
||||
ax[1].plot(times[idxs_oi] - time_oi, fish_freqs[1][idxs_oi], marker='.', color='cornflowerblue')
|
||||
ax[1].set_ylim(min_freq - (max_freq-min_freq)*0.25, max_freq + (max_freq-min_freq)*0.25)
|
||||
ax[1].set_xlim(-dt*3, dt*3)
|
||||
ax[0].set_xticks([])
|
||||
ax[0].set_yticks([])
|
||||
|
||||
ax[1].tick_params(labelsize=12)
|
||||
ax[1].set_xlabel('time [s]', fontsize=14)
|
||||
# plt.ion()
|
||||
for i in tqdm(np.arange(len(frames_oi))):
|
||||
video.set(cv2.CAP_PROP_POS_FRAMES, int(frames_oi[i]))
|
||||
ret, frame = video.read()
|
||||
|
||||
if i == 0:
|
||||
img = ax[0].imshow(frame)
|
||||
line, = ax[1].plot([frame_times[frames_oi[i]] - time_oi, frame_times[frames_oi[i]] - time_oi],
|
||||
[min_freq - (max_freq-min_freq)*0.25, max_freq + (max_freq-min_freq)*0.25],
|
||||
color='k', lw=1)
|
||||
else:
|
||||
img.set_data(frame)
|
||||
line.set_data([frame_times[frames_oi[i]] - time_oi, frame_times[frames_oi[i]] - time_oi],
|
||||
[min_freq - (max_freq-min_freq)*0.25, max_freq + (max_freq-min_freq)*0.25])
|
||||
|
||||
# label = ('rise_video/frame%4.f.jpg' % len(glob.glob('rise_video/*.jpg'))).replace(' ', '0')
|
||||
label = (os.path.join(create_video_path, 'frame%4.f.jpg' % len(glob.glob(os.path.join(create_video_path, '*.jpg'))))).replace(' ', '0')
|
||||
plt.savefig(label, dpi=300)
|
||||
# plt.pause(0.001)
|
||||
|
||||
win_lose_str = 'lose' if fish_nr == 1 else 'win'
|
||||
# video_name = ("./rise_video/%s_%2.f:%2.f:%2.f.mp4" % (win_lose_str, HH, MM, SS)).replace(' ', '0')
|
||||
# command = "ffmpeg -r 25 -i './rise_video/frame%4d.jpg' -vf 'pad=ceil(iw/2)*2:ceil(ih/2)*2' -vcodec libx264 -y -an"
|
||||
|
||||
video_name = os.path.join(create_video_path, ("%s_%2.f:%2.f:%2.f.mp4" % (win_lose_str, HH, MM, SS)).replace(' ', '0'))
|
||||
command1 = "ffmpeg -r 25 -i"
|
||||
frames_path = '"%s"' % os.path.join(create_video_path, "frame%4d.jpg")
|
||||
command2 = "-vf 'pad=ceil(iw/2)*2:ceil(ih/2)*2' -vcodec libx264 -y -an"
|
||||
|
||||
os.system(' '.join([command1, frames_path, command2, video_name]))
|
||||
os.system(' '.join(['rm', os.path.join(create_video_path, '*.jpg')]))
|
||||
# os.system(' '.join([command, video_name]))
|
||||
# os.system('rm ./rise_video/*.jpg')
|
||||
plt.close()
|
||||
embed()
|
||||
quit()
|
||||
|
||||
|
||||
###############################
|
||||
fig, ax = plt.subplots()
|
||||
for i, c in enumerate(['firebrick', 'cornflowerblue']):
|
||||
ax.plot(times, fish_freqs[i], marker='.', color=c)
|
||||
r_idx = np.array(rise_idx[i][~np.isnan(rise_idx[i])], dtype=int)
|
||||
ax.plot(times[r_idx], fish_freqs[i][r_idx], 'o', color='k')
|
||||
pass
|
||||
##############################
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Generate videos around events.')
|
||||
parser.add_argument('file', type=str, help='folder/dataset to generate videos from.')
|
||||
parser.add_argument('-t', type=float, default=10, help='video duration before and after event.')
|
||||
# parser.add_argument("-c", action="store_true", help="check if LED pos is correct")
|
||||
# parser.add_argument('-x', type=int, nargs=2, default=[1272, 1282], help='x-borders of LED detect area (in pixels)')
|
||||
# parser.add_argument('-y', type=int, nargs=2, default=[1500, 1516], help='y-borders of LED area (in pixels)')
|
||||
args = parser.parse_args()
|
||||
main(args.file, args.t)
|
260
trail_analysis.py
Normal file
260
trail_analysis.py
Normal file
@ -0,0 +1,260 @@
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.gridspec as gridspec
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
|
||||
from thunderfish.eventdetection import detect_peaks
|
||||
from IPython import embed
|
||||
|
||||
class Trial(object):
|
||||
def __init__(self, folder, base_path, meta, fish_count):
|
||||
self._isValid = False
|
||||
|
||||
self.base_path = base_path
|
||||
self.folder = folder
|
||||
|
||||
self.meta = meta
|
||||
self.fish_count = fish_count
|
||||
|
||||
self.light_sec = 3 * 60 * 60
|
||||
|
||||
self.ids = None
|
||||
self.fish_freq = None
|
||||
self.fish_freq_interp = None
|
||||
self.fish_freq_val = None
|
||||
|
||||
self.baseline_freq_times = None
|
||||
self.baseline_freqs = None
|
||||
|
||||
self.rise_idxs = []
|
||||
self.rise_size = []
|
||||
|
||||
self.fish_sign = None
|
||||
self.fish_sign_interp = None
|
||||
self.winner = None
|
||||
self.loser = None
|
||||
|
||||
if os.path.exists(os.path.join(self.base_path, self.folder, 'fund_v.npy')):
|
||||
self.load()
|
||||
|
||||
def __repr__(self):
|
||||
return f'Trial(Date={self.folder}, winner={self.winner})'
|
||||
# return self.folder
|
||||
|
||||
def load(self):
|
||||
self.fund_v = np.load(os.path.join(self.base_path, self.folder, 'fund_v.npy'))
|
||||
self.idx_v = np.load(os.path.join(self.base_path, self.folder, 'idx_v.npy'))
|
||||
self.times = np.load(os.path.join(self.base_path, self.folder, 'times.npy'))
|
||||
self.ident_v = np.load(os.path.join(self.base_path, self.folder, 'ident_v.npy'))
|
||||
self.sign_v = np.load(os.path.join(self.base_path, self.folder, 'sign_v.npy'))
|
||||
|
||||
self.ids = np.unique(self.ident_v[~np.isnan(self.ident_v)])
|
||||
if len(self.ids) == self.fish_count:
|
||||
self.isValid = True
|
||||
|
||||
def reshape_and_interpolate(self):
|
||||
self.fish_freq = np.full((self.fish_count, len(self.times)), np.nan)
|
||||
self.fish_sign = np.full((self.fish_count, len(self.times), self.sign_v.shape[1]), np.nan)
|
||||
|
||||
for enu, id in enumerate(self.ids):
|
||||
self.fish_freq[enu][self.idx_v[self.ident_v == id]] = self.fund_v[self.ident_v == id]
|
||||
self.fish_sign[enu][self.idx_v[self.ident_v == id]] = self.sign_v[self.ident_v == id]
|
||||
|
||||
|
||||
self.fish_freq_interp = np.full(self.fish_freq.shape, np.nan)
|
||||
self.fish_sign_interp = np.full(self.fish_sign.shape, np.nan)
|
||||
|
||||
for enu, id in enumerate(self.ids):
|
||||
i0, i1 = self.idx_v[self.ident_v == id][0], self.idx_v[self.ident_v == id][-1]
|
||||
self.fish_freq_interp[enu, i0:i1+1] = np.interp(self.times[i0:i1+1],
|
||||
self.times[self.idx_v[self.ident_v == id]],
|
||||
self.fish_freq[enu][~np.isnan(self.fish_freq[enu])])
|
||||
|
||||
help_sign_v = list(map(lambda x: np.interp(self.times[i0:i1+1], self.times[self.idx_v[self.ident_v == id]], x), self.fish_sign[enu][~np.isnan(self.fish_freq[enu])].T))
|
||||
self.fish_sign_interp[enu, i0:i1+1] = np.array(help_sign_v).T
|
||||
|
||||
def baseline_freq(self, bw = 300):
|
||||
bins = np.arange(-bw / 2, self.times[-1] + bw / 2, bw)
|
||||
self.baseline_freq_times = np.array(bins[:-1] + (bins[1] - bins[0])/2)
|
||||
self.baseline_freqs = np.full((2, len(self.baseline_freq_times)), np.nan)
|
||||
|
||||
for enu, id in enumerate(self.ids):
|
||||
for i in range(len(bins) - 1):
|
||||
Cf = self.fish_freq[enu][(self.times > bins[i]) & (self.times <= bins[i + 1])]
|
||||
if len(Cf) == 0:
|
||||
continue
|
||||
else:
|
||||
self.baseline_freqs[enu][i] = np.nanpercentile(Cf, 5)
|
||||
|
||||
self.fish_freq_val = [np.nanmean(x[self.baseline_freq_times > self.light_sec]) for x in self.baseline_freqs]
|
||||
|
||||
def winner_detection(self):
|
||||
day_mask = self.times > self.light_sec
|
||||
day_idxs = np.arange(len(self.times))[day_mask]
|
||||
|
||||
shelter_power = np.empty((2, len(day_idxs)))
|
||||
for enu, id in enumerate(self.ids):
|
||||
shelter_power[enu] = self.fish_sign_interp[enu][day_idxs, -1]
|
||||
|
||||
mean_shelter_power = np.nanmean(shelter_power, axis=1)
|
||||
self.winner = 1 if mean_shelter_power[1] > mean_shelter_power[0] else 0
|
||||
self.loser = 0 if self.winner == 1 else 1
|
||||
|
||||
def rise_detection(self, rise_th):
|
||||
def check_rises_size(peak):
|
||||
peak_f = self.fish_freq[i][peak]
|
||||
peak_t = self.times[peak]
|
||||
|
||||
closest_baseline_idx = list(map(lambda x: np.argmin(np.abs(self.baseline_freq_times - x)), peak_t))
|
||||
closest_baseline_freq = self.baseline_freqs[i][closest_baseline_idx]
|
||||
|
||||
rise_size = peak_f - closest_baseline_freq
|
||||
|
||||
return rise_size
|
||||
|
||||
for i in range(len(self.fish_freq)):
|
||||
rise_peak_idx, trough = detect_peaks(self.fish_freq[i][~np.isnan(self.fish_freq[i])], rise_th)
|
||||
non_nan_idx = np.arange(len(self.fish_freq[i]))[~np.isnan(self.fish_freq[i])]
|
||||
rise_peak_idx, trough = non_nan_idx[rise_peak_idx], non_nan_idx[trough]
|
||||
|
||||
rise_size = check_rises_size(rise_peak_idx)
|
||||
|
||||
self.rise_idxs.append(rise_peak_idx[rise_size >= rise_th])
|
||||
self.rise_size.append(rise_size[rise_size >= rise_th])
|
||||
|
||||
def update_meta(self):
|
||||
entries = self.meta.index.tolist()
|
||||
if self. folder not in entries:
|
||||
self.meta.loc[self.folder] = ['' for _ in self.meta.columns]
|
||||
self.meta.loc[self.folder, 'Win_ID'] = self.ids[self.winner]
|
||||
self.meta.loc[self.folder, 'Lose_ID'] = self.ids[self.loser]
|
||||
|
||||
self.meta.loc[self.folder, 'Win_EODf'] = self.fish_freq_val[self.winner]
|
||||
self.meta.loc[self.folder, 'Lose_EODf'] = self.fish_freq_val[self.loser]
|
||||
|
||||
self.meta.loc[self.folder, 'Win_rise_c'] = len(self.rise_idxs[self.winner])
|
||||
self.meta.loc[self.folder, 'Lose_rise_c'] = len(self.rise_idxs[self.loser])
|
||||
|
||||
self.meta.loc[self.folder, 'light_sec'] = self.light_sec
|
||||
|
||||
self.meta.to_csv(os.path.join(self.base_path, 'meta.csv'), sep =',')
|
||||
|
||||
def ilustrate(self):
|
||||
fig = plt.figure(figsize=(20/2.54, 12/2.54))
|
||||
gs = gridspec.GridSpec(1, 1, left = 0.1, bottom = 0.1, right = 0.95, top = 0.95)
|
||||
ax = fig.add_subplot(gs[0, 0])
|
||||
|
||||
for enu, id in enumerate(self.ids):
|
||||
c = 'firebrick' if self.winner == enu else 'forestgreen'
|
||||
ax.plot(self.times, self.fish_freq[enu], marker='.', color=c, zorder=1)
|
||||
ax.plot(self.times[np.isnan(self.fish_freq[enu])], self.fish_freq_interp[enu][np.isnan(self.fish_freq[enu])], '.', zorder=1, color=c, alpha=0.25)
|
||||
ax.plot(self.baseline_freq_times, self.baseline_freqs[enu], '--', color='k', zorder=2)
|
||||
|
||||
ax.plot(self.times[self.rise_idxs[enu]], self.fish_freq_interp[enu][self.rise_idxs[enu]], 'o', color='k')
|
||||
|
||||
|
||||
win_str = '(W)' if self.winner == enu else ''
|
||||
|
||||
ax.text(self.times[-1], self.fish_freq_val[enu]-10, '%.0f' % id + win_str, va ='center', ha='right')
|
||||
|
||||
ax.set_xlim(0, self.times[-1])
|
||||
|
||||
freq_range = (np.nanmin(self.fish_freq), np.nanmax(self.fish_freq))
|
||||
ax.set_ylim(freq_range[0] - 20, freq_range[1] + 10)
|
||||
plt.show()
|
||||
|
||||
def save(self):
|
||||
saveorder = -1 if self.winner == 1 else 1
|
||||
|
||||
np.save(os.path.join(self.base_path, self.folder, 'analysis', 'fish_freq.npy'), self.fish_freq[::saveorder])
|
||||
np.save(os.path.join(self.base_path, self.folder, 'analysis', 'fish_freq_interp.npy'), self.fish_freq_interp[::saveorder])
|
||||
|
||||
np.save(os.path.join(self.base_path, self.folder, 'analysis', 'baseline_freqs.npy'), self.baseline_freqs[::saveorder])
|
||||
np.save(os.path.join(self.base_path, self.folder, 'analysis', 'baseline_freq_times.npy'), self.baseline_freq_times[::saveorder])
|
||||
|
||||
help_lens = [len(x) for x in self.rise_idxs]
|
||||
rise_idxs_s = np.full((self.fish_count, np.max(help_lens)), np.nan)
|
||||
rise_size_s = np.full((self.fish_count, np.max(help_lens)), np.nan)
|
||||
for i in range(self.fish_count):
|
||||
rise_idxs_s[i][:len(self.rise_idxs[i])] = self.rise_idxs[i]
|
||||
rise_size_s[i][:len(self.rise_size[i])] = self.rise_size[i]
|
||||
np.save(os.path.join(self.base_path, self.folder, 'analysis', 'rise_idx.npy'), rise_idxs_s[::saveorder])
|
||||
np.save(os.path.join(self.base_path, self.folder, 'analysis', 'rise_size.npy'), rise_size_s[::saveorder])
|
||||
|
||||
@property
|
||||
def isValid(self):
|
||||
return self._isValid
|
||||
|
||||
@isValid.setter
|
||||
def isValid(self, value):
|
||||
print('Trial (%s) is valid' % (self.folder))
|
||||
self._isValid = value
|
||||
|
||||
def frame_to_idx(self, event_frames):
|
||||
self.sr = 20000
|
||||
LED_idx = pd.read_csv(os.path.join(self.folder, 'led_idxs.csv'), sep=',')
|
||||
|
||||
led_idx = np.array(LED_idx).T[0]
|
||||
led_frame = np.load(os.path.join(self.folder, 'LED_frames.npy'))
|
||||
|
||||
led_idx_span = led_idx[-1] - led_idx[0]
|
||||
led_frame_span = led_frame[-1] - led_frame[0]
|
||||
|
||||
frames_to_idx = ((event_frames - led_frame[0]) / led_frame_span) * led_idx_span + led_idx[0]
|
||||
|
||||
event_times = frames_to_idx / self.sr
|
||||
|
||||
return event_times
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Evaluated electrode array recordings with multiple fish.')
|
||||
parser.add_argument('-f', type=str, help='single recording analysis', default='')
|
||||
# parser.add_argument("-c", action="store_true", help="check if LED pos is correct")
|
||||
# parser.add_argument('-x', type=int, nargs=2, default=[1272, 1282], help='x-borders of LED detect area (in pixels)')
|
||||
# parser.add_argument('-y', type=int, nargs=2, default=[1500, 1516], help='y-borders of LED area (in pixels)')
|
||||
args = parser.parse_args()
|
||||
|
||||
base_path = '/home/raab/data/2022_competition'
|
||||
|
||||
if os.path.exists(os.path.join(base_path, 'meta.csv')):
|
||||
meta = pd.read_csv(os.path.join(base_path, 'meta.csv'), sep=',', index_col=0)
|
||||
else:
|
||||
meta = None
|
||||
|
||||
if args.f == '':
|
||||
folders = os.listdir(base_path)
|
||||
folders = [x for x in folders if not '.' in x]
|
||||
else:
|
||||
folders= [os.path.split(os.path.normpath(args.f))[-1]]
|
||||
|
||||
trials = []
|
||||
for folder in folders:
|
||||
trial = Trial(folder, base_path, meta, fish_count=2)
|
||||
if not trial.isValid:
|
||||
continue
|
||||
|
||||
trial.reshape_and_interpolate()
|
||||
trial.winner_detection()
|
||||
trial.baseline_freq(bw=300)
|
||||
|
||||
# ToDo: q10 corrected EODfs
|
||||
|
||||
trial.rise_detection(rise_th=5)
|
||||
|
||||
if meta is not None:
|
||||
trial.update_meta()
|
||||
|
||||
trial.save()
|
||||
trial.ilustrate()
|
||||
trials.append(trial)
|
||||
|
||||
# meta.loc[folder, 'Fish1_ID'] = 1
|
||||
# meta.to_csv('')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue
Block a user