🏥 🏭 Working on the COVID-19 response in Canada? Plotly & the Canadian government can help you and your organization. Learn more and get in touch.

How to draw ellipse on top of scatter plot?

I want to draw ellipse on top of my scatter plot like this ScatterEllipse03

I can do it with matplotlib but I don’t know how to do it with plotly since the shapes/draw in plotly is only have circle object with given parameter x0,y0,x1,y1 I can’t use that to draw my ellipse

what I actually need is a method like this matplotlib method https://matplotlib.org/api/_as_gen/matplotlib.patches.Ellipse.html

since the parameter is x coordinate, y coordinate, width(diameter), and height(diameter)

@mutia

This is a plotly.py question. Please change its category from Plotly.js to Plotly.py.

Here is a function that draws the ellipse as a line:

import numpy as np
from numpy import pi, sin, cos
import plotly.graph_objects as go

def ellipse(x_center=0, y_center=0, ax1 = [1, 0],  ax2 = [0,1], a=1, b =1,  N=100):
    # x_center, y_center the coordinates of ellipse center
    # ax1 ax2 two orthonormal vectors representing the ellipse axis directions
    # a, b the ellipse parameters
    if np.linalg.norm(ax1) != 1 or np.linalg.norm(ax2) != 1:
        raise ValueError('ax1, ax2 must be unit vectors')
    if  abs(np.dot(ax1, ax2)) > 1e-06:
        raise ValueError('ax1, ax2 must be orthogonal vectors')
    t = np.linspace(0, 2*pi, N)
    #ellipse parameterization with respect to a system of axes of directions a1, a2
    xs = a * cos(t)
    ys = b * sin(t)
    #rotation matrix
    R = np.array([ax1, ax2]).T
    # coordinate of the  ellipse points with respect to the system of axes [1, 0], [0,1] with origin (0,0)
    xp, yp = np.dot(R, [xs, ys])
    x = xp + x_center 
    y = yp + y_center
    return x, y
    
#EXAMPLE
fig = go.Figure()
x_center=1
y_center=0.75
x, y = ellipse_arc(x_center=x_center, y_center=y_center, 
                   ax1 =[cos(pi/6), sin(pi/6)],  ax2=[-sin(pi/6),cos(pi/6)],
                   a=3, b =2)
fig.add_scatter(
            x=x,
            y=y,
            mode = 'lines')
fig.update_layout(width =600, height=525)