SuperAPI AI Directory

vedic-calculator

Data & analytics

View repository

Updated 10-15 20:13

About this skill

vedic-calculator: Vedic astrology chart engine

Language contract / 语言契约

  • Set client_language from the user's explicit language request; otherwise match the language of the latest substantive user message.
  • Use client_language for all chat replies, intake questions, confirmations, progress updates, user-visible warnings, reports, and Q&A. Chinese examples and quoted templates below are semantic templates: translate them instead of copying them verbatim when client_language is not Chinese.
  • Keep canonical filenames, CLI flags, JSON keys, structured_data.md schema headings, technical codes, and Sanskrit/English identifiers unchanged. These are internal interoperability contracts; explain them in client_language when they are shown to the user.
  • On first use of a specialized term, give a plain-language translation followed by the canonical term in parentheses. Never translate canonical identifiers inside calculations or evidence citations.
  • If the user changes language mid-run, preserve the existing data and artifact lineage; switch client-facing language from that point onward unless the user explicitly asks to regenerate earlier artifacts.
  • When client_language is Japanese, read resources/ja-calculator.md completely before the first Japanese client-facing message. Apply it only as a terminology, register, intake, and rendering layer; it never changes calculations, schemas, evidence, phases, or output requirements.

Based on the pysweph astronomical engine + PyJHora precise algorithms, it calculates the complete chart data directly from the birth time. The output format is fully compatible with vedic-reader's structured_data.md and can be handed directly to vedic-core for analysis.

Prerequisites

  • Python 3.8 ~ 3.13 (pysweph is a C extension,3.14 is not currently supported)
  • Dependencies: pysweph, PyJHora==4.8.6, pytz

⚠️ Do not directly pip install -r requirements.txt! PyJHora does not declare its runtime dependencies, and the pip package lacks the .se1 ephemeris files. Please use setup_env.py for automatic installation (see below).

Automatic environment detection

运行前检查依赖是否可用(按优先级):

  1. 检查 <skill目录> 或工作目录下是否有已有 venv/:
     - <skill目录>/venv/
     - <工作目录>/vedic-calc-env/
     - <工作目录>/venv/
     找到 → 用其 Python 运行 → 尝试 import swisseph → 成功 → 直接使用

  2. 尝试当前 Python import swisseph:
     - 成功且 swe.version 不是 '0.0.0' → 直接使用
     - 失败或空壳 → 继续

  3. 自动创建 venv(运行 setup_env.py):
     <合适的Python> <skill目录>/scripts/setup_env.py
     脚本会自动:检测 Python 版本 → 创建 venv → 按正确顺序安装 → 验证 SAV=337

⚠️ <skill目录> = the installation path of the vedic-calculator skill; the AI fills this in automatically based on the actual environment. ⚠️ If the system default Python is 3.14, setup_env.py will automatically look for 3.12/3.13 to create the venv.

⚠️ On first use, the environment diagnosis must be run first

在新机器/新环境首次使用 vedic-calculator 前,必须先运行:

  python <skill目录>/scripts/check_env.py

该脚本会自动检查:
  ✅ venv 位置和 Python 版本
  ✅ 3个核心依赖(pysweph/PyJHora/pytz)
  ✅ swisseph 空壳检测
  ✅ 星历表文件
  ✅ 最小计算测试(SAV=337)

如果输出 🎉 → 直接使用它报告的 Python 路径
如果输出 ⚠️ → 按提示运行 setup_env.py 修复

注意:check_env.py 本身可以用任何 Python 版本运行(包括3.14),
它会自动找到正确的 venv Python 来做依赖检查。

Usage workflow

Step 1: Collect birth information

Collect from the user:

- 出生日期 (YYYY-MM-DD)
- 出生时间 (HH:MM,24小时制)
- 出生地点 (城市名)
- 性别
- 感情状态(可选)
- 时间精度(精确到分钟 / ±15分钟 / ±1小时 / 不确定)
- 时间来源(出生证 / 家人记忆 / 大概回忆 / 未追问)

⚠️ Daylight saving time confirmation (required when the birth date falls within the local daylight saving period, such as mainland China from mid-April to mid-September each year from 1986-1991):

向用户输出一句确认(默认=墙上钟,绝大多数记录是当时钟表显示时间):
"您出生时当地正实行夏令时。您提供的时间是当时钟表显示的时间吗?(通常是,直接回'是'即可)
 若家里记录的是未拨快的'标准时/北京时间',请说明。"
