import numpy as np
import matplotlib.pyplot as plt
from matplotlib import ticker
%load_ext jupyter_black
from pycircstat2.distributions import circularuniform
n = 100
x = np.linspace(0, 2 * np.pi, n)
fig, ax = plt.subplot_mosaic(
"abc",
figsize=(16, 5),
per_subplot_kw={"a": {"projection": "polar"}},
layout="constrained",
)
ax["a"].plot(
x,
circularuniform.pdf(x) + 1,
linestyle="-",
color="black",
)
rtick = [0, 1]
ax["a"].set_theta_zero_location("S")
ax["a"].spines["polar"].set_visible(False)
ax["a"].set_rgrids(rtick, ["" for _ in range(len(rtick))], fontsize=16)
gridlines = ax["a"].yaxis.get_gridlines()
gridlines[-1].set_color("k")
gridlines[-1].set_linewidth(1)
# position_major = np.arange(0, 2 * np.pi, 2 * np.pi / 4)
position_major = []
ax["a"].xaxis.set_major_locator(ticker.FixedLocator(position_major))
ax["a"].text(
x=0,
y=0,
s="+",
ha="center",
va="center",
color="black",
)
labels = ["0", "π/2", "π", "3π/2"]
for i, angle in enumerate([0, np.pi / 2, np.pi, 3 * np.pi / 2]):
ax["a"].text(x=angle, y=0.75, s=labels[i], ha="center", va="center", color="black")
ax["a"].legend(frameon=False)
ax["a"].set_title("circular uniform distribution")
ax["b"].plot(x, circularuniform.cdf(x), linestyle="-", color="black")
ax["b"].set_xlabel("θ (rad)")
ax["b"].set_ylabel("CDF")
p = np.linspace(1e-16, 1 - 1e-16, 100)
ax["c"].plot(p, circularuniform.ppf(p), linestyle="-", color="black")
ax["c"].set_xlabel("Cumulative prob.")
ax["c"].set_ylabel("Quantile (rad)")
/var/folders/2g/cw502gdd0hj9q05c6n34nkvr0000gn/T/ipykernel_11655/3684695010.py:44: UserWarning: No artists with labels found to put in legend. Note that artists whose label start with an underscore are ignored when legend() is called with no argument. ax["a"].legend(frameon=False)
Text(0, 0.5, 'Quantile (rad)')
from pycircstat2.distributions import cardioid
n = 100
x = np.linspace(0, 2 * np.pi, n)
mu = np.pi
fig, ax = plt.subplot_mosaic(
"abc",
figsize=(16, 5),
per_subplot_kw={"a": {"projection": "polar"}},
layout="constrained",
)
ax["a"].plot(
x,
cardioid.pdf(x, rho=0.0, mu=mu) + 1,
linestyle=":",
color="black",
label="ρ=0",
)
ax["a"].plot(
x,
cardioid.pdf(x, rho=0.25, mu=mu) + 1,
linestyle="-",
color="black",
label="ρ=0.25",
)
ax["a"].plot(
x, cardioid.pdf(x, rho=0.5, mu=mu) + 1, linestyle="--", color="black", label="ρ=0.5"
)
rtick = [0, 1]
ax["a"].set_theta_zero_location("S")
ax["a"].spines["polar"].set_visible(False)
ax["a"].set_rgrids(rtick, ["" for _ in range(len(rtick))], fontsize=16)
gridlines = ax["a"].yaxis.get_gridlines()
gridlines[-1].set_color("k")
gridlines[-1].set_linewidth(1)
# position_major = np.arange(0, 2 * np.pi, 2 * np.pi / 4)
position_major = []
ax["a"].xaxis.set_major_locator(ticker.FixedLocator(position_major))
ax["a"].text(
x=0,
y=0,
s="+",
ha="center",
va="center",
color="black",
)
labels = ["0", "π/2", "π", "3π/2"]
for i, angle in enumerate([0, np.pi / 2, np.pi, 3 * np.pi / 2]):
ax["a"].text(x=angle, y=0.75, s=labels[i], ha="center", va="center", color="black")
ax["a"].legend(frameon=False)
ax["a"].set_title("Cardioid distr.")
ax["b"].plot(x, cardioid.cdf(x, rho=0.25, mu=mu), linestyle="-", color="black")
ax["b"].plot(x, cardioid.cdf(x, rho=0.5, mu=mu), linestyle="--", color="black")
ax["b"].plot(x, cardioid.cdf(x, rho=0.0, mu=mu), linestyle=":", color="black")
ax["b"].set_xlabel("θ (rad)")
ax["b"].set_ylabel("CDF")
p = np.linspace(1e-16, 1 - 1e-16, 100)
ax["c"].plot(p, cardioid.ppf(p, rho=0.25, mu=mu), linestyle="-", color="black")
ax["c"].plot(p, cardioid.ppf(p, rho=0.5, mu=mu), linestyle="--", color="black")
ax["c"].plot(p, cardioid.ppf(p, rho=0.0, mu=mu), linestyle=":", color="black")
ax["c"].set_xlabel("Cumulative prob.")
ax["c"].set_ylabel("Quantile (rad)")
Text(0, 0.5, 'Quantile (rad)')
from pycircstat2.distributions import wrapnorm
n = 100
x = np.linspace(0, 2 * np.pi, n)
mu = np.pi
fig, ax = plt.subplot_mosaic(
"abc",
figsize=(16, 5),
per_subplot_kw={"a": {"projection": "polar"}},
layout="constrained",
)
ax["a"].plot(
x,
wrapnorm.pdf(x, rho=0.25, mu=mu) + 1,
linestyle="-",
color="black",
label="ρ=0.25",
)
ax["a"].plot(
x, wrapnorm.pdf(x, rho=0.5, mu=mu) + 1, linestyle="--", color="black", label="ρ=0.5"
)
ax["a"].plot(
x,
wrapnorm.pdf(x, rho=0.75, mu=mu) + 1,
linestyle=":",
color="black",
label="ρ=0.75",
)
rtick = [0, 1]
ax["a"].set_theta_zero_location("S")
ax["a"].spines["polar"].set_visible(False)
ax["a"].set_rgrids(rtick, ["" for _ in range(len(rtick))], fontsize=16)
gridlines = ax["a"].yaxis.get_gridlines()
gridlines[-1].set_color("k")
gridlines[-1].set_linewidth(1)
# position_major = np.arange(0, 2 * np.pi, 2 * np.pi / 4)
position_major = []
ax["a"].xaxis.set_major_locator(ticker.FixedLocator(position_major))
ax["a"].text(
x=0,
y=0,
s="+",
ha="center",
va="center",
color="black",
)
labels = ["0", "π/2", "π", "3π/2"]
for i, angle in enumerate([0, np.pi / 2, np.pi, 3 * np.pi / 2]):
ax["a"].text(x=angle, y=0.75, s=labels[i], ha="center", va="center", color="black")
ax["a"].legend(frameon=False)
ax["a"].set_title("wrapped Normal distr.")
ax["b"].plot(x, wrapnorm.cdf(x, rho=0.25, mu=mu), linestyle="-", color="black")
ax["b"].plot(x, wrapnorm.cdf(x, rho=0.5, mu=mu), linestyle="--", color="black")
ax["b"].plot(x, wrapnorm.cdf(x, rho=0.75, mu=mu), linestyle=":", color="black")
ax["b"].set_xlabel("θ (rad)")
ax["b"].set_ylabel("CDF")
p = np.linspace(1e-16, 1 - 1e-16, 100)
ax["c"].plot(p, wrapnorm.ppf(p, rho=0.25, mu=mu), linestyle="-", color="black")
ax["c"].plot(p, wrapnorm.ppf(p, rho=0.5, mu=mu), linestyle="--", color="black")
ax["c"].plot(p, wrapnorm.ppf(p, rho=0.75, mu=mu), linestyle=":", color="black")
ax["c"].set_xlabel("Cumulative prob.")
ax["c"].set_ylabel("Quantile (rad)")
Text(0, 0.5, 'Quantile (rad)')
from pycircstat2.distributions import wrapcauchy
n = 100
x = np.linspace(0, 2 * np.pi, n)
mu = np.pi
fig, ax = plt.subplot_mosaic(
"abc",
figsize=(16, 5),
per_subplot_kw={"a": {"projection": "polar"}},
layout="constrained",
)
ax["a"].plot(
x,
wrapcauchy.pdf(x, rho=0.25, mu=mu) + 1,
linestyle="-",
color="black",
label="ρ=0.25",
)
ax["a"].plot(
x,
wrapcauchy.pdf(x, rho=0.5, mu=mu) + 1,
linestyle="--",
color="black",
label="ρ=0.5",
)
ax["a"].plot(
x,
wrapcauchy.pdf(x, rho=0.75, mu=mu) + 1,
linestyle=":",
color="black",
label="ρ=0.75",
)
rtick = [0, 1]
ax["a"].set_theta_zero_location("S")
ax["a"].spines["polar"].set_visible(False)
ax["a"].set_rgrids(rtick, ["" for _ in range(len(rtick))], fontsize=16)
gridlines = ax["a"].yaxis.get_gridlines()
gridlines[-1].set_color("k")
gridlines[-1].set_linewidth(1)
position_major = []
ax["a"].xaxis.set_major_locator(ticker.FixedLocator(position_major))
ax["a"].text(
x=0,
y=0,
s="+",
ha="center",
va="center",
color="black",
)
labels = ["0", "π/2", "π", "3π/2"]
for i, angle in enumerate([0, np.pi / 2, np.pi, 3 * np.pi / 2]):
ax["a"].text(x=angle, y=0.75, s=labels[i], ha="center", va="center", color="black")
ax["a"].legend(frameon=False)
ax["a"].set_title("wrapped Cauchy distr.")
ax["b"].plot(x, wrapcauchy.cdf(x, rho=0.25, mu=mu), linestyle="-", color="black")
ax["b"].plot(x, wrapcauchy.cdf(x, rho=0.5, mu=mu), linestyle="--", color="black")
ax["b"].plot(x, wrapcauchy.cdf(x, rho=0.75, mu=mu), linestyle=":", color="black")
ax["b"].set_xlabel("θ (rad)")
ax["b"].set_ylabel("CDF")
p = np.linspace(1e-16, 1 - 1e-16, 100)
ax["c"].plot(p, wrapcauchy.ppf(p, rho=0.25, mu=mu), linestyle="-", color="black")
ax["c"].plot(p, wrapcauchy.ppf(p, rho=0.5, mu=mu), linestyle="--", color="black")
ax["c"].plot(p, wrapcauchy.ppf(p, rho=0.75, mu=mu), linestyle=":", color="black")
ax["c"].set_xlabel("Cumulative prob.")
ax["c"].set_ylabel("Quantile (rad)")
Text(0, 0.5, 'Quantile (rad)')
from pycircstat2.distributions import vonmises
n = 100
x = np.linspace(0, 2 * np.pi, n)
mu = np.pi
fig, ax = plt.subplot_mosaic(
"abc",
figsize=(16, 5),
per_subplot_kw={"a": {"projection": "polar"}},
layout="constrained",
)
ax["a"].plot(
x, vonmises.pdf(x, kappa=5, mu=mu) + 1, linestyle="-", color="black", label="κ=5"
)
ax["a"].plot(
x, vonmises.pdf(x, kappa=2, mu=mu) + 1, linestyle="-.", color="black", label="κ=2"
)
ax["a"].plot(
x, vonmises.pdf(x, kappa=1, mu=mu) + 1, linestyle="--", color="black", label="κ=1"
)
ax["a"].plot(
x,
vonmises.pdf(x, kappa=0.5, mu=mu) + 1,
linestyle=":",
color="black",
label="κ=0.5",
)
rtick = [0, 1]
ax["a"].set_theta_zero_location("S")
ax["a"].spines["polar"].set_visible(False)
ax["a"].set_rgrids(rtick, ["" for _ in range(len(rtick))], fontsize=16)
gridlines = ax["a"].yaxis.get_gridlines()
gridlines[-1].set_color("k")
gridlines[-1].set_linewidth(1)
position_major = []
ax["a"].xaxis.set_major_locator(ticker.FixedLocator(position_major))
ax["a"].text(
x=0,
y=0,
s="+",
ha="center",
va="center",
color="black",
)
labels = ["0", "π/2", "π", "3π/2"]
for i, angle in enumerate([0, np.pi / 2, np.pi, 3 * np.pi / 2]):
ax["a"].text(x=angle, y=0.75, s=labels[i], ha="center", va="center", color="black")
ax["a"].legend(frameon=False)
ax["a"].set_title("von Mises distr.")
ax["b"].plot(x, vonmises.cdf(x, kappa=5, mu=mu), linestyle="-", color="black")
ax["b"].plot(x, vonmises.cdf(x, kappa=2, mu=mu), linestyle="-.", color="black")
ax["b"].plot(x, vonmises.cdf(x, kappa=1, mu=mu), linestyle="--", color="black")
ax["b"].plot(x, vonmises.cdf(x, kappa=0.5, mu=mu), linestyle=":", color="black")
ax["b"].set_xlabel("θ (rad)")
ax["b"].set_ylabel("CDF")
p = np.linspace(1e-16, 1 - 1e-16, n)
ax["c"].plot(p, vonmises.ppf(p, kappa=5, mu=mu), linestyle="-", color="black")
ax["c"].plot(p, vonmises.ppf(p, kappa=2, mu=mu), linestyle="-.", color="black")
ax["c"].plot(p, vonmises.ppf(p, kappa=1, mu=mu), linestyle="--", color="black")
ax["c"].plot(p, vonmises.ppf(p, kappa=0.5, mu=mu), linestyle=":", color="black")
ax["c"].set_xlabel("Cumulative prob.")
ax["c"].set_ylabel("Quantile (rad)")
Text(0, 0.5, 'Quantile (rad)')
Circular models in pycircstat2
mainly follows the implementations described in Pewsey, et al. (2014). For more distributions (such as jonespewsey
, inverse_baschelet
and others, please see example notebook B3-Pewsey-2014).
%load_ext watermark
%watermark --time --date --timezone --updated --python --iversions --watermark -p pycircstat2
Last updated: 2024-11-29 16:32:59CET Python implementation: CPython Python version : 3.10.13 IPython version : 8.29.0 pycircstat2: 0.1.2 matplotlib: 3.9.2 numpy : 2.1.3 Watermark: 2.5.0