'Recreate image in Plotly using coordinates

I'm attempting to recreate this image using coordinates. So far I haven't had much luck. Specifically I'm running into trouble being able to see all the colors. I think what I need is a way to determine which rectangles are at the forefront vs background. Would I be better off using matplotlib? Any help on this would be greatly appreciated.

Image I'm attempting to recreate

CURRENT CODE

frame = tools.csv_read(file=['attack_zones'])

x = frame.groupby('identifier')
x = x.agg(Xmin=('X', np.min), Xmax=('X', np.max)).reset_index()

y = frame.groupby('identifier')
y = y.agg(Ymin=('Y', np.min), Ymax=('Y', np.max)).reset_index()

x = x.merge(y,on='identifier',how='left')
x = x.sort_values('identifier',ascending=True)

fig = go.Figure()

#Create scatter trace of text labels
fig.add_trace(go.Scatter(
    x=[-48, 52],
    y=[113, 242],
    text=["Rectangle reference to the plot",
          "Rectangle reference to the axes"],
    mode="text",
))

#Set axes properties
fig.update_xaxes(range=[-134, 134])
fig.update_yaxes(range=[0, 345])

#Set identifier colors
def colors(identifier):
    if identifier < 10:
        return 'purple'
    if identifier < 20:
        return 'pink'
    if identifier < 30:
        return 'yellow'
    else:
        return 'white'

for iden,xmin,xmax,ymin,ymax in zip(x['identifier'],x['Xmin'],x['Xmax'],x['Ymin'],x['Ymax']):
    fig.add_shape(type="rect",
        xref="x", yref="y",
        x0=xmin, y0=ymin,
        x1=xmax, y1=ymax,
        fillcolor=colors(iden),
    )


fig.show()


Solution 1:[1]

There appears to be repeatable portions in your desired image – specifically each "square" can be thought of as a 3x3 array with text labels everywhere except for the center. Therefore, I would recommend writing a function with parameters for the two corners of your square, the text annotations, and fill color of the square, then calling this function repeatedly.

import plotly.graph_objects as go

fig = go.Figure()

def draw_square_with_labels(top_left, bottom_right, text_labels, fill_color, fig=fig):
    """ Adds a 3x3 square trace with labels ordered clockwise on a Plotly graph_object

    Args:
        top_left: starting corner of a rectangle as a tuple or list of form (x0,y0)
        bottom_right: ending corner of a rectangle as a tuple or list of form (x0,y0)
        text_labels: a list of text labels starting from the location of the top_left and moving clockwise
        fill_color: fill color for the square

    Returns:
        fig with a 3x3 colored square trace with labels added
    """
    x0,y0 = top_left
    x2,y2 = bottom_right
    x1,y1 = (x0+x2)/2, (y0+y2)/2
    xy_coordinates = [
        [x0,y0],[x1,y0],[x2,y0],
        [x2,y1],[x2,y2],[x1,y2],
        [x0,y2],[x0,y1],[x0,y0]
    ]
    x = [c[0] for c in xy_coordinates]
    y = [c[1] for c in xy_coordinates]
    text_positions = [
        "bottom right",
        "bottom center",
        "bottom left",
        "middle left",
        "top left",
        "top center",
        "top right",
        "middle right",
    ]
    fig.add_trace(go.Scatter(
        x=x,
        y=y,
        mode='lines+text',
        line_color="rgba(200,200,200,0.7)",
        text=text_labels,
        textposition=text_positions,
        fill='toself', 
        fillcolor = fill_color,
    ))

side_lengths = [10,7,4,1]
text_labels_array = [
    [31,32,33,36,39,38,37,34,""],
    [21,22,23,26,29,28,27,24,""],
    [11,12,13,16,19,18,17,14,""],
    [1,2,3,6,9,8,7,4,""],
]
fill_colors = [
    "rgba(255,255,255,0.5)",
    "rgba(255,255,167,0.5)",
    "rgba(255,182,193,0.5)",
    "rgba(219,112,147,0.5)",
]

for side_length, text_labels, fill_color in zip(side_lengths,text_labels_array,fill_colors):
    draw_square_with_labels(
        top_left=[-side_length,side_length],
        bottom_right=[side_length,-side_length],
        text_labels=text_labels,
        fill_color=fill_color
    )

## add '5' at the center
fig.add_annotation(x=0, y=0, text="5", showarrow=False)

## add guidelines
edge_x, edge_y = 1,10
fig.add_shape(type="line",
    x0=-edge_x, y0=-edge_y, x1=-edge_x, y1=edge_y,
    line=dict(color="rgba(200,200,200,0.7)")
)
fig.add_shape(type="line",
    x0=edge_x, y0=-edge_y, x1=edge_x, y1=edge_y,
    line=dict(color="rgba(200,200,200,0.7)")
)
fig.add_shape(type="line",
    x0=-edge_y, y0=edge_x, x1=edge_y, y1=edge_x,
    line=dict(color="rgba(200,200,200,0.7)")
)
fig.add_shape(type="line",
    x0=-edge_y, y0=-edge_x, x1=edge_y, y1=-edge_x,
    line=dict(color="rgba(200,200,200,0.7)")
)

## add green dashed rectangle
fig.add_shape(type="rect",
    x0=-3.5, y0=-3.5, x1=3.5, y1=3.5,
    line=dict(color="rgba(46,204,113,0.7)", dash='dash')
)

fig.update_xaxes(visible=False, showticklabels=False)
fig.update_yaxes(visible=False, showticklabels=False)
fig.update_layout(template='plotly_white', showlegend=False)
fig.show()

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Derek O