chart-rendering-proposal.md 19 KB

Astro-MCP Chart Rendering — Planning & Brainstorm Document

Date: 2026-06-06 Status: Draft — for review and discussion before implementation


1. Vision & Goals

Astro-MCP already computes everything: planetary positions, houses, aspects, patterns, chart shapes, Davison/composite charts, transit previews. What's missing is visual output — turning that rich data into actual chart wheels and tables that a human can look at.

The goal is to add chart rendering that covers:

  1. Print-ready output (black/white laser printer, PDF)
  2. Web-publishable output (color SVG/HTML with customizable colors)
  3. Data tables (aspect tables, planet tables, house tables)

2. What We Can Already Produce (Data Side)

The existing MCP tools return all the data we need:

Tool Data Available
calculate_natal_chart Planets (sign, degree, house, retrograde), houses, aspects, angles, lunar phase, overview (elements, modalities, hemispheres, stelliums, empty houses, chart ruler, house rulers, retro list), aspect patterns, chart shape, karmic (nodal axis, Saturn, Pluto polarity point, Part of Fortune, 12th house)
calculate_transit_chart Natal planets + transiting planets + transit-to-natal aspects + houses
calculate_synastry_chart Both natal charts + interaspects + house overlays + composite + Davison
calculate_composite_chart Composite planets + houses + aspects + angles
calculate_davison_chart Davison planets + houses + aspects + angles
get_transit_preview Daily transit snapshots with significance scores
get_planetary_positions Quick lookup with zodiac positions

No new calculation logic is needed — rendering is purely a presentation layer on top of existing tools.


3. Chart Types to Render

3.1 Standard Natal Chart Wheel

The classic circular zodiac wheel:

  • Outer ring: 12 zodiac sign segments with glyphs
  • House divisions (12 sectors) with cusp degrees
  • Planets placed at their ecliptic longitude inside the wheel
  • Aspect lines between planets (color-coded by aspect type)
  • Optional: aspect patterns highlighted (T-square, Grand Trine, etc.)

3.2 Bi-Wheel (Transit Chart)

Two concentric zodiac wheels:

  • Inner wheel: natal planet positions (fixed)
  • Outer wheel: transiting planet positions
  • Aspect lines between natal and transit planets
  • Useful for showing current transits to a natal chart

3.3 Synastry / Comparison Wheel

  • Two side-by-side natal wheels, OR
  • Bi-wheel with person A inner, person B outer
  • Interaspect table below

3.4 Composite Chart Wheel

  • Single wheel showing midpoint composite planets
  • Houses computed from Davison midpoint date/location

3.5 Davison Chart Wheel

  • Single wheel with Davison date/location positions

3.6 Aspect Table / Grid

A matrix grid showing all planet-to-planet aspects:

  • Rows and columns = planets
  • Cells = aspect symbol + orb
  • Color-coded or B&W with line styles

3.7 Planet Data Table

Tabular view of all planet positions:

  • Planet, sign, degree:minute, house, retrograde flag
  • Sortable by longitude, planet name, or house

3.8 Houses Table

  • House number, cusp sign, cusp degree, ruler

4. Output Formats & Styles

4.1 Black/White (Print) Mode

  • Target: Laser printer output (PDF or SVG -> PDF)
  • Aspect lines distinguished by line style (solid, dashed, dotted) rather than color
    • Conjunction/Opposition: solid line
    • Trine/Square: dashed line
    • Sextile: dotted line
    • Quincunx: dash-dot line
  • Retrograde planets marked with an "R" or "℞" suffix
  • Planet glyphs from ZodiacFonts (or unicode fallbacks)
  • Clean, minimal design — works well on A4/Letter
  • Aspect table and planet table also in B&W-friendly format

4.2 Color (Web) Mode

  • Target: SVG/HTML embedded in dashboard or standalone
  • User-configurable colors:
    • Background color
    • Zodiac ring color (or per-element coloring: fire=red, earth=green, air=yellow, water=blue)
    • House sector colors (alternating or custom)
    • Aspect line colors (conjunction=red, trine=blue, square=red, sextile=light blue, quincunx=orange, opposition=red)
    • Planet glyph colors
    • Text colors
  • CSS variables for easy theming
  • Hover tooltips on planets showing exact degree
  • Click-to-highlight aspects

4.3 Style Variants

Traditional / Old-Fashioned:

  • Ornate zodiac wheel with decorative borders
  • Classical glyphs (unicode or ZodiacFonts serif style)
  • Black ink on white/cream background
  • Roman-style fonts
  • House numbers in Roman numerals

Modern / Clean:

  • Minimalist design, generous white space
  • Sans-serif fonts
  • Flat colors or monochrome
  • ZodiacFonts sans-serif style glyphs