→ 墙上钟(默认)→ 正常排盘(引擎 pytz 自动按夏令时换算 UTC,正确)
→ 用户声明标准时 → 用固定时区排盘(如中国用 'Etc/GMT-8' 替代 'Asia/Shanghai'——
   注意 Etc 时区符号反转,GMT-8 即 UTC+8),并在备注记录"用户声明标准时"
排盘后 structured_data 元信息会自动带"夏令时"标注行,供用户核对。

Step 2: AI converts geographic coordinates

Based on the city name provided by the user, the AI directly fills in:

  • Latitude (lat)
  • Longitude (lon)
  • Time zone string (tz_str)

Common references:

北京:     39.9042, 116.4074, "Asia/Shanghai"
上海:     31.2304, 121.4737, "Asia/Shanghai"
广州:     23.1291, 113.2644, "Asia/Shanghai"
成都:     30.5728, 104.0668, "Asia/Shanghai"
台北:     25.0330, 121.5654, "Asia/Taipei"
香港:     22.3193, 114.1694, "Asia/Hong_Kong"
新德里:   28.6139, 77.2090,  "Asia/Kolkata"
孟买:     19.0760, 72.8777,  "Asia/Kolkata"

⚠️ All of China uses "Asia/Shanghai" (UTC+8) ⚠️ All of India uses "Asia/Kolkata" (UTC+5:30)

Step 3: Run the engine

Create a calculation script in the working directory and execute it:

import sys, os

# ⚠️ 动态路径:AI根据skill安装位置自动填写
# Claude Code 示例: ~/.claude/skills/vedic-calculator/scripts
# 其它客户端: 换成该客户端实际的 skill 安装目录下的同名路径
SCRIPTS_DIR = r"<vedic-calculator skill 的 scripts 目录绝对路径>"
sys.path.insert(0, SCRIPTS_DIR)

from engine import calculate_full_chart
from transit import calc_transit
from formatter import format_structured_data

# 计算本命盘
chart = calculate_full_chart(
    year=YYYY, month=MM, day=DD, 
    hour=HH, minute=MM,
    lat=LAT, lon=LON, 
    tz_str="TIMEZONE",
    # 按“有效精度”传入:出生证分钟记录至少审计±1;家人明确记忆通常5;
    # ±15分钟报时传15。它审计输入稳定性,不改变报时本身。
    uncertainty_minutes=1
)

# 计算当前过运
transit = calc_transit(
    chart['lagna']['sign_idx'],
    chart['planets']['Moon']['sign_idx'],
    "TIMEZONE"
)

# 元信息
meta = {
    'dob': 'YYYY-MM-DD',
    'time': 'HH:MM',
    'place': '城市名',
    'lat': LAT, 'lon': LON,
    'time_precision': '精确到分钟',
    'time_source': '未追问'
}

# 用户信息
user_info = {
    'gender': '男/女',
    'relationship': '单身/恋爱中/已婚'
}

# 生成structured_data.md
md = format_structured_data(chart, transit, meta, user_info)
with open(r"WORKDIR\structured_data.md", 'w', encoding='utf-8') as f:
    f.write(md)

# ⚠️ 正确的 SAV 验证方式(不要自己猜 key!)
SIGNS = ['Aries','Taurus','Gemini','Cancer','Leo','Virgo','Libra','Scorpio','Sagittarius','Capricorn','Aquarius','Pisces']
sav_total = sum(chart['sav'].get(s, 0) for s in SIGNS)
print(f"✅ SAV total: {sav_total}")
assert sav_total == 337, f"SAV FAILED: {sav_total} != 337"

Execution command (the AI automatically selects Python based on the environment):

# 优先级:skill目录下的venv → 系统Python
# Windows:  <skill目录>\venv\Scripts\python.exe SCRIPT_PATH
# Linux/Mac: <skill目录>/venv/bin/python SCRIPT_PATH
# 都没有venv: python SCRIPT_PATH(需已全局安装依赖)

⚠️ It is forbidden to write your own print to read chart data! You must use formatter.py to output structured_data.md. For the chart data structure, see “engine return data structure” below.

Step 4: Validate the output

Check the generated structured_data.md:

  1. SAV total = 337 ✅
  2. Planet completeness = 10 planets ✅
  3. Ra-Ke difference 180° ✅
  4. Whether the Lagna sign is reasonable
  5. Vimsottari = 9 MD segments, 81 AD segments, 729 PD segments, and each layer [start,end) seamlessly continuous ✅
  6. Divisional chart boundary audit: read分盘可信度声明, and confirm whether D1/D9/D10/D4/D5 are “stable” or “boundary-sensitive” within the valid precision interval. It is forbidden to automatically write all divisional charts as trustworthy because of “birth certificate” or “direct calculation”; the two respectively represent the source of the record and mathematical reproducibility, not stability under input perturbation.

