From ff8c270c3fdbb05ca6e9692850990c05ada5c5e0 Mon Sep 17 00:00:00 2001 From: wendtalexander Date: Tue, 17 Jan 2023 10:08:21 +0100 Subject: [PATCH 01/13] key problems --- code/behavior.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/code/behavior.py b/code/behavior.py index da02838..4a4b2e9 100644 --- a/code/behavior.py +++ b/code/behavior.py @@ -30,12 +30,16 @@ class Behavior: self.dataframe = read_csv(csv_file, delimiter=',') for key in self.dataframe: if ' ' in key: - new_key = key.replace(' ', '_') - if '(' in new_key: - new_key = new_key.replace('(', '') - new_key = new_key.replace(')', '') - new_key = new_key.lower() - setattr(self, new_key, np.array(self.dataframe[key])) + key = key.replace(' ', '_') + if '(' in key: + key = key.replace('(', '') + key = key.replace(')', '') + key = key.lower() + setattr(self, key, np.array(self.dataframe[key])) + + embed() + + """ 1 - chasing onset From 0a9e1b1fb22eec65decc6258bb8ac7b4a9e5112a Mon Sep 17 00:00:00 2001 From: wendtalexander Date: Tue, 17 Jan 2023 21:29:46 +0100 Subject: [PATCH 02/13] adding shifts in behaviour data --- code/behavior.py | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/code/behavior.py b/code/behavior.py index 4a4b2e9..eeeaa2d 100644 --- a/code/behavior.py +++ b/code/behavior.py @@ -1,4 +1,4 @@ -from pathlib import Path +import os import numpy as np from IPython import embed @@ -25,20 +25,27 @@ class Behavior: total_length: """ - def __init__(self, datapath: str) -> None: - csv_file = str(sorted(Path(datapath).glob('**/*.csv'))[0]) - self.dataframe = read_csv(csv_file, delimiter=',') - for key in self.dataframe: + def __init__(self, folder_path: str) -> None: + self.file = os.path.join(datapath, "traces-grid1.raw") + + LED_on_time_BORIS = np.load(os.path.join(folder_path, 'LED_on_time.npy'), allow_pickle=True) + self.time = np.load(datapath + "times.npy", allow_pickle=True) + self.dataframe = read_csv(os.path.join(folder_path, self.file[1:-7] + '.csv')) + 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(')', '') - key = key.lower() - setattr(self, key, np.array(self.dataframe[key])) - - embed() - + 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 + self.shift = last_LED_t_BORIS - real_time_range * factor + self.start_s = (self.start_s - self.shift) / factor + self.stop_s = (self.stop_s - self.shift) / factor + """ From da153f36e97495fcbc7dedb9796d4bde961a1ec2 Mon Sep 17 00:00:00 2001 From: wendtalexander Date: Wed, 18 Jan 2023 18:02:12 +0100 Subject: [PATCH 03/13] adding comments --- code/behavior.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/behavior.py b/code/behavior.py index eeeaa2d..28e7cce 100644 --- a/code/behavior.py +++ b/code/behavior.py @@ -11,6 +11,7 @@ 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: @@ -20,8 +21,8 @@ class Behavior: media_file: observation_date: observation_id: - start_s: - stop_s: + start_s: start time of the event in seconds + stop_s: stop time of the event in seconds total_length: """ From ef0c92bb611e6b870762724bf8cecf23963d1a76 Mon Sep 17 00:00:00 2001 From: wendtalexander Date: Thu, 19 Jan 2023 10:52:02 +0100 Subject: [PATCH 04/13] changing plotstyle --- code/modules/plotstyle.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/plotstyle.py b/code/modules/plotstyle.py index 9e382a7..79886dc 100644 --- a/code/modules/plotstyle.py +++ b/code/modules/plotstyle.py @@ -231,8 +231,8 @@ def PlotStyle() -> None: plt.rcParams["legend.fancybox"] = False # specify the custom font to use - plt.rcParams["font.family"] = "sans-serif" - plt.rcParams["font.sans-serif"] = "Helvetica Now Text" + #plt.rcParams["font.family"] = "sans-serif" + #plt.rcParams["font.sans-serif"] = "Helvetica Now Text" # dark mode modifications plt.rcParams["boxplot.flierprops.color"] = white From 90c6a15433a6b3ad3f14780433af0b54f03fd809 Mon Sep 17 00:00:00 2001 From: wendtalexander Date: Thu, 19 Jan 2023 15:13:30 +0100 Subject: [PATCH 05/13] tryingen to get behaviour data --- code/behavior.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/behavior.py b/code/behavior.py index 28e7cce..f4c5246 100644 --- a/code/behavior.py +++ b/code/behavior.py @@ -32,6 +32,7 @@ class Behavior: LED_on_time_BORIS = np.load(os.path.join(folder_path, 'LED_on_time.npy'), allow_pickle=True) self.time = np.load(datapath + "times.npy", allow_pickle=True) self.dataframe = read_csv(os.path.join(folder_path, self.file[1:-7] + '.csv')) + for k, key in enumerate(self.dataframe.keys()): key = key.lower() if ' ' in key: @@ -83,5 +84,5 @@ def main(datapath: str): if __name__ == '__main__': # Path to the data - datapath = '../data/mount_data/2020-03-13-10_00/' + datapath = '../data/mount_data/2020-05-13-10_00/' main(datapath) From 8d790ad89c4fd12b64c99d3a9e68bc26adc448e5 Mon Sep 17 00:00:00 2001 From: wendtalexander Date: Thu, 19 Jan 2023 15:56:42 +0100 Subject: [PATCH 06/13] adding behaviour plot --- code/behavior.py | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/code/behavior.py b/code/behavior.py index f4c5246..57362e2 100644 --- a/code/behavior.py +++ b/code/behavior.py @@ -3,6 +3,7 @@ import os import numpy as np from IPython import embed from pandas import read_csv +import matplotlib.pyplot as plt @@ -27,12 +28,15 @@ class Behavior: """ def __init__(self, folder_path: str) -> None: - self.file = os.path.join(datapath, "traces-grid1.raw") + LED_on_time_BORIS = np.load(os.path.join(folder_path, 'LED_on_time.npy'), allow_pickle=True) - self.time = np.load(datapath + "times.npy", allow_pickle=True) - self.dataframe = read_csv(os.path.join(folder_path, self.file[1:-7] + '.csv')) - + 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, 'chirps_ids.npy'), allow_pickle=True) + for k, key in enumerate(self.dataframe.keys()): key = key.lower() if ' ' in key: @@ -41,12 +45,13 @@ class Behavior: 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 - self.shift = last_LED_t_BORIS - real_time_range * factor - self.start_s = (self.start_s - self.shift) / factor - self.stop_s = (self.stop_s - self.shift) / factor + 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 @@ -79,7 +84,17 @@ temporal encpding needs to be corrected ... not exactly 25FPS. def main(datapath: str): # behabvior is pandas dataframe with all the data - behavior = Behavior(datapath) + bh = Behavior(datapath) + + + fig, ax = plt.subplots() + ax.plot(bh.chirps, np.ones_like(bh.chirps), marker='o') + ax.plot(bh.start_s, np.ones_like(bh.start_s)*2, marker='*') + plt.show() + + + embed() + exit() if __name__ == '__main__': From 9bc13294d8ece6c3c5d7458c0a7a3b87a454ef3d Mon Sep 17 00:00:00 2001 From: sprause Date: Thu, 19 Jan 2023 16:14:00 +0100 Subject: [PATCH 07/13] sort chirps and chirp ids in time --- code/behavior.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/code/behavior.py b/code/behavior.py index 57362e2..e6aad6a 100644 --- a/code/behavior.py +++ b/code/behavior.py @@ -53,8 +53,6 @@ class Behavior: self.start_s = (self.start_s - shift) / factor self.stop_s = (self.stop_s - shift) / factor - - """ 1 - chasing onset 2 - chasing offset @@ -83,9 +81,14 @@ temporal encpding needs to be corrected ... not exactly 25FPS. """ def main(datapath: str): - # behabvior is pandas dataframe with all the data + + # behavior is pandas dataframe with all the data bh = Behavior(datapath) + # chirps are not sorted in time (presumably due to prior groupings) + # sort chirps and corresponding fish_ids of the chirps + bh.chirps = bh.chirps[np.argsort(bh.chirps)] + bh.chirps_ids = bh.chirps_ids[np.argsort(bh.chirps)] fig, ax = plt.subplots() ax.plot(bh.chirps, np.ones_like(bh.chirps), marker='o') From 7bf39da31cee7a54bd267b72441ef7a19af8e67f Mon Sep 17 00:00:00 2001 From: sprause Date: Thu, 19 Jan 2023 17:30:04 +0100 Subject: [PATCH 08/13] added To Dos --- code/behavior.py | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/code/behavior.py b/code/behavior.py index e6aad6a..3a646bf 100644 --- a/code/behavior.py +++ b/code/behavior.py @@ -86,16 +86,31 @@ def main(datapath: str): bh = Behavior(datapath) # chirps are not sorted in time (presumably due to prior groupings) - # sort chirps and corresponding fish_ids of the chirps - bh.chirps = bh.chirps[np.argsort(bh.chirps)] - bh.chirps_ids = bh.chirps_ids[np.argsort(bh.chirps)] - + # get and sort chirps and corresponding fish_ids of the chirps + chirps = bh.chirps[np.argsort(bh.chirps)] + chirps_ids = bh.chirps_ids[np.argsort(bh.chirps)] + category = bh.behavior + timestamps = bh.start_s + + # split categories + chasing_onset = timestamps[category == 0] + chasing_offset = timestamps[category == 1] + physical_contact = timestamps[category == 2] + + # 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 fig, ax = plt.subplots() - ax.plot(bh.chirps, np.ones_like(bh.chirps), marker='o') - ax.plot(bh.start_s, np.ones_like(bh.start_s)*2, marker='*') + ax.scatter(chirps, np.ones_like(chirps), marker='*', color='royalblue', label='Chirps') + ax.scatter(chasing_onset, np.ones_like(chasing_onset)*2, marker='.', color='forestgreen', label='Chasing onset') + ax.scatter(chasing_offset, np.ones_like(chasing_offset)*2.5, marker='.', color='firebrick', label='Chasing offset') + ax.scatter(physical_contact, np.ones_like(physical_contact)*3, marker='x', color='black', label='Physical contact') + plt.legend() plt.show() - - + embed() exit() From f89225c66afaf312227768b3262d15849a22fd0b Mon Sep 17 00:00:00 2001 From: sprause Date: Fri, 20 Jan 2023 11:40:21 +0100 Subject: [PATCH 09/13] Check for wrong double events --- code/behavior.py | 83 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 9 deletions(-) diff --git a/code/behavior.py b/code/behavior.py index 3a646bf..ebb262d 100644 --- a/code/behavior.py +++ b/code/behavior.py @@ -1,10 +1,10 @@ import os import numpy as np -from IPython import embed -from pandas import read_csv import matplotlib.pyplot as plt +from IPython import embed +from pandas import read_csv @@ -80,6 +80,47 @@ temporal encpding needs to be corrected ... not exactly 25FPS. 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] + + # 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) + longer_array = onset_ids + shorter_array = offset_ids + elif len(onset_ids) < len(offset_ids): + len_diff = len(offset_ids) - len(onset_ids) + longer_array = offset_ids + shorter_array = onset_ids + elif len(onset_ids) == len(offset_ids): + + print('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): + if (shorter_array[i] > longer_array[i]) & (shorter_array[i] < longer_array[i+1]): + pass + else: + wrong_ids.append(longer_array[i]) + longer_array = np.delete(longer_array, i) + + category = np.delete( + category, wrong_ids) + timestamps = np.delete( + timestamps, wrong_ids) + return category, timestamps + + def main(datapath: str): # behavior is pandas dataframe with all the data @@ -92,24 +133,48 @@ def main(datapath: str): category = bh.behavior timestamps = bh.start_s + # Correct for + category, timestamps = correct_chasing_events(category, timestamps) + # split categories chasing_onset = timestamps[category == 0] chasing_offset = timestamps[category == 1] physical_contact = timestamps[category == 2] - # Physical contact-triggered chirps (PTC) mit Rasterplot + ##### 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 - fig, ax = plt.subplots() - ax.scatter(chirps, np.ones_like(chirps), marker='*', color='royalblue', label='Chirps') - ax.scatter(chasing_onset, np.ones_like(chasing_onset)*2, marker='.', color='forestgreen', label='Chasing onset') - ax.scatter(chasing_offset, np.ones_like(chasing_offset)*2.5, marker='.', color='firebrick', label='Chasing offset') - ax.scatter(physical_contact, np.ones_like(physical_contact)*3, marker='x', color='black', label='Physical contact') + fig1, ax1 = plt.subplots() + ax1.scatter(chirps, np.ones_like(chirps), marker='*', color='royalblue', label='Chirps') + ax1.scatter(chasing_onset, np.ones_like(chasing_onset)*2, marker='.', color='forestgreen', label='Chasing onset') + ax1.scatter(chasing_offset, np.ones_like(chasing_offset)*2.5, marker='.', color='firebrick', label='Chasing offset') + ax1.scatter(physical_contact, np.ones_like(physical_contact)*3, marker='x', color='black', label='Physical contact') plt.legend() - plt.show() + # plt.show() + + # Get fish ids + all_fish_ids = np.unique(chirps_ids) + + # Associate chirps to inidividual fish + fish1 = chirps[chirps_ids == all_fish_ids[0]] + fish2 = chirps[chirps_ids == all_fish_ids[1]] + fish = [len(fish1), len(fish2)] + + #### Chirp counts per fish general ##### + fig2, ax2 = plt.subplots() + x = ['Fish1', 'Fish2'] + width = 0.35 + ax2.bar(x, fish, width=width) + ax2.set_ylabel('Chirp count') + # plt.show() + + ##### Count chirps emitted during chasing events and chirps emitted out of chasing events ##### + + # Check if on- and offset are equal in length to get the right on-/offset pairs + # Get rid of tracking faults (two onsets or two offsets after another) embed() exit() From 2da26f9702eff25a5781dcc021be83f3f41d2c13 Mon Sep 17 00:00:00 2001 From: sprause Date: Fri, 20 Jan 2023 13:41:08 +0100 Subject: [PATCH 10/13] started trying the chirps in chasing part --- code/behavior.py | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/code/behavior.py b/code/behavior.py index ebb262d..27123e5 100644 --- a/code/behavior.py +++ b/code/behavior.py @@ -5,8 +5,9 @@ import matplotlib.pyplot as plt 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 @@ -95,19 +96,20 @@ def correct_chasing_events( len_diff = len(onset_ids) - len(offset_ids) longer_array = onset_ids shorter_array = 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) longer_array = offset_ids shorter_array = onset_ids + logger.info(f'Offsets are greater than offsets by {len_diff}') elif len(onset_ids) == len(offset_ids): - - print('Chasing events are equal') + 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): + for i in range(len(longer_array)-(len_diff+1)): if (shorter_array[i] > longer_array[i]) & (shorter_array[i] < longer_array[i+1]): pass else: @@ -129,11 +131,12 @@ def main(datapath: str): # chirps are not sorted in time (presumably due to prior groupings) # get and sort chirps and corresponding fish_ids of the chirps chirps = bh.chirps[np.argsort(bh.chirps)] - chirps_ids = bh.chirps_ids[np.argsort(bh.chirps)] + chirps_fish_ids = bh.chirps_ids[np.argsort(bh.chirps)] category = bh.behavior timestamps = bh.start_s - # Correct for + # 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 @@ -156,11 +159,11 @@ def main(datapath: str): # plt.show() # Get fish ids - all_fish_ids = np.unique(chirps_ids) + all_fish_ids = np.unique(chirps_fish_ids) # Associate chirps to inidividual fish - fish1 = chirps[chirps_ids == all_fish_ids[0]] - fish2 = chirps[chirps_ids == all_fish_ids[1]] + fish1 = chirps[chirps_fish_ids == all_fish_ids[0]] + fish2 = chirps[chirps_fish_ids == all_fish_ids[1]] fish = [len(fish1), len(fish2)] #### Chirp counts per fish general ##### @@ -170,14 +173,15 @@ def main(datapath: str): ax2.bar(x, fish, width=width) ax2.set_ylabel('Chirp count') # plt.show() - + embed() ##### Count chirps emitted during chasing events and chirps emitted out of chasing events ##### + chirps_in_chasing = [] + for onset, offset in zip(chasing_onset, chasing_offset): + if chirps.any((chirps > onset) & (chirps < offset)): + chirps_in_chasing.append(chirps) + print(chirps_in_chasing) + embed() - # Check if on- and offset are equal in length to get the right on-/offset pairs - # Get rid of tracking faults (two onsets or two offsets after another) - - embed() - exit() if __name__ == '__main__': From d425b8dafa69632afcc6694fd972986566f35a89 Mon Sep 17 00:00:00 2001 From: wendtalexander Date: Sat, 21 Jan 2023 10:03:57 +0100 Subject: [PATCH 11/13] adding plot with chirps in chasing --- code/behavior.py | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/code/behavior.py b/code/behavior.py index 27123e5..4b03d6e 100644 --- a/code/behavior.py +++ b/code/behavior.py @@ -157,6 +157,7 @@ def main(datapath: str): ax1.scatter(physical_contact, np.ones_like(physical_contact)*3, marker='x', color='black', label='Physical contact') plt.legend() # plt.show() + plt.close() # Get fish ids all_fish_ids = np.unique(chirps_fish_ids) @@ -173,14 +174,40 @@ def main(datapath: str): ax2.bar(x, fish, width=width) ax2.set_ylabel('Chirp count') # plt.show() - embed() + plt.close() + + ##### Count chirps emitted during chasing events and chirps emitted out of chasing events ##### - chirps_in_chasing = [] + chirps_in_chasings = [] for onset, offset in zip(chasing_onset, chasing_offset): - if chirps.any((chirps > onset) & (chirps < offset)): - chirps_in_chasing.append(chirps) - print(chirps_in_chasing) - embed() + chirps_in_chasing = [c for c in chirps if (c > onset) & (c < offset)] + chirps_in_chasings.append(chirps_in_chasing) + + # chirps out of chasing events + counts_chirps_chasings = 0 + chasings_without_chirps = 0 + for i in chirps_in_chasings: + if i: + chasings_without_chirps += 1 + else: + counts_chirps_chasings += 1 + + # chirps in chasing events + 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.close() + + # comparison between chasing events with and without chirps + + + + + + embed() + + From cd3cbf885691a2416a8fa0956744a97116179eca Mon Sep 17 00:00:00 2001 From: wendtalexander Date: Sat, 21 Jan 2023 21:29:58 +0100 Subject: [PATCH 12/13] adding unfinshed timeline plot --- code/plot_event_timeline.py | 183 ++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 code/plot_event_timeline.py diff --git a/code/plot_event_timeline.py b/code/plot_event_timeline.py new file mode 100644 index 0000000..239dcaa --- /dev/null +++ b/code/plot_event_timeline.py @@ -0,0 +1,183 @@ +import numpy as np + +import os + +import numpy as np +import matplotlib.pyplot as plt + +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) + 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, 'chirps_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 + +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] + + # 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) + longer_array = onset_ids + shorter_array = 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) + longer_array = offset_ids + shorter_array = onset_ids + logger.info(f'Offsets are greater than offsets by {len_diff}') + elif len(onset_ids) == len(offset_ids): + 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)): + if (shorter_array[i] > longer_array[i]) & (shorter_array[i] < longer_array[i+1]): + pass + else: + wrong_ids.append(longer_array[i]) + longer_array = np.delete(longer_array, i) + + category = np.delete( + category, wrong_ids) + timestamps = np.delete( + timestamps, wrong_ids) + return category, timestamps + + + +def main(datapath: str): + # behabvior is pandas dataframe with all the data + bh = Behavior(datapath) + # chirps are not sorted in time (presumably due to prior groupings) + # get and sort chirps and corresponding fish_ids of the chirps + chirps = bh.chirps[np.argsort(bh.chirps)] + chirps_fish_ids = bh.chirps_ids[np.argsort(bh.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) + + # 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(chirps_fish_ids) + # Associate chirps to inidividual fish + fish1 = (chirps[chirps_fish_ids == all_fish_ids[0]] / 60) /60 + fish2 = (chirps[chirps_fish_ids == all_fish_ids[1]] / 60) /60 + + fig, ax = plt.subplots(4, 1, figsize=(10, 5), height_ratios=[0.5, 0.5, 0.5, 6]) + # marker size + s = 200 + ax[0].scatter(physical_contact, np.ones(len(physical_contact)), color='red', marker='|', s=s) + ax[1].scatter(chasing_onset, np.ones(len(chasing_onset)), color='blue', marker='|', s=s ) + ax[1].scatter(chasing_offset, np.ones(len(chasing_offset)), color='green', marker='|', s=s) + ax[2].scatter(fish1, np.ones(len(fish1))-0.25, color='blue', marker='|', s=s) + ax[2].scatter(fish2, np.zeros(len(fish2))+0.25, color='green', marker='|', s=s) + ax[3].scatter(fish2, np.zeros(len(fish2))+0.25, color='green', marker='|', s=s) + + # Hide grid lines + ax[0].grid(False) + ax[0].set_frame_on(False) + ax[0].set_xticks([]) + ax[0].set_yticks([]) + + ax[1].grid(False) + ax[1].set_frame_on(False) + ax[1].set_xticks([]) + ax[1].set_yticks([]) + + ax[2].grid(False) + ax[2].set_frame_on(False) + ax[2].set_yticks([]) + ax[2].set_xticks([]) + + ax[3].axvspan(0, 3, 0, 5, facecolor='grey', alpha=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]') + + plt.show() + + # plot chirps + + + """ + for track_id in np.unique(ident): + # window_index for time array in time window + window_index = np.arange(len(idx))[(ident == track_id) & + (time[idx] >= t0) & + (time[idx] <= (t0+dt))] + freq_temp = freq[window_index] + time_temp = time[idx[window_index]] + #mean_freq = np.mean(freq_temp) + #fdata = bandpass_filter(data_oi[:, track_id], data.samplerate, mean_freq-5, mean_freq+200) + ax.plot(time_temp - t0, freq_temp) + """ + +if __name__ == '__main__': + # Path to the data + datapath = '../data/mount_data/2020-05-13-10_00/' + main(datapath) From da3d7b83a4a10116bbf63dfff2727c0d9594da69 Mon Sep 17 00:00:00 2001 From: wendtalexander Date: Sat, 21 Jan 2023 21:31:41 +0100 Subject: [PATCH 13/13] removing, wrong branch --- code/plot_event_timeline.py | 183 ------------------------------------ 1 file changed, 183 deletions(-) delete mode 100644 code/plot_event_timeline.py diff --git a/code/plot_event_timeline.py b/code/plot_event_timeline.py deleted file mode 100644 index 239dcaa..0000000 --- a/code/plot_event_timeline.py +++ /dev/null @@ -1,183 +0,0 @@ -import numpy as np - -import os - -import numpy as np -import matplotlib.pyplot as plt - -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) - 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, 'chirps_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 - -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] - - # 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) - longer_array = onset_ids - shorter_array = 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) - longer_array = offset_ids - shorter_array = onset_ids - logger.info(f'Offsets are greater than offsets by {len_diff}') - elif len(onset_ids) == len(offset_ids): - 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)): - if (shorter_array[i] > longer_array[i]) & (shorter_array[i] < longer_array[i+1]): - pass - else: - wrong_ids.append(longer_array[i]) - longer_array = np.delete(longer_array, i) - - category = np.delete( - category, wrong_ids) - timestamps = np.delete( - timestamps, wrong_ids) - return category, timestamps - - - -def main(datapath: str): - # behabvior is pandas dataframe with all the data - bh = Behavior(datapath) - # chirps are not sorted in time (presumably due to prior groupings) - # get and sort chirps and corresponding fish_ids of the chirps - chirps = bh.chirps[np.argsort(bh.chirps)] - chirps_fish_ids = bh.chirps_ids[np.argsort(bh.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) - - # 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(chirps_fish_ids) - # Associate chirps to inidividual fish - fish1 = (chirps[chirps_fish_ids == all_fish_ids[0]] / 60) /60 - fish2 = (chirps[chirps_fish_ids == all_fish_ids[1]] / 60) /60 - - fig, ax = plt.subplots(4, 1, figsize=(10, 5), height_ratios=[0.5, 0.5, 0.5, 6]) - # marker size - s = 200 - ax[0].scatter(physical_contact, np.ones(len(physical_contact)), color='red', marker='|', s=s) - ax[1].scatter(chasing_onset, np.ones(len(chasing_onset)), color='blue', marker='|', s=s ) - ax[1].scatter(chasing_offset, np.ones(len(chasing_offset)), color='green', marker='|', s=s) - ax[2].scatter(fish1, np.ones(len(fish1))-0.25, color='blue', marker='|', s=s) - ax[2].scatter(fish2, np.zeros(len(fish2))+0.25, color='green', marker='|', s=s) - ax[3].scatter(fish2, np.zeros(len(fish2))+0.25, color='green', marker='|', s=s) - - # Hide grid lines - ax[0].grid(False) - ax[0].set_frame_on(False) - ax[0].set_xticks([]) - ax[0].set_yticks([]) - - ax[1].grid(False) - ax[1].set_frame_on(False) - ax[1].set_xticks([]) - ax[1].set_yticks([]) - - ax[2].grid(False) - ax[2].set_frame_on(False) - ax[2].set_yticks([]) - ax[2].set_xticks([]) - - ax[3].axvspan(0, 3, 0, 5, facecolor='grey', alpha=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]') - - plt.show() - - # plot chirps - - - """ - for track_id in np.unique(ident): - # window_index for time array in time window - window_index = np.arange(len(idx))[(ident == track_id) & - (time[idx] >= t0) & - (time[idx] <= (t0+dt))] - freq_temp = freq[window_index] - time_temp = time[idx[window_index]] - #mean_freq = np.mean(freq_temp) - #fdata = bandpass_filter(data_oi[:, track_id], data.samplerate, mean_freq-5, mean_freq+200) - ax.plot(time_temp - t0, freq_temp) - """ - -if __name__ == '__main__': - # Path to the data - datapath = '../data/mount_data/2020-05-13-10_00/' - main(datapath)