f83db2fac1
- add external validation reports and open-source comparison references - integrate Jaimini arudha/graha pada, enhanced argala, and additional synastry kutas - update skill docs and capability matrices - add smoke tests for open-source integrations
98 lines
3.1 KiB
Python
98 lines
3.1 KiB
Python
import math
|
|
from .constants import TITHI_NAMES, VARA_NAMES, VARA_LORDS, PANCHANG_YOGA_NAMES, KARANA_NAMES
|
|
from .nakshatra import get_nakshatra
|
|
|
|
|
|
def calculate_panchang(jd, sun_lon, moon_lon, lat=None, lon=None):
|
|
"""
|
|
Calculate the five Panchang elements for a given moment.
|
|
|
|
Parameters
|
|
----------
|
|
jd : float
|
|
Julian Day number
|
|
sun_lon : float
|
|
Sidereal longitude of the Sun (0-360)
|
|
moon_lon : float
|
|
Sidereal longitude of the Moon (0-360)
|
|
|
|
Returns
|
|
-------
|
|
dict with tithi, vara, nakshatra, yoga, karana
|
|
"""
|
|
# --- Tithi ---
|
|
diff = (moon_lon - sun_lon) % 360.0
|
|
tithi_num = int(diff / 12.0) # 0-29
|
|
paksha = "Shukla" if tithi_num < 15 else "Krishna"
|
|
tithi_name = TITHI_NAMES[tithi_num]
|
|
|
|
# --- Vara (weekday) ---
|
|
# Julian Day 0 = Monday in many conventions; swe.julday for J2000 epoch
|
|
# JD 2451545.0 (2000-01-01 12:00 UT) was a Saturday
|
|
# weekday = (JD + 1.5) % 7 => 0=Mon, 1=Tue, ... 6=Sun (Julian convention)
|
|
day_idx = int(math.floor(jd + 0.5)) % 7
|
|
|
|
# Correct for local sunrise if lat/lon provided
|
|
if lat is not None and lon is not None:
|
|
try:
|
|
import swisseph as swe
|
|
swe.set_topo(lon, lat, 0)
|
|
# Find the sunrise for the current civil day UT
|
|
jd_midnight = math.floor(jd - 0.5) + 0.5
|
|
res, tret = swe.rise_trans(jd_midnight, swe.SUN, "", swe.CALC_RISE, (lon, lat, 0.0))
|
|
sunrise_jd = tret[0]
|
|
# If born before today's sunrise, the Vedic day is yesterday
|
|
if jd < sunrise_jd:
|
|
day_idx = (day_idx - 1) % 7
|
|
except Exception:
|
|
pass
|
|
|
|
# JD 0 = Monday (Julian proleptic). Map: 0=Mon,1=Tue,...6=Sun
|
|
vara = VARA_NAMES[day_idx]
|
|
vara_lord = VARA_LORDS[day_idx]
|
|
|
|
# --- Nakshatra (Moon's) ---
|
|
nak = get_nakshatra(moon_lon)
|
|
|
|
# --- Yoga (Panchang Yoga) ---
|
|
yoga_val = (sun_lon + moon_lon) % 360.0
|
|
yoga_idx = int(yoga_val / (360.0 / 27.0))
|
|
if yoga_idx >= 27:
|
|
yoga_idx = 26
|
|
yoga_name = PANCHANG_YOGA_NAMES[yoga_idx]
|
|
|
|
# --- Karana ---
|
|
# Each tithi has 2 karanas (half-tithi = 6 degrees of Sun-Moon distance)
|
|
karana_num = int(diff / 6.0) # 0-59
|
|
if karana_num == 0:
|
|
karana_name = KARANA_NAMES[10] # Kimstughna (first half of Shukla Pratipada)
|
|
elif karana_num >= 57:
|
|
# Last 3 are fixed karanas: Shakuni(57), Chatushpada(58), Nagava(59)
|
|
fixed_idx = karana_num - 57 + 7 # maps to indices 7,8,9
|
|
karana_name = KARANA_NAMES[fixed_idx]
|
|
else:
|
|
# Repeating cycle of first 7 karanas (Bava through Vishti)
|
|
karana_name = KARANA_NAMES[(karana_num - 1) % 7]
|
|
|
|
return {
|
|
"tithi": {
|
|
"number": tithi_num + 1,
|
|
"name": tithi_name,
|
|
"paksha": paksha,
|
|
},
|
|
"vara": {
|
|
"name": vara,
|
|
"lord": vara_lord,
|
|
},
|
|
"nakshatra": {
|
|
"name": nak["name"],
|
|
"pada": nak["pada"],
|
|
"lord": nak["lord"],
|
|
},
|
|
"yoga": {
|
|
"index": yoga_idx,
|
|
"name": yoga_name,
|
|
},
|
|
"karana": karana_name,
|
|
}
|