How to plot a dashed line circle on top of an existing trace based on a measure?

Hello,

I’m trying to plot a circle over trace/plot based on a certain value, in this case the average value. I’d like to plot two more such circles but using two different values.

So far my attempts have not been successful.

In the code below, I want to use the average value of the scaled_bidrates which are used as r in the bar polar chart to plot a circle but I can’t seem make it work.

I want the the circle to be placed on top of the existing chart. Now, in matplotlib I could just pass an x,y and the radius but I can’t seem to do the same thing in Plotly so I’ve still getting used to the API.

Since the values used for r are as follows: r = [1.0, 2.161, 4.327, 1.9, 5.0, 3.884, 2.623, 1.935], and the radius of the circle is the average of these values, I’m expecting that in some places the line will be above the bar while in others it will be below.

df = pd.read_csv('animation/data/factors_df_2022-03-09_06-00-06-30.csv', index_col=0)

# rename factors
names = ['Null', 'Pred=-1', 'Pred=0', 'Other', 'R_min', '0.0', '0.3', '0.8', '1.0']
df.index = names
df.index.names = ['factor']

def find_min_max(array):
    min_g = 1
    max_g = 0.0001
    if min_g > min(array):
        min_g = min(array)
    if max_g < max(array):
        max_g = max(array)
    return min_g, max_g

data_to_scale = df.bidrate.dropna()

# # scale bidrates
start = 1
end = 5
width = end - start
min_bidrate, max_bidrate = find_min_max(data_to_scale)
scaled_bidrates = [np.round((n-min_bidrate)/(max_bidrate-min_bidrate) * width + start,3) for n in data_to_scale]
#print(scaled_bidrates)
weights = df['sum_cnt'].dropna()
ratings = scaled_bidrates
labels = df.index.tolist()[1:]

angles = [(weight / sum(weights) * 360) for weight in weights]
num_slices = len(ratings)
theta = [0.5 * angle for angle in angles]
for index, angle in enumerate(angles):
    for subsequent_index in range(index + 1, len(angles)):
        theta[subsequent_index] += angle
width = angles

print("Average",np.average(scaled_bidrates))
avg = np.average(scaled_bidrates)

fig = go.Figure(
    go.Barpolar(
        r=scaled_bidrates,
        theta=theta,
        width=width,
        marker={
            "colorscale": px.colors.sequential.Reds,
            "showscale": True,
            "color": df['winrate'].dropna(),
            "line_color": None,
            "line_width": 1,
            "cmin": df['winrate'].min(),
            "cmax": df['winrate'].max(),
        },
        text=labels,     #factor names
        hoverinfo='all' #displays factors names if using 'text', need to find a way to set the proper bidrate value
    )
)
angular_tickvals = [(i + 1) * 360 / num_slices for i in range(num_slices)]

fig.update_layout(
    template=None,
    polar = dict(
        radialaxis = dict(range=[0, 5], showticklabels=False, ticks='', linecolor='White'),
        angularaxis = dict(showticklabels=False, ticks='', linecolor='White'),
    ),
    polar_radialaxis_gridcolor="#ffffff",
    polar_angularaxis_gridcolor="#ffffff",
    polar_angularaxis_tickvals=angular_tickvals,
    height=500,
    title='FPP Performance Chart'
)

fig.update_polars(radialaxis_color='black', radialaxis_linecolor='black')

fig.add_shape(type="circle",
    xref="x", yref="y",
    x0=1, y0=1, x1=avg, y1=avg,
    line_color="LightSeaGreen",
    line={'dash': 'dash'}
)
fig.show()
#print(fig)

In the documentation (Layout.shapes with Python) there is a reference regarding the type, as well as for xref but is there a way to sync the positions in some way?

To the code previously posted I started playing around with some snippets from the documentation: Shapes with Python

fig.add_trace(go.Scatter(
    x=[1, 3],
    y=[1, 5],
    text=["Average Bidrate"],
    mode="text",
))
fig.update_xaxes(range=[0, 4.5], zeroline=False)
fig.update_yaxes(range=[0, 4.5], zeroline=False)

I’ve managed to make it closer, actually the scatter plot code is pretty much useless and the axis update pretty much reduce the size of the circle but I still haven’t figure out how to sync them. By synch I mean, the circle’s coordinates should be the same as the barpolar.