th Claude commited on
Commit
6ef027d
·
1 Parent(s): 2a0571f

Add professional SVG chart generation with Kerykeion 5.x

Browse files

✨ New features:
- POST /api/generate-chart-svg endpoint
- Uses ChartDataFactory + ChartDrawer for professional visualization
- Includes aspects (相位线) and proper planet placement
- Returns SVG that can be directly embedded in frontend

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Files changed (1) hide show
  1. app.py +64 -1
app.py CHANGED
@@ -5,10 +5,14 @@ Just returns raw Kerykeion calculations
5
 
6
  from fastapi import FastAPI, HTTPException
7
  from fastapi.middleware.cors import CORSMiddleware
 
8
  from pydantic import BaseModel
9
- from kerykeion import AstrologicalSubject
 
 
10
  from typing import Optional, Any, Dict
11
  import logging
 
12
 
13
  logging.basicConfig(level=logging.INFO)
14
  logger = logging.getLogger(__name__)
@@ -118,6 +122,65 @@ async def calculate_chart(req: BirthRequest):
118
  logger.error(f"❌ Error: {e}")
119
  raise HTTPException(status_code=500, detail=str(e))
120
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  if __name__ == "__main__":
122
  import uvicorn
123
  # Hugging Face Spaces requires port 7860
 
5
 
6
  from fastapi import FastAPI, HTTPException
7
  from fastapi.middleware.cors import CORSMiddleware
8
+ from fastapi.responses import Response
9
  from pydantic import BaseModel
10
+ from kerykeion import AstrologicalSubject, AstrologicalSubjectFactory
11
+ from kerykeion.chart_data_factory import ChartDataFactory
12
+ from kerykeion.charts.chart_drawer import ChartDrawer
13
  from typing import Optional, Any, Dict
14
  import logging
15
+ import io
16
 
17
  logging.basicConfig(level=logging.INFO)
18
  logger = logging.getLogger(__name__)
 
122
  logger.error(f"❌ Error: {e}")
123
  raise HTTPException(status_code=500, detail=str(e))
124
 
125
+
126
+ @app.post("/api/generate-chart-svg")
127
+ async def generate_chart_svg(req: BirthRequest):
128
+ """Generate professional birth chart SVG with aspects"""
129
+ try:
130
+ logger.info(f"🎨 Generating SVG chart for: {req.name}")
131
+
132
+ year, month, day = map(int, req.date.split('-'))
133
+ hour, minute = map(int, req.time.split(':'))
134
+
135
+ # Use new Kerykeion 5.x API
136
+ subject = AstrologicalSubjectFactory.from_birth_data(
137
+ name=req.name,
138
+ year=year, month=month, day=day,
139
+ hour=hour, minute=minute,
140
+ lng=req.longitude or 0.0,
141
+ lat=req.latitude or 0.0,
142
+ tz_str=req.timezone,
143
+ zodiac_type="Tropic",
144
+ houses_system_identifier="P",
145
+ online=False
146
+ )
147
+
148
+ # Create chart data
149
+ chart_data = ChartDataFactory.create_natal_chart_data(subject)
150
+
151
+ # Generate SVG
152
+ chart_drawer = ChartDrawer(chart_data=chart_data)
153
+
154
+ # Get SVG content (ChartDrawer internally generates SVG)
155
+ # We need to save to a temp location then read it
156
+ import tempfile
157
+ from pathlib import Path
158
+
159
+ with tempfile.TemporaryDirectory() as tmpdir:
160
+ output_path = Path(tmpdir)
161
+ chart_drawer.save_svg(output_path=output_path, filename="chart")
162
+
163
+ svg_file = output_path / "chart.svg"
164
+ if not svg_file.exists():
165
+ raise HTTPException(status_code=500, detail="Failed to generate SVG")
166
+
167
+ svg_content = svg_file.read_text()
168
+
169
+ logger.info(f"✅ SVG generated for {req.name}")
170
+
171
+ return Response(
172
+ content=svg_content,
173
+ media_type="image/svg+xml",
174
+ headers={
175
+ "Content-Disposition": f'inline; filename="{req.name}-chart.svg"'
176
+ }
177
+ )
178
+
179
+ except Exception as e:
180
+ logger.error(f"❌ SVG Error: {e}")
181
+ raise HTTPException(status_code=500, detail=str(e))
182
+
183
+
184
  if __name__ == "__main__":
185
  import uvicorn
186
  # Hugging Face Spaces requires port 7860