import altair as alt
import numpy as np
import pandas as pdIn [1]:
Parameters:
In [2]:
x_mean, y_mean = 4, 4
sigma_X, sigma_Y = 3, 3
sigma_D = 0.5
dAverage = np.sqrt(x_mean**2 + y_mean**2)2D Gaussian function f(x, y):
In [3]:
def f_xy(x, y):
return (
1
/ (2 * np.pi * sigma_X * sigma_Y)
* np.exp(
-(
((x - x_mean) ** 2) / (2 * sigma_X**2)
+ ((y - y_mean) ** 2) / (2 * sigma_Y**2)
)
)
)Distance Gaussian f_D(d, x, y):
In [4]:
def fD(d, x, y):
return (
1
/ (np.sqrt(2 * np.pi) * sigma_D)
* np.exp(-((d - np.sqrt(x**2 + y**2)) ** 2) / (2 * sigma_D**2))
)Combined function f(x, y, d):
In [5]:
def f_xy_d(x, y, d):
return fD(d, x, y) * f_xy(x, y)Interactive plotting function: one panel for f(x, y), the other for f(x, y, d) with a circle of radius d.
In [6]:
def generate_common_components(font_size=12, domain=[-10, 10]):
axis_cfg = alt.Axis(
grid=False,
labelFont="Times",
labelFontSize=font_size,
labelFontStyle="normal",
titleFont="Times",
titleFontSize=font_size,
titleFontStyle="italic",
)
xs = np.linspace(domain[0], domain[1], 70)
X, Y = np.meshgrid(xs, xs)
step = xs[1] - xs[0]
df_grid = pd.DataFrame(
{
"x": X.ravel(),
"y": Y.ravel(),
"x2": (X + step).ravel(),
"y2": (Y + step).ravel(),
"center_x": (X + step / 2).ravel(),
"center_y": (Y + step / 2).ravel(),
"value_uncond": f_xy(X, Y).ravel(),
}
)
d_slider = alt.param(
"d",
bind=alt.binding_range(
min=float(dAverage - 2), max=float(dAverage + 2), step=0.1, name="𝑑"
),
value=float(dAverage),
)
encode_x = alt.X("x:Q", title="x", scale=alt.Scale(domain=domain), axis=axis_cfg)
encode_y = alt.Y("y:Q", title="y", scale=alt.Scale(domain=domain), axis=axis_cfg)
return {
"axis_cfg": axis_cfg,
"df_grid": df_grid,
"d_slider": d_slider,
"encode_x": encode_x,
"encode_y": encode_y,
}
def plot_unconditional(components):
chart = (
alt.Chart(components["df_grid"])
.mark_rect()
.encode(
x=components["encode_x"],
x2="x2:Q",
y=components["encode_y"],
y2="y2:Q",
color=alt.Color("value_uncond:Q", legend=None),
)
.properties(width=300, height=300)
)
return chart
def plot_conditional(components):
expr = (
"datum.value_uncond / (sqrt(2 * PI) * {sd}) * "
"exp(- (pow(d - sqrt(pow(datum.center_x, 2) + pow(datum.center_y, 2)), 2)) / (2 * {sd} * {sd}))"
).format(sd=sigma_D)
density_chart = (
alt.Chart(components["df_grid"])
.transform_calculate(value_cond=expr)
.mark_rect()
.encode(
x=components["encode_x"],
x2="x2:Q",
y=components["encode_y"],
y2="y2:Q",
color=alt.Color("value_cond:Q", legend=None),
)
.properties(width=300, height=300)
.add_params(components["d_slider"])
)
theta = np.linspace(0, 2 * np.pi, 100)
circle_df = pd.DataFrame({"theta": theta, "x": np.cos(theta), "y": np.sin(theta)})
circle = (
alt.Chart(circle_df)
.transform_calculate(
x_scaled="datum.x * d",
y_scaled="datum.y * d",
)
.mark_line(color="gray", strokeWidth=1)
.encode(
x=alt.X(
"x_scaled:Q",
scale=alt.Scale(domain=[-10, 10]),
axis=components["axis_cfg"],
),
y=alt.Y(
"y_scaled:Q",
scale=alt.Scale(domain=[-10, 10]),
axis=components["axis_cfg"],
),
order=alt.Order("theta:Q"),
)
.add_params(components["d_slider"])
)
return density_chart + circleCreate the interactive slider for d
In [7]:
components = generate_common_components(font_size=12)In [11]:
plot_unconditional(components)In [12]:
plot_conditional(components)