Dark Theme (for web):

  • Dark background (matching dashboard dark theme: #0f1117)
  • Light glyphs and text
  • Accent colors that work on dark

5. ZodiacFonts.com — Resource Evaluation

URL: https://www.zodiacfonts.com/ License: Free tier under SIL OFL (Open Font License). Pro license for premium exclusives.

What they offer:

  • 101 free astrology symbols as fonts + SVG + PNG
  • Coverage: zodiac signs (12 + Ophiuchus), planets (Sun through Pluto + asteroids), houses, aspects, dwarf planets, lunar phases
  • Styles: sans-serif and slab-serif
  • Weights: light, regular, bold
  • Formats: font files (TTF/OTF), individual SVG files, PNG

How we'd use this:

  1. Use the font files directly — embed via @font-face in CSS, render zodiac glyphs with a single unicode character. This is the cleanest approach for both web SVG and WeasyPrint PDF generation.
  2. Use individual SVGs as fallback — embed as <image> or inline <svg> in the chart wheel for planet markers.
  3. The sans-serif regular style works best for clean modern charts; the slab-serif for traditional style.

Integration plan:

  • Download the free font pack at build/install time
  • Store font files in static/fonts/ directory
  • CSS: @font-face { font-family: 'ZodiacFont'; src: url('/static/fonts/zodiac-sans-regular.ttf'); }
  • Planet glyphs referenced via unicode PUA (Private Use Area) codepoints
  • Fallback to standard unicode astrological symbols (♈♉♊...) if font missing

Code point mapping (to verify from the actual font):

Zodiac signs:    ♈ ♉ ♊ ♋ ♌ ♍ ♎ ♏ ♐ ♑ ♒ ♓  (U+2648..U+2653)
Planets:         ☉ ☽ ☿ ♀ ♃ ♄ ♅ ♆ ♇ ⚳ ⚷ ⚴ ⚵ ⚶  (various unicode)
Aspects:         ☌ ⚹ △ □ ⚻ ☍                        (U+260C, U+26B9, etc.)

6. Technical Architecture

6.1 Rendering Engine: Pure SVG Generation (SVGWrite)

Recommended approach: Use svgwrite (Python library) to programmatically generate SVG chart wheels directly on the server side.

Why SVGWrite over alternatives:

  • Already lightweight, pure Python — no heavy dependencies
  • SVG is scalable, works for both web and print
  • WeasyPrint (already installed!) can convert SVG -> PDF natively
  • Python 3.13 compatible
  • Completely programmatic — we control every element
  • Dashboard already serves Jinja2 templates — SVG can be inline or standalone

Alternative considered:

  • matplotlib (already installed) — possible but designed for data plots, not radial astrology charts. Aspects would be hacky. Possible for aspect grid heatmaps.
  • Playwright + HTML template — overkill, adds Chromium dependency
  • Cairo (pycairo) — graphics library, powerful but lower-level than SVGWrite
  • Client-side JavaScript (D3.js / Canvas) — ideal for interactive web charts, but won't work for print/PDF on the server side. Could complement server-side.

6.2 Proposed Architecture

                        ┌─────────────────────┐
                        │   MCP Tool (data)    │
                        │  calculate_natal_    │
                        │  chart / transit /   │
                        │  synastry / etc.     │
                        └────────┬────────────┘
                                 │ JSON data
                                 ▼
                        ┌─────────────────────┐
                        │   Chart Renderer     │
                        │  (new module:        │
                        │   chart_renderer.py) │
                        │                      │
                        │  - wheel SVG gen     │
                        │  - aspect grid SVG   │
                        │  - planet table SVG  │
                        │  - style engine      │
                        │  - color themes      │
                        └────────┬────────────┘
                                 │ SVG string
                    ┌────────────┼─────────────┐
                    ▼                           ▼
          ┌──────────────┐           ┌──────────────────┐
          │  Web Route    │           │  PDF Export       │
          │  (inline SVG  │           │  (WeasyPrint      │
          │   in HTML)    │           │   SVG -> PDF)     │
          └──────────────┘           └──────────────────┘

6.3 New Files to Create

src/astro_mcp/
  chart_renderer.py    — Main rendering module
  chart_styles.py      — Theme/style definitions (colors, fonts, line styles)
  chart_templates/     — (optional) Jinja2 templates for HTML wrapping

static/
  fonts/               — ZodiacFonts TTF files
  chart-colors.yaml    — User-configurable color themes

templates/
  chart-wheel.html     — Standalone chart display page
  chart-aspects.html   — Aspect table page
  chart-print.html     — Print-optimized layout

docs/
  chart-rendering-proposal.md  ← this file

6.4 New MCP Tools (optional)

New tools that return chart data ready for rendering, or even render and return SVG/PDF directly:

@mcp.tool()
async def render_chart(
    chart_data: dict,        # output from calculate_natal_chart etc.
    format: str = "svg",     # "svg" | "pdf" | "png"
    style: str = "modern",   # "modern" | "traditional" | "minimal"
    color_mode: str = "color" | "bw",
    include_aspects: bool = True,
    include_table: bool = True,
) -> dict:
    """Render an astrological chart wheel as SVG, PDF, or PNG.
    
    Returns the rendered chart as base64-encoded data or saves to file
    and returns the path.
    """

6.5 New HTTP Routes (Dashboard Integration)

GET  /dashboard/charts/person/{id}         — Select chart type + options
GET  /dashboard/charts/person/{id}/natal   — Render natal chart wheel
GET  /dashboard/charts/person/{id}/transit?date=... — Transit bi-wheel
GET  /dashboard/charts/compare/{id1}/{id2} — Synastry bi-wheel
GET  /dashboard/charts/aspects/{id}         — Aspect grid/table

Each route accepts query params:

  • format=svg|pdf|png (default: inline SVG)
  • style=modern|traditional|minimal
  • color=color|bw (default: color for web, bw for pdf)
  • width=800 (SVG pixel width)
  • house_system=placidus

7. SVG Chart Wheel Construction Details

7.1 Coordinate System

  • Center: (cx, cy) — center of the wheel
  • Radius: configurable (default ~200px for 400x400 SVG)
  • Zodiac ring: outer band, divided into 12 segments of 30 degrees each
    • 0° = top (standard orientation, or ASC at top for house-aligned)
  • House sectors: from center out, divided by cusp longitudes
  • Planet positions: placed at radius between ring and center, at their ecliptic longitude angle

7.2 Angle Convention

  • Standard: 0° Aries at the left (traditional "9 o'clock" position), increasing counterclockwise
  • Or: ASC at top (90°), then houses increase counterclockwise
  • We should support both orientations

7.3 Element Layers (bottom to top)

  1. Background circle
  2. Zodiac ring (12 sign segments with glyphs)
  3. House sectors (from center to zodiac ring)
  4. House cusp lines + degree labels
  5. Aspect lines (between planets)
  6. Planet markers (glyphs + labels)
  7. Angles labels (ASC, MC, DSC, IC)
  8. Title/legend area
  9. Optional: chart info (name, date, location)

7.4 Aspect Line Coding

Aspect Color (web) Line style (B&W) Symbol
Conjunction Red (#e74c3c) Solid (2px)
Sextile Blue (#3498db) Dotted (1px)
Square Red (#c0392b) Dashed (2px)
Trine Green (#2ecc71) Dashed (2px)
Quincunx Orange (#e67e22) Dash-dot (1px)
Opposition Red (#e74c3c) Solid (2px)

Colors fully customizable per theme.


8. Integration with Existing Tools

8.1 Flow for "Generate My Chart"

1. call calculate_natal_chart(birth_data, include_overview=true, include_patterns=true)
   → get full chart JSON

2. pass JSON to chart_renderer.render_wheel(chart_data, style="modern", color="color")
   → get SVG string

3. either:
   a. embed SVG inline in Jinja2 template → HTML page (web dashboard)
   b. pass SVG to WeasyPrint → PDF (download/print)
   c. use cairosvg to convert SVG → PNG (thumbnail/preview)

8.2 Caching Strategy

  • Chart data is deterministic for a given birth time + location + house system
  • Cache rendered SVGs keyed by (person_id, chart_type, style, color_mode, options)
  • Invalidate when person data changes
  • Same enrichment caching pattern as news-mcp: compute once, store forever (the chart doesn't change unless the underlying data changes)

8.3 Dashboard Person Detail Enhancement

The existing /dashboard/persons/{id} page shows person data but no chart. Add a tab or section:

  • "Chart" tab showing the natal wheel
  • Controls for style, color mode, download as PDF/PNG
  • Transit slider (pick a date, see transit bi-wheel)

9. User-Configurable Themes

9.1 Configuration File (chart-colors.yaml)

# Default color theme
zodiac_signs:
  fire:    "#e74c3c"
  earth:   "#27ae60"
  air:     "#f39c12"
  water:   "#3498db"

aspect_colors:
  conjunction:  "#e74c3c"
  sextile:      "#3498db"
  square:       "#c0392b"
  trine:        "#2ecc71"
  quincunx:     "#e67e22"
  opposition:   "#e74c3c"

# B&W theme
bw:
  aspect_styles:
    conjunction:  { stroke: "#000", stroke_width: 2, dasharray: "none" }
    sextile:      { stroke: "#000", stroke_width: 1, dasharray: "3,3" }
    square:       { stroke: "#000", stroke_width: 2, dasharray: "6,3" }
    trine:        { stroke: "#000", stroke_width: 2, dasharray: "6,3" }
    quincunx:     { stroke: "#000", stroke_width: 1, dasharray: "6,3,2,3" }
    opposition:   { stroke: "#000", stroke_width: 2, dasharray: "none" }

# Dark theme (web)
dark:
  background: "#0f1117"
  text: "#c9d1d9"
  ring_fill: "#161b22"
  ring_stroke: "#30363d"

# Light theme (print)
light:
  background: "#ffffff"
  text: "#000000"
  ring_fill: "#f8f4e8"   # parchment
  ring_stroke: "#8b7355"

10. PDF Export Details

Method: SVG → WeasyPrint → PDF

  • WeasyPrint is already installed (v68.1)
  • Generates the chart as SVG, wraps in minimal HTML, converts to PDF
  • Supports:
    • A4, Letter, and custom page sizes
    • Embedded fonts (ZodiacFonts via @font-face)
    • Footer with chart info, date generated
    • Multi-page: chart wheel on page 1, aspect table on page 2, planet data on page 3

PDF Layout

Page 1: Title + Chart Wheel
┌──────────────────────────────┐
│  John Doe — Natal Chart      │
│  1965-07-02 00:05 GMT+1     │
│  Graz, Austria                │
│                               │
│       [  CHART WHEEL  ]       │
│                               │
│  Placidus | Tropical          │
└──────────────────────────────┘

Page 2: Aspect Table
┌──────────────────────────────┐
│  Aspect Grid                  │
│  [ colored/symbol grid ]      │
│                               │
│  Tightest Aspects:            │
│  Sun ☌ Moon  0°32'           │
│  Mars △ Jupiter 1°15'        │
│  ...                          │
└──────────────────────────────┘

Page 3: Planet & House Data
┌──────────────────────────────┐
│  Planet Positions             │
│  Sun    Leo    9°23'   10H   │
│  Moon   Cancer 22°17'  9H   │
│  ...                          │
│                               │
│  House Cusps                  │
│  ASC  Virgo    28°41'         │
│  MC   Gemini   25°12'         │
│  ...                          │
└──────────────────────────────┘

11. Implementation Phases

Phase 1: Foundation

  • Add svgwrite dependency
  • Create chart_styles.py with theme definitions
  • Create chart_renderer.py with basic wheel SVG generation
    • Zodiac ring with 12 segments and glyph labels
    • House sector divisions
    • Planet glyphs placed at correct angles
  • Verify with a simple natal chart (test data)

Phase 2: Aspect Lines + B&W Support

  • Draw aspect lines between planets (gray, by type)
  • Implement B&W line styles (solid/dashed/dotted per aspect)
  • Add retrograde marking
  • Add angle labels (ASC, MC, DSC, IC)

Phase 3: Color Themes + Print

  • Implement color theme system
  • Add zodiac sign element coloring
  • PDF export via WeasyPrint
  • B&W print-optimized layout

Phase 4: Additional Chart Types

  • Bi-wheel (transit chart)
  • Synastry side-by-side
  • Aspect grid/table
  • Planet/house data tables

Phase 5: Dashboard Integration

  • Add chart tab to person detail page
  • Style/color mode selector
  • PDF download button
  • Transit date picker with live preview

Phase 6: Polish

  • Traditional / old-fashioned style variant
  • Custom color theme editor in dashboard
  • Caching of rendered charts
  • Performance tests (render 100 charts under X seconds)

12. Open Questions / Decisions Needed

  1. Orientation: Traditional (0° Aries left) or ASC-at-top? Support both?
  2. Font strategy: Download ZodiacFonts at setup time, or bundle a subset? → Recommend: download at pip install / first run, cache in static/fonts/
  3. Ophiuchus: Support optional 13-sign zodiac? → Phase 2+, configurable
  4. Chart wheel sizing: Fixed sizes (S/M/L) or fully responsive? → SVG is inherently scalable; generate at request time, scale in browser
  5. Client-side interactivity: Pure server SVG, or add JS for tooltips/zoom? → Phase 1: pure server SVG. Phase 5: add optional JS enhancement.
  6. Person info on chart: Show name, birth date, location on the chart image? → Yes, configurable: show_info=true/false, per privacy setting

13. Real-World Examples to Study

  • astro.com charts — the gold standard for readability
  • astro-seek.com — clean modern SVG charts
  • Solar Fire (desktop) — professional traditional charts
  • OpenAstro.org (R. Rottenseifner) — open-source Python astro calculations
  • 瑞士Ephemeris sample charts — B&W laser-printed from SwissEph

End of document — ready for review.