Cube-view: UCIe position/size from topology.yaml (ucie_mm.size=2.0)

UCIe components placed at defined positions from _cube_local_positions
with size from cube.geometry.ucie_mm.size. N/S horizontal, E/W vertical.
Connection ports rendered as color-coded boxes inside UCIe component.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-05 00:11:11 -07:00
parent 66ec6cd40c
commit df81835d84
2 changed files with 94 additions and 122 deletions
+56 -56
View File
@@ -241,62 +241,62 @@
<text x="622" y="604" font-family="monospace" font-size="6" fill="#10b98188">256GB/s</text> <text x="622" y="604" font-family="monospace" font-size="6" fill="#10b98188">256GB/s</text>
<line x1="835" y1="677" x2="646" y2="531" stroke="#10b981" stroke-width="1.5" opacity="0.6" stroke-dasharray="4,3"/> <line x1="835" y1="677" x2="646" y2="531" stroke="#10b981" stroke-width="1.5" opacity="0.6" stroke-dasharray="4,3"/>
<text x="751" y="604" font-family="monospace" font-size="6" fill="#10b98188">256GB/s</text> <text x="751" y="604" font-family="monospace" font-size="6" fill="#10b98188">256GB/s</text>
<rect x="210" y="120" width="18" height="580" rx="3" fill="#1e1b4b" stroke="#8b5cf6" stroke-width="1.5" opacity="0.8"/> <rect x="85" y="360" width="50" height="100" rx="3" fill="#1e1b4b" stroke="#8b5cf6" stroke-width="1.5" opacity="0.9"/>
<text x="219" y="117" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#8b5cf6">UCIe-W</text> <text x="110" y="357" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#8b5cf6">UCIe-W</text>
<rect x="212" y="122" width="14" height="143" rx="2" fill="#818cf8" opacity="0.7"/> <rect x="87" y="362" width="46" height="23" rx="2" fill="#818cf8" opacity="0.7"/>
<text x="219" y="196" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c0</text> <text x="110" y="376" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c0</text>
<line x1="226" y1="194" x2="127" y2="135" stroke="#818cf8" stroke-width="1" opacity="0.5"/> <line x1="133" y1="374" x2="127" y2="135" stroke="#818cf8" stroke-width="1" opacity="0.5"/>
<rect x="212" y="266" width="14" height="143" rx="2" fill="#a78bfa" opacity="0.7"/> <rect x="87" y="386" width="46" height="23" rx="2" fill="#a78bfa" opacity="0.7"/>
<text x="219" y="340" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c1</text> <text x="110" y="400" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c1</text>
<line x1="226" y1="338" x2="127" y2="260" stroke="#a78bfa" stroke-width="1" opacity="0.5"/> <line x1="133" y1="398" x2="127" y2="260" stroke="#a78bfa" stroke-width="1" opacity="0.5"/>
<rect x="212" y="410" width="14" height="143" rx="2" fill="#c084fc" opacity="0.7"/> <rect x="87" y="410" width="46" height="23" rx="2" fill="#c084fc" opacity="0.7"/>
<text x="219" y="484" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c2</text> <text x="110" y="424" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c2</text>
<line x1="226" y1="482" x2="127" y2="560" stroke="#c084fc" stroke-width="1" opacity="0.5"/> <line x1="133" y1="422" x2="127" y2="560" stroke="#c084fc" stroke-width="1" opacity="0.5"/>
<rect x="212" y="554" width="14" height="143" rx="2" fill="#e879f9" opacity="0.7"/> <rect x="87" y="434" width="46" height="23" rx="2" fill="#e879f9" opacity="0.7"/>
<text x="219" y="628" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c3</text> <text x="110" y="448" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c3</text>
<line x1="226" y1="626" x2="127" y2="685" stroke="#e879f9" stroke-width="1" opacity="0.5"/> <line x1="133" y1="446" x2="127" y2="685" stroke="#e879f9" stroke-width="1" opacity="0.5"/>
<rect x="120" y="210" width="730" height="18" rx="3" fill="#1e1b4b" stroke="#8b5cf6" stroke-width="1.5" opacity="0.8"/> <rect x="435" y="85" width="100" height="50" rx="3" fill="#1e1b4b" stroke="#8b5cf6" stroke-width="1.5" opacity="0.9"/>
<text x="485" y="207" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#8b5cf6">UCIe-N</text> <text x="485" y="82" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#8b5cf6">UCIe-N</text>
<rect x="122" y="212" width="180" height="14" rx="2" fill="#818cf8" opacity="0.7"/> <rect x="437" y="87" width="23" height="46" rx="2" fill="#818cf8" opacity="0.7"/>
<text x="212" y="222" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c0</text> <text x="448" y="113" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c0</text>
<line x1="212" y1="226" x2="135" y2="127" stroke="#818cf8" stroke-width="1" opacity="0.5"/> <line x1="448" y1="133" x2="135" y2="127" stroke="#818cf8" stroke-width="1" opacity="0.5"/>
<rect x="304" y="212" width="180" height="14" rx="2" fill="#a78bfa" opacity="0.7"/> <rect x="461" y="87" width="23" height="46" rx="2" fill="#a78bfa" opacity="0.7"/>
<text x="394" y="222" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c1</text> <text x="472" y="113" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c1</text>
<line x1="394" y1="226" x2="285" y2="127" stroke="#a78bfa" stroke-width="1" opacity="0.5"/> <line x1="472" y1="133" x2="285" y2="127" stroke="#a78bfa" stroke-width="1" opacity="0.5"/>
<rect x="485" y="212" width="180" height="14" rx="2" fill="#c084fc" opacity="0.7"/> <rect x="485" y="87" width="23" height="46" rx="2" fill="#c084fc" opacity="0.7"/>
<text x="575" y="222" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c2</text> <text x="496" y="113" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c2</text>
<line x1="575" y1="226" x2="685" y2="127" stroke="#c084fc" stroke-width="1" opacity="0.5"/> <line x1="496" y1="133" x2="685" y2="127" stroke="#c084fc" stroke-width="1" opacity="0.5"/>
<rect x="666" y="212" width="180" height="14" rx="2" fill="#e879f9" opacity="0.7"/> <rect x="509" y="87" width="23" height="46" rx="2" fill="#e879f9" opacity="0.7"/>
<text x="757" y="222" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c3</text> <text x="520" y="113" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c3</text>
<line x1="757" y1="226" x2="835" y2="127" stroke="#e879f9" stroke-width="1" opacity="0.5"/> <line x1="520" y1="133" x2="835" y2="127" stroke="#e879f9" stroke-width="1" opacity="0.5"/>
<rect x="742" y="120" width="18" height="580" rx="3" fill="#1e1b4b" stroke="#8b5cf6" stroke-width="1.5" opacity="0.8"/> <rect x="835" y="360" width="50" height="100" rx="3" fill="#1e1b4b" stroke="#8b5cf6" stroke-width="1.5" opacity="0.9"/>
<text x="751" y="117" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#8b5cf6">UCIe-E</text> <text x="860" y="357" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#8b5cf6">UCIe-E</text>
<rect x="744" y="122" width="14" height="143" rx="2" fill="#818cf8" opacity="0.7"/> <rect x="837" y="362" width="46" height="23" rx="2" fill="#818cf8" opacity="0.7"/>
<text x="751" y="196" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c0</text> <text x="860" y="376" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c0</text>
<line x1="744" y1="194" x2="843" y2="135" stroke="#818cf8" stroke-width="1" opacity="0.5"/> <line x1="837" y1="374" x2="843" y2="135" stroke="#818cf8" stroke-width="1" opacity="0.5"/>
<rect x="744" y="266" width="14" height="143" rx="2" fill="#a78bfa" opacity="0.7"/> <rect x="837" y="386" width="46" height="23" rx="2" fill="#a78bfa" opacity="0.7"/>
<text x="751" y="340" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c1</text> <text x="860" y="400" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c1</text>
<line x1="744" y1="338" x2="843" y2="260" stroke="#a78bfa" stroke-width="1" opacity="0.5"/> <line x1="837" y1="398" x2="843" y2="260" stroke="#a78bfa" stroke-width="1" opacity="0.5"/>
<rect x="744" y="410" width="14" height="143" rx="2" fill="#c084fc" opacity="0.7"/> <rect x="837" y="410" width="46" height="23" rx="2" fill="#c084fc" opacity="0.7"/>
<text x="751" y="484" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c2</text> <text x="860" y="424" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c2</text>
<line x1="744" y1="482" x2="843" y2="560" stroke="#c084fc" stroke-width="1" opacity="0.5"/> <line x1="837" y1="422" x2="843" y2="560" stroke="#c084fc" stroke-width="1" opacity="0.5"/>
<rect x="744" y="554" width="14" height="143" rx="2" fill="#e879f9" opacity="0.7"/> <rect x="837" y="434" width="46" height="23" rx="2" fill="#e879f9" opacity="0.7"/>
<text x="751" y="628" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c3</text> <text x="860" y="448" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c3</text>
<line x1="744" y1="626" x2="843" y2="685" stroke="#e879f9" stroke-width="1" opacity="0.5"/> <line x1="837" y1="446" x2="843" y2="685" stroke="#e879f9" stroke-width="1" opacity="0.5"/>
<rect x="120" y="592" width="730" height="18" rx="3" fill="#1e1b4b" stroke="#8b5cf6" stroke-width="1.5" opacity="0.8"/> <rect x="435" y="685" width="100" height="50" rx="3" fill="#1e1b4b" stroke="#8b5cf6" stroke-width="1.5" opacity="0.9"/>
<text x="485" y="589" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#8b5cf6">UCIe-S</text> <text x="485" y="682" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#8b5cf6">UCIe-S</text>
<rect x="122" y="594" width="180" height="14" rx="2" fill="#818cf8" opacity="0.7"/> <rect x="437" y="687" width="23" height="46" rx="2" fill="#818cf8" opacity="0.7"/>
<text x="212" y="604" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c0</text> <text x="448" y="713" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c0</text>
<line x1="212" y1="594" x2="135" y2="693" stroke="#818cf8" stroke-width="1" opacity="0.5"/> <line x1="448" y1="687" x2="135" y2="693" stroke="#818cf8" stroke-width="1" opacity="0.5"/>
<rect x="304" y="594" width="180" height="14" rx="2" fill="#a78bfa" opacity="0.7"/> <rect x="461" y="687" width="23" height="46" rx="2" fill="#a78bfa" opacity="0.7"/>
<text x="394" y="604" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c1</text> <text x="472" y="713" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c1</text>
<line x1="394" y1="594" x2="285" y2="693" stroke="#a78bfa" stroke-width="1" opacity="0.5"/> <line x1="472" y1="687" x2="285" y2="693" stroke="#a78bfa" stroke-width="1" opacity="0.5"/>
<rect x="485" y="594" width="180" height="14" rx="2" fill="#c084fc" opacity="0.7"/> <rect x="485" y="687" width="23" height="46" rx="2" fill="#c084fc" opacity="0.7"/>
<text x="575" y="604" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c2</text> <text x="496" y="713" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c2</text>
<line x1="575" y1="594" x2="685" y2="693" stroke="#c084fc" stroke-width="1" opacity="0.5"/> <line x1="496" y1="687" x2="685" y2="693" stroke="#c084fc" stroke-width="1" opacity="0.5"/>
<rect x="666" y="594" width="180" height="14" rx="2" fill="#e879f9" opacity="0.7"/> <rect x="509" y="687" width="23" height="46" rx="2" fill="#e879f9" opacity="0.7"/>
<text x="757" y="604" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c3</text> <text x="520" y="713" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c3</text>
<line x1="757" y1="594" x2="835" y2="693" stroke="#e879f9" stroke-width="1" opacity="0.5"/> <line x1="520" y1="687" x2="835" y2="693" stroke="#e879f9" stroke-width="1" opacity="0.5"/>
<rect x="60" y="865" width="10" height="10" rx="2" fill="#3b82f6" stroke="#475569" stroke-width="0.5"/> <rect x="60" y="865" width="10" height="10" rx="2" fill="#3b82f6" stroke="#475569" stroke-width="0.5"/>
<text x="74" y="874" font-family="monospace" font-size="8" fill="#94a3b8">PE Router</text> <text x="74" y="874" font-family="monospace" font-size="8" fill="#94a3b8">PE Router</text>
<rect x="147" y="865" width="10" height="10" rx="2" fill="#f59e0b" stroke="#475569" stroke-width="0.5"/> <rect x="147" y="865" width="10" height="10" rx="2" fill="#f59e0b" stroke="#475569" stroke-width="0.5"/>

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