Hard constraints for divisional chart consumption:

  • ✅ 审计区间内稳定: the corresponding divisional chart can be used normally according to the current Lagna;
  • ⚠️ 边界敏感: retain the calculation table for the given moment, but the divisional chart houses, internal house lords, and all downstream pattern conclusions must be conditionalized or downgraded;
  • Legacy structured_data lacking a boundary audit: mark as “unverified” and do not supplement it as highly trustworthy;
  • When the birth certificate does not state whether what was recorded was the cry, the delivery, the cord clamping, or an entry made after the fact, the semantic meaning of the time remains unknown.

Hard constraints on time resolution:

  • When reading only MD, output only background trends;
  • When reading MD×AD, output at most the stage window;
  • When the user requests a monthly or narrower-than-AD window, MD×AD×PD must be read;
  • When PD is missing or verification fails, stop month-level determination; it is forbidden to use AD or a 365.25-day approximation to fabricate month-level precision.

Step 4.5: Three-tier progressive reading (does not modify canonical data)

Normal Calculator chart casting must still compute, verify, and write the complete set in one pass9 MD + 81 AD + 729 PD. Progressive reading optimizes the downstream model context, not deleting data, computing less, or changing the timeline.

Downstream reader/rectifier/core/core-pro/QA all consume in three tiers:

  1. MD background layer: first determine the major life stages;
  2. AD stage layer: then determine domain candidates and event stages;
  3. PD micro-trigger layer: read only when the user requests month/day, when the actual output is narrower than the complete AD, or when adjacent AD/PD handoffs would change the conclusion.

It is forbidden by default to sendstructured_data.mdthe full 729-row PD table into the model context. Use deterministic tools:

# 默认读盘:输出全部非PD数据与MD/AD,折叠729行PD
python <calculator>/scripts/dasha_query.py --file structured_data.md --overview

# 完整性校验:只输出校验结果,不展开PD
python <calculator>/scripts/dasha_query.py --file structured_data.md --check

# 月级下钻:只返回命中的PD与相邻上下文
python <calculator>/scripts/dasha_query.py --file structured_data.md --month 2023-06 --context 1

# 日级或自定义[start,end)窗口
python <calculator>/scripts/dasha_query.py --file structured_data.md --date 2023-06-15 --context 1
python <calculator>/scripts/dasha_query.py --file structured_data.md --start 2023-05-01 --end 2023-07-01 --context 1

When comparing candidates, first complete the MD/AD matrices for all candidates using the same method, lock inallcandidates that still require PD differentiation, and only then drill down uniformly. It is forbidden to read PD for only the currently favored candidate, and forbidden to read through all 729 rows and then work backward to pick the window that looks most like the answer.

Step 5: Mode selection

After structured_data.md is generated, output to the user:

✅ 排盘完成!所有数据已生成(行星/分盘/SAV/Dasha大运+小运+三级运/宫主表/尊贵度/过运…)

📊 Shadbala 精度说明:
   structured_data以calc为主数据源。
   Shadbala始终先写入calc基准值。如没有JHora PDF,直接采用calc。
   如有同一出生时间生成的JHora PDF,则逐行对照并展示PDF值;
   二者不一致时会明确提示"当前采用PDF"。其余PDF数据只用于交叉验证。

下一步:
  a) 直接进入验前事(推荐)
  b) 发送 JHora PDF 补充 Shadbala

