| 212 | |
| 213 | |
| 214 | def write_svg(rows: list[dict[str, object]]) -> None: |
| 215 | xs = [float(row["auto"]) for row in rows] |
| 216 | ys = [float(row["human"]) for row in rows] |
| 217 | slope, intercept = regression(xs, ys) |
| 218 | r = pearson(xs, ys) |
| 219 | x1, x2 = min(xs), max(xs) |
| 220 | y1, y2 = slope * x1 + intercept, slope * x2 + intercept |
| 221 | |
| 222 | def rgb(color: tuple[int, int, int]) -> str: |
| 223 | return f"rgb({color[0]},{color[1]},{color[2]})" |
| 224 | |
| 225 | parts = [ |
| 226 | f'<svg xmlns="http://www.w3.org/2000/svg" width="{W}" height="{H}" viewBox="0 0 {W} {H}">', |
| 227 | '<rect width="100%" height="100%" fill="white"/>', |
| 228 | f'<line x1="{PLOT_L}" y1="{PLOT_T}" x2="{PLOT_L}" y2="{PLOT_B}" stroke="{rgb(AXIS)}" stroke-width="3"/>', |
| 229 | f'<line x1="{PLOT_L}" y1="{PLOT_B}" x2="{PLOT_R}" y2="{PLOT_B}" stroke="{rgb(AXIS)}" stroke-width="3"/>', |
| 230 | ] |
| 231 | for tick in [65, 70, 75, 80, 85, 90, 95, 100]: |
| 232 | y = y_pos(float(tick)) |
| 233 | parts.append(f'<line x1="{PLOT_L-10}" y1="{y}" x2="{PLOT_L}" y2="{y}" stroke="{rgb(AXIS)}" stroke-width="3"/>') |
| 234 | parts.append(f'<text x="{PLOT_L-18}" y="{y+12}" font-family="Times New Roman" font-size="36" font-weight="700" text-anchor="end" fill="{rgb(TEXT)}">{tick}</text>') |
| 235 | for tick in [63.5, 64.0, 64.5, 65.0]: |
| 236 | x = x_pos(tick) |
| 237 | parts.append(f'<line x1="{x}" y1="{PLOT_B}" x2="{x}" y2="{PLOT_B+13}" stroke="{rgb(AXIS)}" stroke-width="3"/>') |
| 238 | parts.append(f'<text x="{x}" y="{PLOT_B+60}" font-family="Times New Roman" font-size="36" font-weight="700" text-anchor="middle" fill="{rgb(TEXT)}">{tick:.1f}</text>') |
| 239 | parts.append(f'<text x="{PLOT_L-48}" y="{PLOT_T-52}" font-family="Times New Roman" font-size="42" font-weight="700" fill="{rgb(TEXT)}">Human</text>') |
| 240 | parts.append(f'<text x="{PLOT_R+45}" y="{PLOT_B+20}" font-family="Times New Roman" font-size="42" font-weight="700" fill="{rgb(TEXT)}">ModelAuto</text>') |
| 241 | parts.append(f'<line x1="{x_pos(x1)}" y1="{y_pos(y1)}" x2="{x_pos(x2)}" y2="{y_pos(y2)}" stroke="{rgb(RED)}" stroke-width="6"/>') |
| 242 | for x, y in [(x1, y1), (x2, y2)]: |
| 243 | parts.append(f'<circle cx="{x_pos(x)}" cy="{y_pos(y)}" r="10" fill="white" stroke="{rgb(BLUE)}" stroke-width="5"/>') |
| 244 | for row in rows: |
| 245 | key = str(row["key"]) |
| 246 | color = MODEL_COLORS[key] |
| 247 | parts.append(f'<circle cx="{x_pos(float(row["auto"]))}" cy="{y_pos(float(row["human"]))}" r="11" fill="{rgb(color)}"/>') |
| 248 | for row in rows: |
| 249 | key = str(row["key"]) |
| 250 | color = MODEL_COLORS[key] |
| 251 | dx, dy = LABEL_OFFSETS[key] |
| 252 | parts.append( |
| 253 | f'<text x="{x_pos(float(row["auto"]))+dx}" y="{y_pos(float(row["human"]))+dy+28}" ' |
| 254 | f'font-family="Times New Roman" font-size="31" font-weight="700" fill="{rgb(color)}">{row["name"]}</text>' |
| 255 | ) |
| 256 | parts.append(f'<text x="{PLOT_R-430}" y="{PLOT_T+73}" font-family="Times New Roman" font-size="44" font-weight="700" fill="{rgb(RED)}">Pearson's r = {r:.4f}</text>') |
| 257 | parts.append("</svg>") |
| 258 | SVG_OUT.write_text("\n".join(parts), encoding="utf-8") |
| 259 | |
| 260 | |
| 261 | def write_csv(rows: list[dict[str, object]]) -> None: |