From c070192996dc95176a6241ec911facb663231509 Mon Sep 17 00:00:00 2001 From: wendtalexander Date: Tue, 24 Jan 2023 23:16:36 +0100 Subject: [PATCH] making things worse --- code/plot_chirp_bodylegth.py | 274 +++++++++++++++++++--------- poster/figs/chirps_winner_loser.pdf | Bin 15532 -> 16954 bytes 2 files changed, 191 insertions(+), 83 deletions(-) diff --git a/code/plot_chirp_bodylegth.py b/code/plot_chirp_bodylegth.py index 6d5c782..3c34953 100644 --- a/code/plot_chirp_bodylegth.py +++ b/code/plot_chirp_bodylegth.py @@ -17,11 +17,106 @@ ps = PlotStyle() logger = makeLogger(__name__) +def get_chirp_winner_loser(folder_name, Behavior, order_meta_df): + + foldername = folder_name.split('/')[-2] + winner_row = order_meta_df[order_meta_df['recording'] == foldername] + 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) + + if winner > 0: + if winner == winner_fish1: + winner_fish_id = winner_row['rec_id1'].values[0] + loser_fish_id = winner_row['rec_id2'].values[0] + + elif winner == winner_fish2: + winner_fish_id = winner_row['rec_id2'].values[0] + loser_fish_id = winner_row['rec_id1'].values[0] + + chirp_winner = len( + Behavior.chirps[Behavior.chirps_ids == winner_fish_id]) + chirp_loser = len( + Behavior.chirps[Behavior.chirps_ids == loser_fish_id]) + + return chirp_winner, chirp_loser + else: + return np.nan, np.nan + + +def get_chirp_size(folder_name, Behavior, order_meta_df, id_meta_df): + + foldername = folder_name.split('/')[-2] + folder_row = order_meta_df[order_meta_df['recording'] == foldername] + fish1 = folder_row['fish1'].values[0].astype(int) + fish2 = folder_row['fish2'].values[0].astype(int) + + groub = folder_row['group'].values[0].astype(int) + size_fish1_row = id_meta_df[(id_meta_df['group'] == groub) & ( + id_meta_df['fish'] == fish1)] + size_fish2_row = id_meta_df[(id_meta_df['group'] == groub) & ( + id_meta_df['fish'] == fish2)] + + size_winners = [size_fish1_row[col].values[0] + for col in ['l1', 'l2', 'l3']] + mean_size_winner = np.nanmean(size_winners) + + size_losers = [size_fish2_row[col].values[0] for col in ['l1', 'l2', 'l3']] + mean_size_loser = np.nanmean(size_losers) + + if mean_size_winner > mean_size_loser: + size_diff = mean_size_winner - mean_size_loser + winner_fish_id = folder_row['rec_id1'].values[0] + loser_fish_id = folder_row['rec_id2'].values[0] + + elif mean_size_winner < mean_size_loser: + size_diff = mean_size_loser - mean_size_winner + winner_fish_id = folder_row['rec_id2'].values[0] + loser_fish_id = folder_row['rec_id1'].values[0] + + else: + size_diff = np.nan + winner_fish_id = np.nan + loser_fish_id = np.nan + + chirp_diff = len(Behavior.chirps[Behavior.chirps_ids == winner_fish_id]) - len( + Behavior.chirps[Behavior.chirps_ids == loser_fish_id]) + + return size_diff, chirp_diff + + +def get_chirp_freq(folder_name, Behavior, order_meta_df): + + foldername = folder_name.split('/')[-2] + folder_row = order_meta_df[order_meta_df['recording'] == foldername] + fish1 = folder_row['rec_id1'].values[0].astype(int) + fish2 = folder_row['rec_id2'].values[0].astype(int) + chirp_freq_fish1 = np.nanmedian( + Behavior.freq[Behavior.ident == fish1]) + chirp_freq_fish2 = np.nanmedian( + Behavior.freq[Behavior.ident == fish2]) + + if chirp_freq_fish1 > chirp_freq_fish2: + freq_diff = chirp_freq_fish1 - chirp_freq_fish2 + winner_fish_id = folder_row['rec_id1'].values[0] + loser_fish_id = folder_row['rec_id2'].values[0] + + elif chirp_freq_fish1 < chirp_freq_fish2: + freq_diff = chirp_freq_fish2 - chirp_freq_fish1 + winner_fish_id = folder_row['rec_id2'].values[0] + loser_fish_id = folder_row['rec_id1'].values[0] + + chirp_diff = len(Behavior.chirps[Behavior.chirps_ids == winner_fish_id]) - len( + Behavior.chirps[Behavior.chirps_ids == loser_fish_id]) + + return freq_diff, chirp_diff + + def main(datapath: str): foldernames = [ datapath + x + '/' for x in os.listdir(datapath) if os.path.isdir(datapath+x)] - path_order_meta = ( + 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] @@ -30,11 +125,11 @@ def main(datapath: str): id_meta_df = read_csv(path_id_meta) chirps_winner = [] - size_diff = [] - chirps_diff = [] + size_diffs = [] + size_chirps_diffs = [] chirps_loser = [] - freq_diff = [] - + freq_diffs = [] + freq_chirps_diffs = [] for foldername in foldernames: # behabvior is pandas dataframe with all the data @@ -49,89 +144,102 @@ def main(datapath: str): # 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)) + winner_chirp, loser_chirp = get_chirp_winner_loser( + foldername, bh, order_meta_df) + chirps_winner.append(winner_chirp) + chirps_loser.append(loser_chirp) + size_diff, chirp_diff = get_chirp_size( + foldername, bh, order_meta_df, id_meta_df) + size_diffs.append(size_diff) + size_chirps_diffs.append(chirp_diff) + + freq_diff, freq_chirps_diff = get_chirp_freq( + foldername, bh, order_meta_df) + freq_diffs.append(freq_diff) + freq_chirps_diffs.append(freq_chirps_diff) + + # 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_diffs.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_diffs.append(mean_size_winner - mean_size_loser) + # else: + # pass + + # 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_diffs.append(chirp_winner - chirp_loser) + # freq_diffs.append(freq_winner - freq_loser) + + fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(10, 5)) scatterwinner = 1.15 scatterloser = 1.85 + chirps_winner = np.asarray(chirps_winner)[~np.isnan(chirps_winner)] + chirps_loser = np.asarray(chirps_loser)[~np.isnan(chirps_loser)] + bplot1 = ax1.boxplot(chirps_winner, positions=[ - 1], showfliers=False, patch_artist=True) + 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') + 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) + 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) + ax1.plot([scatterwinner, scatterloser], [w, l], + color='r', alpha=0.5, linewidth=0.5) colors1 = ps.red ps.set_boxplot_color(bplot1, colors1) @@ -139,11 +247,11 @@ def main(datapath: str): ps.set_boxplot_color(bplot2, colors1) ax1.set_ylabel('Chirpscounts [n]') - ax2.scatter(size_diff, chirps_diff, color='r') + ax2.scatter(size_diffs, size_chirps_diffs, color='r') ax2.set_xlabel('Size difference [mm]') ax2.set_ylabel('Chirps difference [n]') - ax3.scatter(freq_diff, chirps_diff, color='r') + ax3.scatter(freq_diffs, freq_chirps_diffs, color='r') ax3.set_xlabel('Frequency difference [Hz]') ax3.set_yticklabels([]) ax3.set diff --git a/poster/figs/chirps_winner_loser.pdf b/poster/figs/chirps_winner_loser.pdf index 8bf96862670b190f871ebc67160d506701d906d3..7d8d1cda773e95dc07b9b3fc248a90d6279292cb 100644 GIT binary patch delta 5497 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 delta 4230 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 S7tuHvBH_^@B5G81^uGapB$z4y