+38 -66
View File
@@ -683,9 +683,18 @@ def _render_cube_view_svg(view: ViewGraph, spec: dict) -> str:
f'{agg_bw:.0f}GB/s</text>' f'{agg_bw:.0f}GB/s</text>'
) )
# ── UCIe port components (inside cube boundary, on edges) ── # ── UCIe port components (position/size from topology.yaml) ──
# ucie_mm.size = 2.0mm, positions from _cube_local_positions
ucie_size_mm = cube.get("geometry", {}).get("ucie_mm", {}).get("size", 2.0)
ucie_positions = {
"N": (cube_w / 2, ucie_size_mm / 2), # top center
"S": (cube_w / 2, cube_h - ucie_size_mm / 2), # bottom center
"W": (ucie_size_mm / 2, cube_h / 2), # left center
"E": (cube_w - ucie_size_mm / 2, cube_h / 2), # right center
}
# Collect UCIe connections per direction # Collect UCIe connections per direction
ucie_by_dir: dict[str, list[tuple[str, str, float, float]]] = {} # dir → [(conn, rkey, rx, ry)] ucie_by_dir: dict[str, list[tuple[str, str, float, float]]] = {}
for rkey, rval in routers.items(): for rkey, rval in routers.items():
if rval is None: if rval is None:
continue continue
@@ -699,123 +708,86 @@ def _render_cube_view_svg(view: ViewGraph, spec: dict) -> str:
ucie_by_dir.setdefault(direction, []).append((conn, rkey, rx, ry)) ucie_by_dir.setdefault(direction, []).append((conn, rkey, rx, ry))
ucie_colors = ["#818cf8", "#a78bfa", "#c084fc", "#e879f9"] ucie_colors = ["#818cf8", "#a78bfa", "#c084fc", "#e879f9"]
ucie_port_inset = 3 # mm inset from cube edge
for direction, conns in ucie_by_dir.items(): for direction, conns in ucie_by_dir.items():
conns.sort(key=lambda x: x[0]) # sort by conn name conns.sort(key=lambda x: x[0])
n_conn = len(conns) n_conn = len(conns)
ucx_mm, ucy_mm = ucie_positions.get(direction, (cube_w / 2, cube_h / 2))
ucx, ucy = mm2px(ucx_mm, ucy_mm)
# UCIe component box position (inside cube, along edge) # UCIe box: size from topology, N/S horizontal, E/W vertical
if direction == "N": us = ucie_size_mm * scale
# Horizontal bar along top edge if direction in ("N", "S"):
# Find X span from attached routers uw, uh = us, us * 0.5
xs = [mm2px(rx, ry)[0] for _, _, rx, ry in conns]
ux1 = min(xs) - 15
ux2 = max(xs) + 15
uw = ux2 - ux1
uh = 18
ux = ux1
uy = pad + ucie_port_inset * scale
elif direction == "S":
xs = [mm2px(rx, ry)[0] for _, _, rx, ry in conns]
ux1 = min(xs) - 15
ux2 = max(xs) + 15
uw = ux2 - ux1
uh = 18
ux = ux1
uy = pad + cube_h * scale - ucie_port_inset * scale - uh
elif direction == "W":
ys = [mm2px(rx, ry)[1] for _, _, rx, ry in conns]
uy1 = min(ys) - 15
uy2 = max(ys) + 15
uw = 18
uh = uy2 - uy1
ux = pad + ucie_port_inset * scale
uy = uy1
elif direction == "E":
ys = [mm2px(rx, ry)[1] for _, _, rx, ry in conns]
uy1 = min(ys) - 15
uy2 = max(ys) + 15
uw = 18
uh = uy2 - uy1
ux = pad + cube_w * scale - ucie_port_inset * scale - uw
uy = uy1
else: else:
continue uw, uh = us * 0.5, us
ux = ucx - uw / 2
uy = ucy - uh / 2
# UCIe component background # UCIe component background
parts.append( parts.append(
f' <rect x="{ux:.0f}" y="{uy:.0f}" ' f' <rect x="{ux:.0f}" y="{uy:.0f}" '
f'width="{uw:.0f}" height="{uh:.0f}" ' f'width="{uw:.0f}" height="{uh:.0f}" '
f'rx="3" fill="#1e1b4b" stroke="#8b5cf6" stroke-width="1.5" opacity="0.8"/>' f'rx="3" fill="#1e1b4b" stroke="#8b5cf6" stroke-width="1.5" opacity="0.9"/>'
)
# UCIe direction label
parts.append(
f' <text x="{ucx:.0f}" y="{uy - 3:.0f}" text-anchor="middle" '
f'font-family="monospace" font-size="7" font-weight="bold" fill="#8b5cf6">'
f'UCIe-{direction}</text>'
) )
# UCIe label
if direction in ("N", "S"):
parts.append(
f' <text x="{ux + uw / 2:.0f}" y="{uy - 3:.0f}" text-anchor="middle" '
f'font-family="monospace" font-size="7" font-weight="bold" fill="#8b5cf6">'
f'UCIe-{direction}</text>'
)
else:
parts.append(
f' <text x="{ux + uw / 2:.0f}" y="{uy - 3:.0f}" text-anchor="middle" '
f'font-family="monospace" font-size="7" font-weight="bold" fill="#8b5cf6">'
f'UCIe-{direction}</text>'
)
# Connection port boxes inside UCIe component # Connection port boxes inside UCIe component
for ci, (conn, rkey, crx, cry) in enumerate(conns): for ci, (conn, rkey, crx, cry) in enumerate(conns):
c_color = ucie_colors[ci % len(ucie_colors)] c_color = ucie_colors[ci % len(ucie_colors)]
if direction in ("N", "S"): if direction in ("N", "S"):
# Horizontal layout
cw = max((uw - 4) / n_conn - 1, 6) cw = max((uw - 4) / n_conn - 1, 6)
ch = uh - 4 ch = uh - 4
cx = ux + 2 + ci * (cw + 1) cx = ux + 2 + ci * (cw + 1)
cy = uy + 2 cy_box = uy + 2
else: else:
# Vertical layout
cw = uw - 4 cw = uw - 4
ch = max((uh - 4) / n_conn - 1, 6) ch = max((uh - 4) / n_conn - 1, 6)
cx = ux + 2 cx = ux + 2
cy = uy + 2 + ci * (ch + 1) cy_box = uy + 2 + ci * (ch + 1)
parts.append( parts.append(
f' <rect x="{cx:.0f}" y="{cy:.0f}" ' f' <rect x="{cx:.0f}" y="{cy_box:.0f}" '
f'width="{cw:.0f}" height="{ch:.0f}" ' f'width="{cw:.0f}" height="{ch:.0f}" '
f'rx="2" fill="{c_color}" opacity="0.7"/>' f'rx="2" fill="{c_color}" opacity="0.7"/>'
) )
# Connection label
lx = cx + cw / 2 lx = cx + cw / 2
ly_t = cy + ch / 2 + 3 ly_t = cy_box + ch / 2 + 3
parts.append( parts.append(
f' <text x="{lx:.0f}" y="{ly_t:.0f}" text-anchor="middle" ' f' <text x="{lx:.0f}" y="{ly_t:.0f}" text-anchor="middle" '
f'font-family="monospace" font-size="5" fill="white">' f'font-family="monospace" font-size="5" fill="white">'
f'{conn}</text>' f'{conn}</text>'
) )
# Connector line: port box → attached router # Connector line: port router
rpx, rpy = mm2px(crx, cry) rpx, rpy = mm2px(crx, cry)
if direction == "N": if direction == "N":
parts.append( parts.append(
f' <line x1="{lx:.0f}" y1="{cy + ch:.0f}" ' f' <line x1="{lx:.0f}" y1="{cy_box + ch:.0f}" '
f'x2="{rpx:.0f}" y2="{rpy - r_size:.0f}" ' f'x2="{rpx:.0f}" y2="{rpy - r_size:.0f}" '
f'stroke="{c_color}" stroke-width="1" opacity="0.5"/>' f'stroke="{c_color}" stroke-width="1" opacity="0.5"/>'
) )
elif direction == "S": elif direction == "S":
parts.append( parts.append(
f' <line x1="{lx:.0f}" y1="{cy:.0f}" ' f' <line x1="{lx:.0f}" y1="{cy_box:.0f}" '
f'x2="{rpx:.0f}" y2="{rpy + r_size:.0f}" ' f'x2="{rpx:.0f}" y2="{rpy + r_size:.0f}" '
f'stroke="{c_color}" stroke-width="1" opacity="0.5"/>' f'stroke="{c_color}" stroke-width="1" opacity="0.5"/>'
) )
elif direction == "W": elif direction == "W":
parts.append( parts.append(
f' <line x1="{cx + cw:.0f}" y1="{cy + ch / 2:.0f}" ' f' <line x1="{cx + cw:.0f}" y1="{cy_box + ch / 2:.0f}" '
f'x2="{rpx - r_size:.0f}" y2="{rpy:.0f}" ' f'x2="{rpx - r_size:.0f}" y2="{rpy:.0f}" '
f'stroke="{c_color}" stroke-width="1" opacity="0.5"/>' f'stroke="{c_color}" stroke-width="1" opacity="0.5"/>'
) )
elif direction == "E": elif direction == "E":
parts.append( parts.append(
f' <line x1="{cx:.0f}" y1="{cy + ch / 2:.0f}" ' f' <line x1="{cx:.0f}" y1="{cy_box + ch / 2:.0f}" '
f'x2="{rpx + r_size:.0f}" y2="{rpy:.0f}" ' f'x2="{rpx + r_size:.0f}" y2="{rpy:.0f}" '
f'stroke="{c_color}" stroke-width="1" opacity="0.5"/>' f'stroke="{c_color}" stroke-width="1" opacity="0.5"/>'
) )