Interactive Example - Error Matrix

Interactive Example - Error Matrix#

from ipywidgets import interactive
import ipywidgets as widgets
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from math import degrees
def draw_ellipses(theta, sigma_x, sigma_y):
    fig, ax = plt.subplots(figsize=(10, 10))

    # Parameter
    t = np.linspace(0, 2*np.pi, 100)
    
    # Ellipse one
    ellipse = np.array([sigma_x*np.cos(t), sigma_y*np.sin(t)])
    x, y = ellipse
    ax.plot(x, y, color='b')

    # Draw first rectangle
    rectangle = Rectangle((-sigma_x, -sigma_y), 2*sigma_x, 2*sigma_y, color='b', fill=False)
    ax.add_patch(rectangle)

    # Ellipse two
    rot = np.array([[np.cos(theta) , -np.sin(theta)],[np.sin(theta) , np.cos(theta)]])
    ellipse_rot = np.dot(rot, ellipse)
    x_rot, y_rot = ellipse_rot
    ax.plot(x_rot, y_rot, color='r')

    # Draw second rectangle
    inverse_error_matrix = np.array([[1/sigma_x**2, 0], [0, 1/sigma_y**2]])
    inverse_error_matrix_rot = np.dot(np.linalg.inv(rot), np.dot(inverse_error_matrix, rot))
    error_matrix_rot = np.linalg.inv(inverse_error_matrix_rot)
    x_rectangle_rot = np.sqrt(error_matrix_rot[0, 0])
    y_rectangle_rot = np.sqrt(error_matrix_rot[1, 1])
    rectangle_rot = Rectangle((-x_rectangle_rot, -y_rectangle_rot), 2*x_rectangle_rot, 2*y_rectangle_rot, color='r', fill=False)
    ax.add_patch(rectangle_rot)

    # Draw axes
    smpl = np.linspace(-0.55, 0.55, 100)
    ax.plot(smpl, np.zeros(len(smpl)), color='k', alpha=0.6)
    ax.plot(np.zeros(len(smpl)), smpl, color='k', alpha=0.6)

    # Draw annotations
    ax.annotate(f'$\sigma_x = {sigma_x}$', xy=(sigma_x, 0), color='b', fontsize=16)
    ax.annotate(f'$\sigma_y = {sigma_y}$', xy=(0, sigma_y), color='b', fontsize=16)
    ax.annotate('$\sigma_x\prime = {:.2f}$'.format(x_rectangle_rot), xy=(x_rectangle_rot, 0), color='r', fontsize=16)
    ax.annotate('$\sigma_y\prime = {:.2f}$'.format(y_rectangle_rot), xy=(0, y_rectangle_rot), color='r', fontsize=16)

    # Decorate
    min = -0.55
    max = 0.55
    major_tickes = np.arange(min, max, 0.1)
    minor_tickes = np.arange(min, max, 0.01)
    ax.set_xticks(major_tickes)
    ax.set_xticks(minor_tickes, minor=True)
    ax.set_yticks(major_tickes)
    ax.set_yticks(minor_tickes, minor=True)
    ax.grid(True, alpha=0.2, which="both")
    ax.set_xlim(min, max)
    ax.set_ylim(min, max)

    plt.show();
slider_plots = interactive(
    draw_ellipses,
    theta = widgets.FloatSlider(
        value=np.pi/4,
        min=0,
        max=2*np.pi,
        step=0.01,
        description='theta',
    ),
    sigma_x = widgets.FloatSlider(
        value=0.25,
        min=0.1,
        max=0.5,
        step=0.01,
        description='sigma_x',
    ),
    sigma_y = widgets.FloatSlider(
        value=0.5,
        min=0.1,
        max=0.5,
        step=0.01,
        description='sigma_y',
    )
)
display(slider_plots)