After chart casting is complete, do not insert the Little Fire Person profile export into the normal a/b flow above. First let the user continue with the flow above, and only add one optional hint at the end of the message: "If you want to bring this chart into Little Fire Person, you can say 'organize a profile that can be copied to Little Fire Person'." Only when the user explicitly makes a request such as "Little Fire Person profile", "copyable profile", "relationship profile", or similar, enter the export branch; ordinary chart-casting users do not automatically receive extra long profiles.

  • User selects a) or says "analyze directly"/"start" → trigger vedic-reader (streamlined mode: skip extraction, directly read structured_data → verify past events)

  • User sends PDF → verify consistency of birth information → extract valid Shadbala from the PDF text layer → compare line by line with calc Shadbala → for lines present in the PDF, display the PDF values, and mark and alert the user to differing lines → for lines missing from the PDF, keep calc → other PDF data is only cross-validated → then trigger reader to verify past events

  • User explicitly requests Little Fire Person profile → keep the generated canonical structured_data.md unchanged, run scripts/make_xiaohuo_person_card.py structured_data.md, and send the xiaohuo-person-v1 plain text paragraph returned by stdout directly to the user; do not generate images, do not require the user to open or understand files, and do not treat the profile card as a new chart-casting result. When used by two people, each person casts their chart separately and generates a separate personal profile, then paste them in the two-person conversation labeled A/B. The export includes explicit Lagna, the current MD/AD/PD, and a dated slow-planet transit snapshot; the exporter does not call the ephemeris, and does not change an old snapshot to today. If the user requests real transits for the current day and the source file date has expired, the full Calc must be rerun before exporting; it is not allowed to rerun only the exporter or manually change the date.

engine return data structure

⚠️ Required reading! Do not guess key names. The following is the dict structure returned by calculate_full_chart() .

chart = {
    # 基础天文
    'ayanamsa': 23.8982,           # float, True Chitra ayanamsa 度数(约23.9°,与Lahiri差<1′)
    'lagna': {
        'sign': 'Cancer',          # str, 英文星座名
        'sign_idx': 3,             # int, 0-indexed (Aries=0)
        'degree': 13.61,           # float, 绝对度数 (星座内)
        'deg_str': "13°36'",       # str, 格式化度分
        'longitude': 103.61,       # float, 黄道经度
        'nakshatra': {'name': 'Pushya', 'pada': 4, 'lord': 'Saturn'}
    },
    'planets': {
        'Sun': {
            'sign': 'Scorpio', 'sign_idx': 7,
            'degree': 25.41, 'deg_str': "25°24'",
            'longitude': 235.41,
            'house': 5,            # int, 1-indexed 从 Lagna 数
            'retrograde': False,
            'nakshatra': {'name': 'Jyeshtha', 'pada': 3, 'lord': 'Mercury'}
        },
        # ... Moon, Mars, Mercury, Jupiter, Venus, Saturn, Rahu, Ketu 同结构
    },

    # SAV — ⚠️ key 是英文星座名,不是 'by_sign'!
    'sav': {
        'Aries': 36, 'Taurus': 34, 'Gemini': 22, 'Cancer': 28,
        'Leo': 34, 'Virgo': 29, 'Libra': 29, 'Scorpio': 25,
        'Sagittarius': 32, 'Capricorn': 20, 'Aquarius': 26, 'Pisces': 22
    },
    'sav_by_house': {
        1: {'sign': 'Cancer', 'value': 28},  # 按宫位编号
        # ... 2-12 同结构
    },

    # BAV
    'bav': {
        'Sun': {'Aries': 6, 'Taurus': 5, ...},  # 12星座
        # ... Moon, Mars, Mercury, Jupiter, Venus, Saturn
    },

    # Shadbala — ⚠️ 用 strength_pct (不是 strength_ratio)!
    'shadbala': {
        'Sun': {
            'total_60ths': 288.6,  'total_rupas': 4.81,
            'sthana': 82.0, 'kaala': 55.0, 'dig': 6.7,
            'cheshta': 44.9, 'naisargika': 60.0, 'drik': 40.0,
            'strength_pct': 96.2,  # ⚠️ 百分比,直接用!
            'classification': '弱',
            'ishta_phala': 7.64,   # Ishta Phala
            'kashta_phala': 50.18  # Kashta Phala
        },
        # ... Moon, Mars, Mercury, Jupiter, Venus, Saturn 同结构
    },

    # Dasha
    'dashas': [
        {
            'planet': 'Jupiter', 'start': '1998-02', 'end': '2014-02',
            'years': 16, 'is_current': False,
            'antardashas': [
                {
                    'planet': 'Jupiter',
                    'start': '1998-02-11', 'end': '2000-04-01',
                    'start_time': '1998-02-11 12:34', 'end_time': '2000-04-01 08:20',
                    'is_current': False,
                    'pratyantardashas': [
                        {
                            'planet': 'Jupiter',
                            'start': '1998-02-11', 'end': '1998-05-26',
                            'start_time': '1998-02-11 12:34', 'end_time': '1998-05-26 04:15',
                            'is_current': False
                        },
                        # ... 每个AD共9个PD
                    ]
                },
                # ... 9个小运
            ]
        },
        # ... 共9段大运
    ],

    # 分盘 — (sign_name, sign_idx) tuple
    'd9':  {'Lagna': ('Scorpio', 7), 'Sun': ('Aquarius', 10), ...},
    'd10': {'Lagna': ('Cancer', 3),  'Sun': ('Pisces', 11), ...},
    'd4':  {'Lagna': ('Libra', 6),   'Sun': ('Leo', 4), ...},
    'd5':  {'Lagna': ('Pisces', 11), 'Sun': ('Scorpio', 7), ...},
    'vargottama': {'Sun': False, 'Moon': False, 'Rahu': True, ...},
    'divisional_charts': {'D2': ..., 'D3': ..., ...},  # 额外分盘

    # 预分析
    'karakas': {'7k': [...], '8k': [...], 'dk_7k': 'Saturn', 'dk_8k': 'Rahu', 'dk_note': '7K(主)=Saturn, 8K(参考)=Rahu'},
    'dignity': {'Sun': {'compound': 'great_friend', ...}, ...},
    'aspects': [{'p1':'Rahu','p2':'Ketu','type':'对冲(180°)','degree_diff':'180.0'}, ...],
    'house_lords': {1: {'lord':'Moon','domain':'自我','lord_house':8}, ...},
    'special_points': {'AL': {'sign':'Virgo','house':3}, 'UL': {'sign':'Pisces','house':9}},
    'combustion': {},
    'moon_phase': {'waxing': True, 'sun_moon_diff': 88.6},
}

