Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding 500 circles in a plotly graph using add_shape function takes 45 seconds, how to reduce this?

I am trying to add small circles in a plotly graph. I want to add around 1000 small circles. But to add 500 circles itself it's taking more than 45 seconds. Is there any way to reduce this timing? I hear using d3 lib in javascript will be much faster. But I would like to achieve this using python.

Please see my code below.

Data points would be some thing like this,

-0.0919488188976378 0.4985236220472441 -0.08210629921259843 0.5083661417322834
-0.11714566929133859 0.4985236220472441 -0.1073031496062992 0.5083661417322834
-0.1423425196850394 0.4985236220472441 -0.1325 0.5083661417322834

x0, y0, x1, y1 format.

The code that adds shaple is

fig = go.Figure()
for data in datapoints:
    x0 = data[0]
    y0 = data[1]        
    x1 = data[2]
    y1 = data[3]
    fig.add_shape(type="circle",
                    xref="x", yref="y",
                    x0=x0, y0=y0, x1=x1, y1=y1,
                    line_color='gold',
                    fillcolor='gold',
                    )
                    
print("--- %s seconds ---" % (time.time() - start_time))

To code takes around 45 seconds to execute.

Is there any way to reduce this timing? or is there any other library to achieve this requirement? My requirement is based on some input files (shapes specifications/dimensions), I need to create SVG images using python.

Thanks in advance.

like image 879
Muthu Saravanan R Avatar asked Sep 16 '25 22:09

Muthu Saravanan R


2 Answers

We found a way to reduce this time. The idea is to add all the shapes into a list & pass this list to a layout constructor. So plotly is trying to add at a single stretch which seems to reduce the timings. Refer to the following code for more details.

fig = go.Figure()

shapes = []
for data in datapoints:
    x0 = data[0]
    y0 = data[1]        
    x1 = data[2]
    y1 = data[3]
    shapes.append(dict(type="circle",
                    xref="x", yref="y",
                    x0=x0, y0=y0, x1=x1, y1=y1,
                    line_color='gold',
                    fillcolor='gold',
                    ))
fig.update_layout(shapes=shapes)
                
like image 166
Muthu Saravanan R Avatar answered Sep 19 '25 12:09

Muthu Saravanan R


Here is some code to demo how to add shapes with ‘update’ in one figture and subfigures.

import plotly.graph_objects as go
from plotly.subplots import make_subplots
import numpy as np

shapes_data = [
    {"x0": 1, "y0": 1, "x1": 2, "y1": 2, "color": "red"},
    {"x0": 3, "y0": 2, "x1": 4, "y1": 3, "color": "blue"},
    {"x0": 2, "y0": 4, "x1": 3, "y1": 5, "color": "green"}
]

# Method 1: Using Update Layout to add shapes to single plot
fig1 = go.Figure()
fig1.add_trace(go.Scatter(x=[0, 5], y=[0, 5], mode='markers', name='Base Data'))
shapes_list = []
for shape in shapes_data:
    shapes_list.append(
        dict(
            type="rect",
            x0=shape["x0"], y0=shape["y0"],
            x1=shape["x1"], y1=shape["y1"],
            fillcolor=shape["color"],
            opacity=0.5,
            line=dict(color=shape["color"], width=2)
        )
    )

fig1.update_layout(
    shapes=shapes_list,
    title="Method 2: Adding Shapes with Update Layout",
    xaxis_title="X Axis",
    yaxis_title="Y Axis"
)


# Method 2: Adding shapes to subplots
fig2 = make_subplots(
    rows=1, cols=2,
    subplot_titles=("Left Subplot", "Right Subplot")
)
fig2.add_trace(go.Scatter(x=[0, 5], y=[0, 5], mode='markers', name='Left Data'), row=1, col=1)
fig2.add_trace(go.Scatter(x=[0, 5], y=[0, 5], mode='markers', name='Right Data'), row=1, col=2)
left_shapes = []
right_shapes = []
for i, shape in enumerate(shapes_data):
    if i < 2:  # Add first two shapes to left subplot
        left_shapes.append(dict(
            type="rect",
            x0=shape["x0"], y0=shape["y0"],
            x1=shape["x1"], y1=shape["y1"],
            fillcolor=shape["color"],
            opacity=0.5,
            line=dict(color=shape["color"], width=2),
            # MAIN DIFFERENCE:
            xref="x", yref="y"  # Reference to first subplot
        ))
    else:  # Add remaining shapes to right subplot
        right_shapes.append(dict(
            type="rect",
            x0=shape["x0"], y0=shape["y0"],
            x1=shape["x1"], y1=shape["y1"],
            fillcolor=shape["color"],
            opacity=0.5,
            line=dict(color=shape["color"], width=2),
            xref="x2", yref="y2"  # Reference to second subplot
        ))

all_shapes = left_shapes + right_shapes
fig2.update_layout(
    shapes=all_shapes,
    title="Method 3: Adding Shapes to Subplots Example"
)

fig1.show()
fig2.show()

Performance comparison between ‘for loop’ and ‘update’:

enter image description here

like image 38
Wuji Chen Avatar answered Sep 19 '25 12:09

Wuji Chen