pimco-charts/app/models/chart_spec.py
DJP a3a38e85d2 Initial commit: PIMCO chart generator with iterative refinement
AI-powered tool that generates publication-quality SVG charts matching
PIMCO's InDesign style. Upload Excel/CSV data, write a plain-English
brief, then iterate with natural language edits until the chart is
exactly right.

- Claude Opus 4.6 interprets briefs into structured ChartSpec JSON
- Deterministic SVG renderer via drawsvg (no visual hallucinations)
- Roboto/Roboto Condensed fonts base64-embedded in SVG
- FastAPI + HTMX web frontend with live preview
- Conversational refinement: "make lines thicker", "change title", etc.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:29:47 -05:00

53 lines
1.6 KiB
Python

"""Pydantic models for the chart specification - the contract between AI and renderer."""
from __future__ import annotations
from typing import Literal
from pydantic import BaseModel, Field
class AxisSpec(BaseModel):
label: str | None = None
suffix: str | None = None
date_format: str | None = None
min_val: float | None = None
max_val: float | None = None
tick_interval: float | None = None
class ShadedFillSpec(BaseModel):
reference_series: str = Field(description="Label of the reference series to shade against")
above_color: Literal["blue", "pink"] = "blue"
below_color: Literal["blue", "pink"] = "pink"
class SeriesSpec(BaseModel):
label: str
data_column: str = Field(description="Column name from uploaded data")
chart_type: Literal["line", "bar", "stacked_bar", "area", "pie"] = "line"
color_index: int | None = None
line_style: Literal["solid", "dashed", "dotted"] = "solid"
line_weight: float | None = None
shaded_fill: ShadedFillSpec | None = None
class AnnotationSpec(BaseModel):
type: Literal["ellipse", "callout", "label"]
x_start: str | None = None
x_end: str | None = None
y_start: float | None = None
y_end: float | None = None
text: str | None = None
class PanelSpec(BaseModel):
title: str
subtitle: str | None = None
x_axis: AxisSpec
y_axis: AxisSpec
series: list[SeriesSpec]
annotations: list[AnnotationSpec] = Field(default_factory=list)
class ChartSpec(BaseModel):
layout: Literal["single", "dual_panel"] = "single"
panels: list[PanelSpec]