Output specification

The output structured_data.md contains the following data sections (fully matching data_contract.md):

Section Content
Meta information Birth time, place, Ayanamsa, chart reading method
Planetary positions 10 planets + Lagna, signs/houses/degrees/retrograde
Nakshatra Nakshatra + Pada for all planets
Chara Karakas 7K main table (KN Rao) + 8K reference
Shadbala Rupas/percentage/ranking/strength/Ishta/Kashta for 7 planets
SAV Raw values (by sign) + house mapping (by house)
BAV 7 planets × 12 signs matrix
Vimsottari Dasha 9 Mahadasha periods + 81 Antardasha periods + 729 Pratyantardasha periods; current MD/AD/PD
Special points AL(Arudha Lagna) + UL(Upapada Lagna)
Compound Dignity Panchadha Maitri (exaltation/moolatrikona/debilitation directly determined)
Graha Drishti Vedic planetary aspects (house casting: star→7th etc.; Western orb aspect table deprecated and removed)
House lord table Complete 12 houses
Divisional charts D9/D10/D4/D5 + Vargottama + birth-time uncertainty interval boundary audit
Validation 12 automatic validations
Transits Slow planet transits + Sade Sati + dual transits

Technical specifications

  • Ayanamsa: True Chitrapaksha (TRUE_CITRA)(fixed, unchangeable; belongs to the Lahiri system, difference <1′)
  • Node mode: Mean Node
  • Astronomical core: pysweph (Swiss Ephemeris C binding)
  • SAV/BAV: PyJHora native (ashtakavarga_pyjhora.py)
  • Dasha: PyJHora native MD/AD/PD (dasha_pyjhora.py); intervals uniformly follow[start,end), manual approximation to fill in the third-level dasha is prohibited
  • Shadbala: PyJHora + 9 corrections (shadbala_pyjhora.py)
  • Divisional charts: PyJHora native (divisional_pyjhora.py) — 15 charts D1~D60
  • Divisional chart stability: within the caller-provideduncertainty_minutesrecalculate D1/D9/D10/D4/D5 Lagna minute by minute mathematical correctness and input stability are reported separately
  • Dignity: self-built (exaltation/moolatrikona/debilitation determined first); combustion orb / directional strength house two tables inlined in engine.py
  • Chara Karakas: 7K (KN Rao) + 8K reference
  • Fault tolerance strategy: fail-fast(missing dependencies directly error out, no incorrect results given)

Relationship with other skills

路径1(纯calc,推荐):
  用户给出生信息 → vedic-calculator → structured_data.md → vedic-reader(验前事) → vedic-core

路径2(PDF + calc主数据):
  用户给PDF → reader提取出生信息 → calculator生成canonical structured_data
  → PDF交叉验证(仅有效Shadbala可覆盖)→ reader(验前事) → core

路径3(兜底):
  用户材料无法提供完整出生信息 → reader提取模式(标注降级)→ reader(验前事) → core

The structured_data.md format output by all paths is completely identical; core does not need to distinguish the data source.