import plotly.express as px
import plotly.graph_objects as go
fig = px.scatter(
data_toy1, x="x1", y="x2",
color="y")
# Lines
line_coefs = np.array(
[[1, 1, -2], [-1, 0.3, 0.5], [-0.5, 0.3, -1], [0.1, -1, 1]])
frames = []
x_line = np.array([np.min(x1[:,1]), np.max(x1[:,1])])
y_range = np.array([np.min(x1[:,2]), np.max(x1[:,2])])
id_small = np.argsort(np.abs(x1[:,1]) + np.abs(x1[:,2]))[5]
point_far = np.array([x_line[0], y_range[1]])
point_near = np.array([x1[id_small,1],x1[id_small,2]])
for i, coef in enumerate(line_coefs):
y_line = (-coef[0] - coef[1] * x_line) / coef[2]
a, b = -coef[1]/coef[2], -coef[0]/coef[2]
point_proj_far = np.array([(point_far[0]+a*point_far[1]-a*b)/(a**2+1), a*(point_far[0]+a*point_far[1]-a*b)/(a**2+1)+b])
point_proj_near = np.array([(point_near[0]+a*point_near[1]-a*b)/(a**2+1), a*(point_near[0]+a*point_near[1]-a*b)/(a**2+1)+b])
p1 = np.row_stack([point_far, point_proj_far])
p2 = np.row_stack([point_near, point_proj_near])
frames.append(go.Frame(
data=[fig.data[0],
fig.data[1],
go.Scatter(
x=p1[:,0],
y=p1[:,1],
name="Far from boundary",
line=dict(dash="dash"),
visible="legendonly"
),
go.Scatter(
x=p2[:,0],
y=p2[:,1],
name="Close to boundary",
line=dict(dash="dash"),
visible="legendonly"
),
go.Scatter(
x=x_line, y=y_line, mode='lines',
line=dict(width=3, color="black"),
name=f'Line: {i+1}')],
name=f'{i+1}'))
y_line = (-line_coefs[0,0] - line_coefs[0,1] * x_line) / line_coefs[0,2]
a, b = -line_coefs[0,0]/line_coefs[0,2], - line_coefs[0,1]/line_coefs[0,2]
point_proj_far = np.array([(point_far[0]+a*point_far[1]-a*b)/(a**2+1), a*(point_far[0]+a*point_far[1]-a*b)/(a**2+1)+b])
point_proj_near = np.array([(point_near[0]+a*point_near[1]-a*b)/(a**2+1), a*(point_near[0]+a*point_near[1]-a*b)/(a**2+1)+b])
p1 = np.row_stack([point_far, point_proj_far])
p2 = np.row_stack([point_near, point_proj_near])
fig1 = go.Figure(
data=[
fig.data[0],
fig.data[1],
go.Scatter(
x=p1[:,0],
y=p1[:,1],
name="Far from boundary",
line=dict(dash="dash"),
visible="legendonly"
),
go.Scatter(
x=p2[:,0],
y=p2[:,1],
name="Close to boundary",
line=dict(dash="dash"),
visible="legendonly"
),
go.Scatter(
x=x_line, y=y_line, mode='lines',
line=dict(width=3, color="black"),
name=f'Line: 1')
],
layout=go.Layout(
title="1st simulated data & boundary lines",
xaxis=dict(title="x1", range=[-3.4, 3.4]),
yaxis=dict(title="x2", range=[-3.4, 3.4]),
updatemenus=[{
"buttons": [
{
"args": [None, {"frame": {"duration": 1000, "redraw": True}, "fromcurrent": True, "mode": "immediate"}],
"label": "Play",
"method": "animate"
},
{
"args": [[None], {"frame": {"duration": 0, "redraw": False}, "mode": "immediate"}],
"label": "Stop",
"method": "animate"
}
],
"type": "buttons",
"showactive": False,
"x": -0.1,
"y": 1.25,
"pad": {"r": 10, "t": 50}
}],
sliders=[{
"active": 0,
"currentvalue": {"prefix": "Line: "},
"pad": {"t": 50},
"steps": [{"label": f"{i}",
"method": "animate",
"args": [[f'{i}'], {"frame": {"duration": 1000, "redraw": True}, "mode": "immediate",
"transition": {"duration": 10}}]}
for i in range(1,5)]
}]
),
frames=frames
)
fig1.update_layout(height=350, width=500)
fig1.show()