完整数据版补上研究口径的推运、次小运和细分盘(#92)。
研究章在渲染时计算,不写入资料包。四种星座大运次小运和 Kalachakra 第三层不改原来的主运、子运。D81、D108、D144 只留在研究章。 自测:test_research_timing、星座大运、域读取、卫生预算、真恒星、jhora 扫描、API 增长、六章标题、英文版。三张虚构盘中英出稿都低于 180 秒。PyJHora 已导入但未做逐层对照。 Co-Authored-By: Grok (agent loop)
This commit is contained in:
co-authored by
Grok (agent loop)
parent
85e8adddbc
commit
d45e65a9ec
@@ -0,0 +1,474 @@
|
||||
"""Research timing for one chart. Nothing here is written onto the packet.
|
||||
|
||||
The in-process cache is keyed by birth inputs so the two report languages
|
||||
share one ephemeris pass. A failed family keeps its own reason and does not
|
||||
drop the chapter.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import time
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
import swisseph as swe
|
||||
|
||||
try:
|
||||
from research_timing.cycles import (
|
||||
TITHI_FORWARD,
|
||||
TITHI_REVERSE,
|
||||
karana_year,
|
||||
nakshatra_tribhagi,
|
||||
remap_angular,
|
||||
tithi_ashtottari,
|
||||
yoga_vimshottari,
|
||||
)
|
||||
from research_timing.families import (
|
||||
buddhi_gati,
|
||||
hora_sign_from_events,
|
||||
kaala_from_events,
|
||||
karana_seed,
|
||||
research_vargas,
|
||||
saptavarga_lords,
|
||||
sudasa_birth,
|
||||
sudasa_confirmed_anchor,
|
||||
varnada_jss,
|
||||
)
|
||||
from research_timing.frame import SiderealFrame, birth_jd
|
||||
from research_timing.search import (
|
||||
ElongationClock,
|
||||
containing_tithi,
|
||||
find_returns,
|
||||
hindu_solar_events,
|
||||
jd_to_utc,
|
||||
measure_elongation,
|
||||
)
|
||||
except ImportError: # pragma: no cover - package import
|
||||
from scripts.research_timing.cycles import (
|
||||
TITHI_FORWARD,
|
||||
TITHI_REVERSE,
|
||||
karana_year,
|
||||
nakshatra_tribhagi,
|
||||
remap_angular,
|
||||
tithi_ashtottari,
|
||||
yoga_vimshottari,
|
||||
)
|
||||
from scripts.research_timing.families import (
|
||||
buddhi_gati,
|
||||
hora_sign_from_events,
|
||||
kaala_from_events,
|
||||
karana_seed,
|
||||
research_vargas,
|
||||
saptavarga_lords,
|
||||
sudasa_birth,
|
||||
sudasa_confirmed_anchor,
|
||||
varnada_jss,
|
||||
)
|
||||
from scripts.research_timing.frame import SiderealFrame, birth_jd
|
||||
from scripts.research_timing.search import (
|
||||
ElongationClock,
|
||||
containing_tithi,
|
||||
find_returns,
|
||||
hindu_solar_events,
|
||||
jd_to_utc,
|
||||
measure_elongation,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
_CACHE: dict[tuple, dict] = {}
|
||||
_PLANETS = ("Sun", "Moon", "Mars", "Mercury", "Jupiter", "Venus", "Saturn", "Rahu", "Ketu")
|
||||
|
||||
|
||||
def research_bundle(chart: dict) -> dict:
|
||||
"""Compute every research family for one birth. ``chart`` is not retained."""
|
||||
key = _fingerprint(chart)
|
||||
cached = _CACHE.get(key)
|
||||
if cached is not None:
|
||||
return cached
|
||||
started = time.perf_counter()
|
||||
built = _build(chart)
|
||||
built["elapsed_seconds"] = time.perf_counter() - started
|
||||
_CACHE[key] = built
|
||||
return built
|
||||
|
||||
|
||||
def _build(chart: dict) -> dict:
|
||||
frame = SiderealFrame(chart["ayanamsa"], chart["node_mode"])
|
||||
natal_jd = birth_jd(chart["year"], chart["month"], chart["day"], chart["hour_decimal"], chart["tz"])
|
||||
sun, moon = frame.sun_moon(natal_jd)
|
||||
longitudes = dict(chart["longitudes"])
|
||||
ascendant = float(chart["ascendant"])
|
||||
epoch = chart["epoch"]
|
||||
year_days = float(chart["year_days"])
|
||||
query = chart["query"]
|
||||
families: dict[str, dict] = {}
|
||||
|
||||
def keep(name: str, producer) -> None:
|
||||
try:
|
||||
families[name] = producer()
|
||||
except (ValueError, RuntimeError, OverflowError, KeyError, TypeError) as exc:
|
||||
logger.warning("research timing %s failed: %s: %s", name, type(exc).__name__, exc)
|
||||
families[name] = {
|
||||
"status": "omitted",
|
||||
"periods": [],
|
||||
"reason_en": "This branch did not finish. The runtime log has the cause.",
|
||||
"reason_zh": "这一支没有算成,原因记在运行日志里。",
|
||||
}
|
||||
|
||||
keep("tithi-natal-forward", lambda: _mark(tithi_ashtottari(
|
||||
epoch, _tithi_number(sun, moon), _arc_remaining(sun, moon), 108 * year_days, TITHI_FORWARD, natal=True,
|
||||
), sun, moon))
|
||||
keep("tithi-natal-reverse", lambda: _mark(tithi_ashtottari(
|
||||
epoch, _tithi_number(sun, moon), _arc_remaining(sun, moon), 108 * year_days, TITHI_REVERSE, natal=True,
|
||||
), sun, moon))
|
||||
keep("yoga-natal", lambda: _mark(yoga_vimshottari(
|
||||
epoch, (sun + moon) % 360.0, 120 * year_days, natal=True, depth=3,
|
||||
), sun, moon))
|
||||
|
||||
annual = _annual_returns(frame, natal_jd, chart["target_year"])
|
||||
families["annual-returns"] = annual
|
||||
_attach_tithi_pairs(keep, frame, natal_jd, annual["returns"]["tithi"], sun, moon)
|
||||
_attach_pravesha(keep, frame, natal_jd, "yoga", annual["returns"]["yoga"], sun, moon)
|
||||
_attach_pravesha(keep, frame, natal_jd, "nakshatra", annual["returns"]["nakshatra"], sun, moon)
|
||||
keep("karana", lambda: _mark(_karana(frame, annual, chart, year_days), sun, moon))
|
||||
|
||||
keep("saptavarga", lambda: {"status": "calculated", "rows": saptavarga_lords(longitudes, ascendant), "birth_sun": sun, "birth_moon": moon})
|
||||
keep("buddhi-gati", lambda: _mark(buddhi_gati(int(ascendant // 30), longitudes, epoch, year_days), sun, moon))
|
||||
events = hindu_solar_events(epoch, chart["lat"], chart["lon"])
|
||||
keep("kaala", lambda: _mark(kaala_from_events(epoch, events, year_days), sun, moon))
|
||||
keep("sudasa-confirmed", lambda: _mark(sudasa_confirmed_anchor(), sun, moon))
|
||||
keep("sudasa-birth", lambda: _mark(sudasa_birth(ascendant, longitudes, epoch, year_days), sun, moon))
|
||||
hora = hora_sign_from_events(epoch, int(ascendant // 30), events)
|
||||
if hora.get("status") != "calculated":
|
||||
families["varnada"] = _mark(hora, sun, moon)
|
||||
else:
|
||||
built = varnada_jss(int(ascendant // 30), int(hora["sign_index"]), longitudes, epoch, year_days)
|
||||
families["varnada"] = {"status": "calculated", "variants": [_mark(item, sun, moon) for item in built], "birth_sun": sun, "birth_moon": moon}
|
||||
keep("research-vargas", lambda: {"status": "calculated", "rows": research_vargas(longitudes, ascendant), "birth_sun": sun, "birth_moon": moon})
|
||||
return {
|
||||
"birth_sun": sun,
|
||||
"birth_moon": moon,
|
||||
"birth_jd": natal_jd,
|
||||
"query": query.isoformat(),
|
||||
"target_year": chart["target_year"],
|
||||
"families": families,
|
||||
"reference_note_en": (
|
||||
"The reference instant is noon on the first day of the first listed report month. "
|
||||
"The packet does not keep a separate today field. "
|
||||
"Yoga and Nakshatra returns use the report target year. "
|
||||
"Tithi pairs use that year and the next two years."
|
||||
),
|
||||
"reference_note_zh": (
|
||||
"参考时刻取报告月历第一行的月份,当月 1 日正午。资料包没有另存阅读当天的时刻。"
|
||||
" Yoga 与 Nakshatra 的回归用这个目标年。 Tithi 配对用该年及后两年。"
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def _attach_tithi_pairs(keep, frame, natal_jd: float, rows: list[dict], sun: float, moon: float) -> None:
|
||||
"""Every 300–400 day pair. Three target years. Depth stays at two."""
|
||||
for index, row in enumerate(rows, start=1):
|
||||
year = int(row["year"])
|
||||
label = f"tithi-{year}-{index}"
|
||||
try:
|
||||
partners = _later_returns(frame, natal_jd, "tithi_pravesha", row["jd_ut"], 0.0, 400.0)
|
||||
partners = [item for item in partners if 300 <= item["jd_ut"] - row["jd_ut"] <= 400]
|
||||
except (ValueError, RuntimeError, OverflowError) as exc:
|
||||
logger.warning("research timing tithi pair failed: %s: %s", type(exc).__name__, exc)
|
||||
keep(label, lambda: _failed())
|
||||
continue
|
||||
if not partners:
|
||||
keep(label, lambda: {
|
||||
"status": "omitted",
|
||||
"periods": [],
|
||||
"reason_en": "No return falls between 300 and 400 days later, so this year is not listed.",
|
||||
"reason_zh": "之后 300 到 400 天里没有下一次回归,这一年不列表。",
|
||||
})
|
||||
continue
|
||||
stamp = jd_to_utc(row["jd_ut"])
|
||||
arc = _arc_remaining(row["sun_longitude"], row["moon_longitude"])
|
||||
number = _tithi_number(row["sun_longitude"], row["moon_longitude"])
|
||||
for pair_index, partner in enumerate(partners, start=1):
|
||||
span = float(partner["jd_ut"] - row["jd_ut"])
|
||||
for direction, name in ((TITHI_FORWARD, "forward"), (TITHI_REVERSE, "reverse")):
|
||||
keep(
|
||||
f"{label}-pair-{pair_index}-arc-{name}",
|
||||
lambda direction=direction, span=span, stamp=stamp, arc=arc, number=number: _mark(
|
||||
tithi_ashtottari(stamp, number, arc, span, direction, natal=False), sun, moon,
|
||||
),
|
||||
)
|
||||
keep(
|
||||
f"{label}-pair-{pair_index}-time-{name}",
|
||||
lambda direction=direction, span=span, stamp=stamp, number=number, jd=row["jd_ut"]: _mark(
|
||||
_tithi_elapsed(frame, jd, stamp, number, span, direction), sun, moon,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def _attach_pravesha(keep, frame, natal_jd: float, technique: str, rows: list[dict], sun: float, moon: float) -> None:
|
||||
"""Reference-year returns. Each successor in the next 300–400 days stays separate."""
|
||||
finder = "yoga_pravesha" if technique == "yoga" else "nakshatra_pravesha"
|
||||
for index, row in enumerate(rows, start=1):
|
||||
stamp = jd_to_utc(row["jd_ut"])
|
||||
try:
|
||||
successors = _later_returns(frame, natal_jd, finder, row["jd_ut"], 300.0, 400.0)
|
||||
except (ValueError, RuntimeError, OverflowError) as exc:
|
||||
logger.warning("research timing %s successor failed: %s: %s", technique, type(exc).__name__, exc)
|
||||
keep(f"{technique}-{index}-successor", lambda: _failed())
|
||||
keep(f"{technique}-{index}-tithi-year", lambda stamp=stamp, jd=row["jd_ut"]: _mark(
|
||||
_remap_year(frame, technique, stamp, jd, None, 4320.0, depth=3), sun, moon,
|
||||
))
|
||||
continue
|
||||
if not successors:
|
||||
keep(f"{technique}-{index}-successor", lambda: {
|
||||
"status": "omitted",
|
||||
"periods": [],
|
||||
"reason_en": "No later return falls between 300 and 400 days, so the successor year is not listed.",
|
||||
"reason_zh": "之后 300 到 400 天里没有下一次回归,后继年这里不列表。",
|
||||
})
|
||||
for pair_index, partner in enumerate(successors, start=1):
|
||||
keep(
|
||||
f"{technique}-{index}-successor-{pair_index}",
|
||||
lambda stamp=stamp, jd=row["jd_ut"], successor=partner["jd_ut"]: _mark(
|
||||
_remap_year(frame, technique, stamp, jd, successor, measure_elongation(frame, jd, successor), depth=3),
|
||||
sun, moon,
|
||||
),
|
||||
)
|
||||
keep(
|
||||
f"{technique}-{index}-tithi-year",
|
||||
lambda stamp=stamp, jd=row["jd_ut"]: _mark(
|
||||
_remap_year(frame, technique, stamp, jd, None, 4320.0, depth=3), sun, moon,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def _tithi_elapsed(frame, jd: float, stamp: datetime, number: int, span: float, direction: str) -> dict:
|
||||
held = containing_tithi(frame, jd)
|
||||
return tithi_ashtottari(stamp, number, held["remaining_time_fraction"], span, direction, natal=False)
|
||||
|
||||
|
||||
def _remap_year(frame, technique: str, stamp: datetime, return_jd: float, successor: float | None, angle: float, depth: int) -> dict:
|
||||
if technique == "yoga":
|
||||
sun, moon = frame.sun_moon(return_jd)
|
||||
template = yoga_vimshottari(stamp, (sun + moon) % 360.0, 360.0, natal=False, depth=depth)
|
||||
else:
|
||||
_sun, moon = frame.sun_moon(return_jd)
|
||||
template = nakshatra_tribhagi(stamp, moon % 360.0, 360.0, depth=depth)
|
||||
clock = ElongationClock(frame, return_jd, angle, successor)
|
||||
template["periods"] = remap_angular(template["periods"], clock, return_jd)
|
||||
return template
|
||||
|
||||
|
||||
def _annual_returns(frame: SiderealFrame, natal_jd: float, target_year: int) -> dict:
|
||||
"""Tithi roots for three years. Yoga and nakshatra roots for the target year only."""
|
||||
tithi = []
|
||||
for year in range(int(target_year), int(target_year) + 3):
|
||||
begin = float(swe.julday(year, 1, 1, 0.0))
|
||||
end = float(swe.julday(year + 1, 1, 1, 0.0))
|
||||
for row in find_returns(frame, "tithi_pravesha", natal_jd, begin, end)["returns"]:
|
||||
copied = dict(row)
|
||||
copied["year"] = year
|
||||
tithi.append(copied)
|
||||
begin = float(swe.julday(int(target_year), 1, 1, 0.0))
|
||||
end = float(swe.julday(int(target_year) + 1, 1, 1, 0.0))
|
||||
return {
|
||||
"status": "calculated",
|
||||
"returns": {
|
||||
"tithi": tithi,
|
||||
"yoga": list(find_returns(frame, "yoga_pravesha", natal_jd, begin, end)["returns"]),
|
||||
"nakshatra": list(find_returns(frame, "nakshatra_pravesha", natal_jd, begin, end)["returns"]),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def _later_returns(frame, natal_jd: float, technique: str, jd: float, start_offset: float, end_offset: float) -> list[dict]:
|
||||
begin = float(jd) + float(start_offset)
|
||||
end = float(jd) + float(end_offset)
|
||||
if start_offset <= 0:
|
||||
begin = float(jd) - 1e-4
|
||||
end = begin + 400.0
|
||||
found = find_returns(frame, technique, natal_jd, begin, end)["returns"]
|
||||
return [item for item in found if item["jd_ut"] > float(jd) + 1e-6]
|
||||
|
||||
|
||||
def _failed() -> dict:
|
||||
return {
|
||||
"status": "omitted",
|
||||
"periods": [],
|
||||
"reason_en": "This branch did not finish. The runtime log has the cause.",
|
||||
"reason_zh": "这一支没有算成,原因记在运行日志里。",
|
||||
}
|
||||
|
||||
|
||||
def _tithi_number(sun: float, moon: float) -> int:
|
||||
return int(((moon - sun) % 360.0) // 12) + 1
|
||||
|
||||
|
||||
def _arc_remaining(sun: float, moon: float) -> float:
|
||||
return 1.0 - (((moon - sun) % 360.0) % 12.0) / 12.0
|
||||
|
||||
|
||||
def _mark(result: dict, sun: float, moon: float) -> dict:
|
||||
result = dict(result)
|
||||
result["birth_sun"] = sun
|
||||
result["birth_moon"] = moon
|
||||
return result
|
||||
|
||||
|
||||
def _fingerprint(chart: dict) -> tuple:
|
||||
return (
|
||||
chart["year"], chart["month"], chart["day"], round(chart["hour_decimal"], 6),
|
||||
round(chart["lat"], 6), round(chart["lon"], 6), round(chart["tz"], 4),
|
||||
chart["ayanamsa"], chart["node_mode"], chart["target_year"],
|
||||
chart["query"].isoformat(), round(chart["year_days"], 6),
|
||||
round(chart["ascendant"], 8),
|
||||
tuple(round(float(chart["longitudes"][name]), 8) for name in _PLANETS),
|
||||
)
|
||||
|
||||
|
||||
def _karana(frame: SiderealFrame, annual: dict, chart: dict, year_days: float) -> dict:
|
||||
"""Each target-year tithi return, with Julene, PVR, and the 360-tithi PVR year."""
|
||||
rows = [
|
||||
row for row in ((annual.get("returns") or {}).get("tithi") or [])
|
||||
if int(row.get("year", -1)) == int(chart["target_year"])
|
||||
]
|
||||
if not rows:
|
||||
return {
|
||||
"status": "omitted",
|
||||
"periods": [],
|
||||
"reason_en": "No tithi return falls in the target year, so the karana year is not listed.",
|
||||
"reason_zh": "目标年没有 Tithi 回归,Karana 年这里不列表。",
|
||||
}
|
||||
groups = []
|
||||
for index, row in enumerate(rows, start=1):
|
||||
groups.append({
|
||||
"index": index,
|
||||
"variants": _karana_variants(frame, chart, year_days, row),
|
||||
})
|
||||
return {"status": "calculated", "returns": groups}
|
||||
|
||||
|
||||
def _karana_variants(frame: SiderealFrame, chart: dict, year_days: float, row: dict) -> list[dict]:
|
||||
stamp = jd_to_utc(row["jd_ut"])
|
||||
sun, moon = row["sun_longitude"], row["moon_longitude"]
|
||||
ascendant = _return_ascendant(chart, row["jd_ut"])
|
||||
return_jd = row["jd_ut"]
|
||||
variants = []
|
||||
for profile in ("julene", "pvr"):
|
||||
seed = karana_seed(sun, moon, ascendant if profile == "pvr" else None, profile)
|
||||
if seed.get("status") != "calculated":
|
||||
variants.append({"profile": profile, **seed, "periods": []})
|
||||
continue
|
||||
built = karana_year(stamp, seed["lord"], seed["remaining_fraction"], float(year_days))
|
||||
built["profile"] = profile
|
||||
built["karana"] = seed["karana"]
|
||||
built["reason_en"] = "The research passage does not supply child periods."
|
||||
built["reason_zh"] = "这份研究材料没有给出子运,所以这里只列主运。"
|
||||
variants.append(built)
|
||||
pvr = next((item for item in variants if item.get("profile") == "pvr" and item.get("status") == "calculated"), None)
|
||||
if pvr is None:
|
||||
variants.append({
|
||||
"profile": "pvr-tithi-year",
|
||||
"status": "omitted",
|
||||
"periods": [],
|
||||
"reason_en": "The quadrant lord is not available, so the tithi-year cycle is not listed.",
|
||||
"reason_zh": "象限主星没有得到,360 个太阴月的年这里不列表。",
|
||||
})
|
||||
else:
|
||||
try:
|
||||
template = karana_year(stamp, pvr["seed_lord"], pvr["remaining_fraction"], 360.0)
|
||||
clock = ElongationClock(frame, return_jd, 4320.0, None)
|
||||
template["periods"] = remap_angular(template["periods"], clock, return_jd)
|
||||
template["profile"] = "pvr-tithi-year"
|
||||
template["karana"] = pvr.get("karana")
|
||||
template["reason_en"] = "The research passage does not supply child periods."
|
||||
template["reason_zh"] = "这份研究材料没有给出子运,所以这里只列主运。"
|
||||
except (ValueError, RuntimeError) as exc:
|
||||
logger.warning("research timing karana tithi year failed: %s: %s", type(exc).__name__, exc)
|
||||
template = {
|
||||
"profile": "pvr-tithi-year",
|
||||
"status": "omitted",
|
||||
"periods": [],
|
||||
"reason_en": "The tithi-year cycle did not finish. The runtime log has the cause.",
|
||||
"reason_zh": "360 个太阴月的年没有算成,原因记在运行日志里。",
|
||||
}
|
||||
variants.append(template)
|
||||
return variants
|
||||
|
||||
|
||||
def chart_birth_jd(chart: dict) -> float:
|
||||
return birth_jd(chart["year"], chart["month"], chart["day"], chart["hour_decimal"], chart["tz"])
|
||||
|
||||
|
||||
def _return_ascendant(chart: dict, jd: float) -> float:
|
||||
try:
|
||||
from jyotish_engine import compute_chart_data
|
||||
except ImportError: # pragma: no cover - package import
|
||||
from scripts.jyotish_engine import compute_chart_data
|
||||
local = jd_to_utc(jd).astimezone(timezone(timedelta(hours=chart["tz"]))).replace(microsecond=0)
|
||||
found, _index, chart_jd, ayanamsa_value = compute_chart_data(
|
||||
local.year, local.month, local.day, local.hour, local.minute,
|
||||
chart["lat"], chart["lon"], chart["tz"],
|
||||
node_mode=chart["node_mode"], second=local.second, ayanamsa_name=chart["ayanamsa"],
|
||||
)
|
||||
if not isinstance(found, dict):
|
||||
raise RuntimeError("return ascendant is unavailable")
|
||||
houses, _ascmc = swe.houses(float(chart_jd), chart["lat"], chart["lon"], b"A")
|
||||
return (float(houses[0]) - float(ayanamsa_value)) % 360.0
|
||||
|
||||
|
||||
def chart_from_parts(
|
||||
*,
|
||||
year: int,
|
||||
month: int,
|
||||
day: int,
|
||||
hour: int,
|
||||
minute: int,
|
||||
second: int,
|
||||
lat: float,
|
||||
lon: float,
|
||||
tz: float,
|
||||
ayanamsa: str,
|
||||
node_mode: str,
|
||||
target_year: int,
|
||||
query: datetime,
|
||||
year_days: float = 365.25,
|
||||
) -> dict:
|
||||
"""Build the calculator input from a chart function result. Positions stay on our frame."""
|
||||
try:
|
||||
from jyotish_engine import compute_chart_data
|
||||
except ImportError: # pragma: no cover - package import
|
||||
from scripts.jyotish_engine import compute_chart_data
|
||||
chart, _asc_index, jd, ayanamsa_value = compute_chart_data(
|
||||
int(year), int(month), int(day), int(hour), int(minute),
|
||||
float(lat), float(lon), float(tz),
|
||||
node_mode=node_mode, second=int(second), ayanamsa_name=ayanamsa,
|
||||
)
|
||||
if not isinstance(chart, dict):
|
||||
raise RuntimeError("chart function returned no positions")
|
||||
houses, _ascmc = swe.houses(float(jd), float(lat), float(lon), b"A")
|
||||
ascendant = (float(houses[0]) - float(ayanamsa_value)) % 360.0
|
||||
longitudes = {name: float(chart["planets"][name]["degree_raw"]) for name in _PLANETS}
|
||||
epoch = datetime(int(year), int(month), int(day), int(hour), int(minute), int(second),
|
||||
tzinfo=timezone(timedelta(hours=float(tz))))
|
||||
if query.utcoffset() is None:
|
||||
query = query.replace(tzinfo=timezone(timedelta(hours=float(tz))))
|
||||
return {
|
||||
"year": int(year),
|
||||
"month": int(month),
|
||||
"day": int(day),
|
||||
"hour_decimal": int(hour) + int(minute) / 60.0 + int(second) / 3600.0,
|
||||
"lat": float(lat),
|
||||
"lon": float(lon),
|
||||
"tz": float(tz),
|
||||
"ayanamsa": str(ayanamsa or "lahiri"),
|
||||
"node_mode": node_mode if node_mode in ("mean", "true") else "mean",
|
||||
"target_year": int(target_year),
|
||||
"query": query,
|
||||
"year_days": float(year_days),
|
||||
"epoch": epoch,
|
||||
"ascendant": ascendant,
|
||||
"longitudes": longitudes,
|
||||
"chart_sun": longitudes["Sun"],
|
||||
"chart_moon": longitudes["Moon"],
|
||||
}
|
||||
Reference in New Issue
Block a user