From a70ba5003779a1fedd3331a65f813987eedbcf57 Mon Sep 17 00:00:00 2001
From: tillraab <till.raab@student.uni-tuebingen.de>
Date: Thu, 2 Jun 2022 13:51:21 +0200
Subject: [PATCH] all files for init commit added

---
 LED_detect.py     |  81 +++++++++++++++
 README.md         |  53 ++++++++++
 eval_LED.py       |  59 +++++++++++
 event_videos.py   | 110 ++++++++++++++++++++
 trail_analysis.py | 260 ++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 563 insertions(+)
 create mode 100644 LED_detect.py
 create mode 100644 README.md
 create mode 100644 eval_LED.py
 create mode 100644 event_videos.py
 create mode 100644 trail_analysis.py

diff --git a/LED_detect.py b/LED_detect.py
new file mode 100644
index 0000000..9d16ed1
--- /dev/null
+++ b/LED_detect.py
@@ -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)
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ded59c5
--- /dev/null
+++ b/README.md
@@ -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.
\ No newline at end of file
diff --git a/eval_LED.py b/eval_LED.py
new file mode 100644
index 0000000..e990a3a
--- /dev/null
+++ b/eval_LED.py
@@ -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])
\ No newline at end of file
diff --git a/event_videos.py b/event_videos.py
new file mode 100644
index 0000000..1466e03
--- /dev/null
+++ b/event_videos.py
@@ -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)
\ No newline at end of file
diff --git a/trail_analysis.py b/trail_analysis.py
new file mode 100644
index 0000000..5438d0f
--- /dev/null
+++ b/trail_analysis.py
@@ -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()
\ No newline at end of file