import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import operator
from matplotlib.ticker import FuncFormatter
import seaborn as sns
current_palette = sns.color_palette()
import matplotlib.ticker as mticker
import os
import os.path as op
import sys
sys.path.append(op.dirname(op.dirname(op.dirname(op.abspath("__file__")))))
from pycircular.utils import date2rad
from pycircular.stats import periodic_mean_std, von_mises_distribution
from pycircular.stats import kuiper_two
fig_adjustment = {'hour': 2*np.pi/30, 'dayweek': -2*np.pi/8, 'daymonth': -2*np.pi/35}
[docs]def plot_kernel(dates, freq, y, bottom=0, ymax=1,
rescale=True, figsize=(8, 8),
time_segment='hour', fig=None, ax1=None):
"""Figure for plotting the kernel
# TODO: finish
"""
fig, ax1 = base_periodic_fig(dates, freq, bottom=bottom, ymax=ymax,
rescale=rescale, figsize=figsize,
time_segment=time_segment, fig=fig, ax1=ax1)
if rescale:
y = y / y.max()
n = y.shape[0]
z = np.linspace(0, np.pi * 2, n)
ax1.plot(z + fig_adjustment[time_segment], y, color=current_palette[1], ls='-', linewidth=2)
ax1.fill_between(z + fig_adjustment[time_segment], 0, y, alpha=0.5, color=current_palette[1])
return fig, ax1
[docs]def base_periodic_fig(dates, freq, bottom=0, ymax=1,
rescale=True, figsize=(8, 8),
time_segment='hour', fig=None, ax1=None):
"""Base figure for plotting periodic time variables
Parameters
----------
dates : array-like of shape = [unique_n_samples] of dates in format 'datetime64[ns]'.
freq : array-like of shape = [unique_n_samples] of frequencies for each date.
# TODO: finish
time_segment: string of values ['hour', 'dayweek', 'daymonth']
Returns
-------
fig, ax : Figure and axis objects
Examples
--------
>>> import numpy as np
>>> import pandas as pd
>>> import matplotlib.pyplot as plt
>>> from pycircular.utils import freq_time, date2rad
>>> from pycircular.plots import base_periodic_fig
>>> dates = pd.to_datetime(["2013-10-02 19:10:00", "2013-10-21 19:00:00", "2013-10-24 3:00:00"])
>>> time_segment = 'dayweek' # 'hour', 'dayweek', 'daymonth
>>> freq_arr, times = freq_time(dates, time_segment=time_segment)
>>> fig, ax1 = base_periodic_fig(freq_arr[:, 0], freq_arr[:, 1], time_segment=time_segment)
"""
if rescale:
freq = freq / freq.max()
ymax = 1.
angles = date2rad(dates, time_segment)
if fig is None:
fig = plt.figure(figsize=figsize)
ax1 = plt.subplot(111, polar=True)
# Define figure parameters
width = (2*np.pi)
if time_segment == 'hour':
width /= 30
ticks_loc = ax1.get_xticks().tolist()
ax1.xaxis.set_major_locator(mticker.FixedLocator(ticks_loc))
ax1.set_xticklabels(['6h', '3h', '0h', '21h', '18h', '15h', '12h', '9h'])
angles=[i+(width/2) for i in angles]
elif time_segment == 'dayweek':
width /= 30
temp_xticks = np.linspace(np.pi/2, 2*np.pi+np.pi/2, 7, endpoint=False)
temp_xticks[-1] -= 2 * np.pi
ax1.set_xticks(temp_xticks)
ticks_loc = ax1.get_xticks().tolist()
ax1.xaxis.set_major_locator(mticker.FixedLocator(ticks_loc))
ax1.set_xticklabels(['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'])
angles=[i-(width) for i in angles]
# TO DO: check the shift amount for good visualization
# angles=[i-(width/2) for i in angles] ?
elif time_segment == 'daymonth':
width /= 31
temp_xticks = np.linspace(np.pi/2, 2*np.pi+np.pi/2, 31, endpoint=False)
temp_xticks[temp_xticks>2*np.pi] -= 2 * np.pi
ax1.set_xticks(temp_xticks)
ticks_loc = ax1.get_xticks().tolist()
ax1.xaxis.set_major_locator(mticker.FixedLocator(ticks_loc))
ax1.set_xticklabels(range(1, 32))
angles=[i-(width/2) for i in angles]
# TODO: what to do with 31
ax1.bar(angles, freq, width=width, bottom=bottom, alpha=0.5)
ax1.set_ylim([0, bottom+ymax])
ax1.set_yticklabels([])
return fig, ax1
# TODO: Inherit the properties from base_clock. Probably as a class
[docs]def clock_vonmises_distribution(ax1, mean, x, p, rescale=True):
# TODO: add description
if rescale:
p = p / p.max()
# Plot the mean
ax1.plot([mean, mean], [0, 1], c=current_palette[1], ls='--', linewidth=5)
# Plot the distribution
ax1.plot(x, p, c=current_palette[1], ls='-', linewidth=2)
ax1.fill_between(x, 0, p, alpha=0.5, color=current_palette[1])
return ax1
[docs]def plot_CDF_kernel(x, y):
"""Plot of the CDF kernel and kuiper test
Parameters
----------
x : array-like of shape = [n_samples] of radians.
y : array-like of the kernel density.
Returns
-------
fig, ax : Figure and axis objects
Examples
--------
>>> import numpy as np
>>> from pycircular.density import kernel, bwEstimation
>>> from pycircular.density_tests import kuiper_two
>>> from pycircular.plots import plot_CDF_kernel
>>> x = np.array([0.8 , 1. , 1.1 , 1.15, 4. , 4.2 , 4.3 , 4.4])
>>> bw = bwEstimation(x, upper=500)
>>> y = kernel(x, bw=2)
>>> fig, ax1 = plot_CDF_kernel(x, y)
"""
p, (z, d_cdf, k_cdf, D1_, D2_, D1, D2) = kuiper_two(x, y, return_all=True)
fig = plt.figure()
ax1 = plt.subplot(111)
ax1.plot(z, d_cdf)
ax1.plot(z, k_cdf)
ax1.plot([z[D1_], z[D1_]], [d_cdf[D1_], k_cdf[D1_]], c='r', lw=5)
ax1.plot([z[D2_], z[D2_]], [d_cdf[D2_], k_cdf[D2_]], c='r', lw=5)
return fig, ax1