Source code for simba.plotting.circular_plotting

import os
from typing import Optional, Union

import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.pyplot import cm, figure

from simba.mixins.plotting_mixin import PlottingMixin
from simba.utils.printing import stdout_success
from simba.utils.read_write import read_df


[docs]class CircularPlotting(PlottingMixin): def __init__(self): PlottingMixin.__init__(self)
[docs] def diffusion_plot(self, data: np.ndarray, fps: int, degree_width: Optional[int] = 5, palette: Optional[str] = 'jet', title: Optional[str] = None, save_path: Optional[Union[str, os.PathLike]] = None) -> plt.figure: """ Create polar plot representing the within a video. .. image:: _static/img/circular_plotter.png :alt: Circular plotter :width: 450 :align: center :param np.ndarray data: 1D np.ndarray with angle in degrees with one entry per frame. :param int fps: Framerate the video was recorded in. :param int degree_width: The width of the bars in the plot. :param str palette: The polar plot palette. :param str title: Title of the plot :param Optional[Union[str, os.PathLike]] save_path: Plot save location on disk. If None, then return plt.figure polar plot. :example: >>> data = np.random.normal(loc=180, scale=99, size=5000) >>> _ = CircularPlotting().diffusion_plot(data=data, title='Mean 180 degree plot', fps=30, degree_width=5, palette='jet', save_path='/Users/simon/Desktop/envs/troubleshooting/circular_features_zebrafish/project_folder/frames/output/dispersion/20200730_AB_7dpf_850nm_0004.png') """ matplotlib.rcParams["font.size"] = 100 max_seconds = int(data.shape[0] / fps) second_bin = int(max_seconds / 5) if second_bin > 1: second_bin = 1 data_rad = [x * 2 * np.pi / 360 for x in data] angle_bin_starts = np.arange(0.0, 2 * np.pi, 2 * np.pi * (degree_width / 360)) n_length_bins = int(max_seconds / second_bin) bin_width = 2 * np.pi * (degree_width / 360) counts, bin_edges = np.histogram(data_rad, bins=angle_bin_starts) colors = self.create_single_color_lst(pallete_name=palette, increments=bin_edges.shape[0], as_rgb_ratio=True) norm_counts = counts / (fps * second_bin) bin_numbers = [np.round(norm_counts * n_length_bins / max_seconds, 0)] bin_lengths = [x / degree_width for x in bin_numbers] plt.figure().clear() plt.close() fig = figure(figsize=(8, 8)) ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], polar=True) bars = ax.bar(angle_bin_starts[:-1], bin_lengths[0], width=bin_width, bottom=0.0) ax.set_theta_zero_location("N") ax.set_theta_direction(-1) ax.set_yticklabels([]) ax.yaxis.grid(False) for cnt, (r, bar) in enumerate(zip(bin_lengths[0], bars)): bar.set_facecolor(colors[cnt]) if title is not None: plt.title(title) if save_path is not None: plt.savefig(save_path) stdout_success(msg=f"Diffusion plot {save_path} created!") return ax
[docs] def diffusion_time_bin_plot(self, data: np.ndarray, fps: int, time_bin: int, degree_width: int, palette: str, save_path: Union[str, os.PathLike]): """ Create polar plots representing angular diffusion within each N second time-bin of the video. .. image:: _static/img/cicular_time_bins.png :alt: Cicular time bins :width: 600 :align: center :param np.ndarray data: 1D np.ndarray with angle in degrees with one entry per frame. :param int fps: Framerate the video was recorded in. :param int time_bin: The length of each time bin (one plot will be created per time bin). :param int degree_width: The width of the bars in the plot. :param str palette: The polar plot palette. :param Optional[Union[str, os.PathLike]] save_path: Plot save location on disk. If None, then return plt.figure polar plot. :example: >>> data = np.random.normal(loc=180, scale=99, size=5000) >>> _ = CircularPlotting().diffusion_time_bin_plot(data=data, fps=30, degree_width=40, palette='jet', save_path='/Users/simon/Desktop/envs/troubleshooting/circular_features_zebrafish/project_folder/frames/output/dispertion_time_series/20200730_AB_7dpf_850nm_0004', time_bin=10) """ time_bin_frame_size = time_bin * fps split_data = np.array_split(data, data.shape[0] / time_bin_frame_size) if not os.path.isdir(save_path): os.makedirs(save_path) for bin_cnt, time_bin_data in enumerate(split_data): time_plot = self.diffusion_plot( data=time_bin_data, fps=fps, degree_width=degree_width, palette=palette, title=f"Time bin {bin_cnt+1}", ) fig_save_path = os.path.join(save_path, f"Time_bin_{bin_cnt+1}.png") time_plot.figure.savefig(fig_save_path) plt.figure().clear() plt.close() plt.clf() stdout_success(msg=f"Diffusion plot {save_path} created!")
# data = read_df('/Users/simon/Desktop/envs/simba/troubleshooting/zebrafish/project_folder/csv/features_extracted/test.csv', file_type='csv', usecols=[f'Fish_clockwise_angle_degrees']).values.flatten() # CircularPlotting().diffusion_plot(data=data, title='Mean 180 degree plot', fps=30, degree_width=15, palette='jet', save_path='/Users/simon/Desktop/envs/simba/troubleshooting/zebrafish/project_folder/csv/features_extracted/test.png') # # # # # #data = np.split(data, data.shape[0]) # # # # # # data = np.random.normal(loc=90, scale=99, size=5000) # # # _ = CircularPlotting().diffusion_plot(data=data, title='test', fps=30, degree_width=20, palette='jet', save_path='/Users/simon/Desktop/envs/troubleshooting/circular_features_zebrafish/project_folder/frames/output/dispersion/20200730_AB_7dpf_850nm_0004.png') # # #_ = CircularPlotting().diffusion_time_bin_plot(data=data, fps=30, degree_width=40, palette='jet', save_path='/Users/simon/Desktop/envs/troubleshooting/circular_features_zebrafish/project_folder/frames/output/dispertion_time_series/20200730_AB_7dpf_850nm_0004', time_bin=10) # # # print(np.rad2deg(circstd(np.deg2rad(data)))) # print(np.rad2deg(circmean(np.deg2rad(data)))) # # # config_path='/Users/simon/Desktop/envs/troubleshooting/circular_features_zebrafish/project_folder/project_config.ini' # save_path='/Users/simon/Desktop/envs/troubleshooting/circular_features_zebrafish/project_folder/frames/output/20200730_AB_7dpf_850nm_0002.png' # DW = 20 # MAX_SECONDS = 10 # SECOND_BIN = 1 # LAST_BIN = 2*np.pi # # length_raw = np.arange(0,MAX_SECONDS+SECOND_BIN, SECOND_BIN) # length_dict = {x: x/MAX_SECONDS for x in length_raw} # data_rad = [x*2*np.pi/360 for x in data] # angle_bin_starts = np.arange(0.0, 2*np.pi, 2*np.pi * (DW/360)) # n_length_bins = int(MAX_SECONDS/SECOND_BIN) # bin_width = 2*np.pi * (DW/360) # # # for bin_start in angle_bin_starts: # counts, bin_edges = np.histogram(data_rad, bins=angle_bin_starts) # colors = PlottingMixin().create_single_color_lst(pallete_name='jet', increments=bin_edges.shape[0], as_rgb_ratio=True) # norm_counts = counts/(30*SECOND_BIN) # bin_numbers = [np.round(norm_counts * n_length_bins/MAX_SECONDS, 0)] # bin_lengths = [x/5 for x in bin_numbers] # bin_widths = [bin_width for idx in range(0, 72)] # fig = figure(figsize=(8,8)) # ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], polar=True) # #ax.set_yticklabels([list(range(1, MAX_SECONDS))]) # bars = ax.bar(angle_bin_starts[:-1], bin_lengths[0], width=bin_width, bottom=0.0) # ax.set_theta_zero_location('N') # ax.set_theta_direction(-1) # ax.set_yticklabels([]) # #labels = [str(int(x)) + 's' for x in np.linspace(0, MAX_SECONDS, 4)] # #labels_cnt = np.linspace(0, 1, 4) # # #ax.set_rgrids(labels_cnt, labels, fontsize=16) # #lines, labels = ax.set_rgrids(labels_cnt, labels, fontsize=16) # for cnt, (r, bar) in enumerate(zip(bin_lengths[0], bars)): # bar.set_facecolor(colors[cnt]) # #bar.set_facecolor([cm.Reds(r)]) # # # # # # # # # #plt.clf() # # compass_plot = plt.subplot(1, 1, 1, projection='polar') # # compass_plot.set_theta_zero_location('N') # # bars = compass_plot.bar(data, 0.01, width=0.01, bottom=0.0) # # # # # N = 20 # # theta = np.arange(0.0, 2*np.pi, 2*np.pi/N) # # radii = 10*np.random.rand(N) # # width = np.pi/4*np.random.rand(N) # # bars = ax.bar(theta, radii, width=width, bottom=0.0) # # for r,bar in zip(radii, bars): # # bar.set_facecolor( cm.jet(r/10.)) # # bar.set_alpha(0.5) # # # # show()