> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lokpanchang.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Calculating Panchangam

> How panchangam is computed from coordinates: inputs, pipeline, and where the backend uses it

The application generates a **panchangam** (daily Hindu almanac) for a given date and location. The core logic lives in the **`panchangam/`** package; the main entry point used by the backend is **`generate_panchangam_with_timezone`** in `app.py`, which calls into `panchangam.panchangam_main` and returns a structured dictionary that is then turned into WhatsApp template parameters in `messaging.py`.

## Inputs

A panchangam run is driven by:

* **Latitude and longitude** — Observation location (e.g. user’s saved coordinates).
* **Timezone** — IANA name (e.g. `America/Los_Angeles`, `Asia/Kolkata`) used for sunrise/sunset and all displayed times.
* **Target date** — Optional; if omitted, the current date in that timezone is used.
* **Optional** — `include_transitions` (whether to compute tithi/nakshatra/yoga/karana transition times during the day), `city_detail` (for location name/region in the output).

## Pipeline (how a panchangam is calculated)

1. **Location** — A single location is represented as an `astral.LocationInfo` (name, region, timezone, lat, lon). The backend builds this in `app.py` via `create_location_with_timezone()`; optionally it uses `city_detail` from the database for display name and region.

2. **Date in timezone** — The target date is interpreted in the given timezone (e.g. “today” in the user’s local time). Sunrise, sunset, and day divisions are all in that local time.

3. **Sun and moon times** — **`get_sun_moon_times(date, location)`** in `panchangam_main.py` uses the **astral** library to compute sunrise, sunset, solar noon, and (when possible) moonrise and moonset for that date and location.

4. **Julian Day** — **`get_julian_day(dt)`** in `calculations.py` uses **Swiss Ephemeris** (`swisseph`) to get the Julian Day for the given datetime. This is the time base for planetary positions.

5. **Planet positions (sidereal)** — **`get_planet_positions(jd)`** in `calculations.py` uses Swiss Ephemeris to get Sun and Moon positions, then applies an **ayanamsa** correction to convert from tropical to **sidereal** longitudes. The default ayanamsa is set in **`panchangam/config.py`** (e.g. Lahiri). Sidereal longitudes are used for all panchangam elements.

6. **Panchangam elements** — **`calculate_panchangam_elements(date, jd)`** in `panchangam_main.py` uses helpers from **`calculations.py`** to derive:

   * **Tithi** — Lunar day (1–30) from the Moon–Sun angle (each tithi = 12°).
   * **Nakshatra** — Lunar mansion (1–27) from Moon longitude (each segment ≈ 13°20′).
   * **Yoga** — From combined Sun+Moon longitude (27 segments).
   * **Karana** — Half-tithi (11 karanas: 7 variable + 4 fixed).
   * **Paksha** — Shukla (waxing) or Krishna (waning) from tithi.
   * **Samvatsara, Masa, Ritu** — Year name (60-year cycle), lunar month, and season from Sun longitude and date.

   Name constants (e.g. `TITHI_NAMES`, `NAKSHATRA_NAMES`) come from **`panchangam/config.py`**.

7. **Day divisions** — **`calculate_day_divisions(date, sunrise, sunset, solar_noon)`** in `panchangam_main.py` uses functions in `calculations.py` to compute:
   * **Rahukalam** — Weekday-dependent 1/8 of daylight.
   * **Yamagandam** — Similarly derived.
   * **Gulika Kalam** — Similarly derived.
   * **Abhijit Muhurta** — 24 minutes before and after solar noon.

8. **Transitions (optional)** — If `include_transitions` is true, **`find_transitions()`** in **`panchangam/transitions.py`** steps through the day (using **Skyfield** and segment rules from `calculations.get_segment_angle`) to find when tithi, nakshatra, yoga, or karana change. Results are attached to the panchangam dict as `transitions`.

9. **Output structure** — The result is a single dictionary with keys such as `date`, `location`, `sun_moon_times`, `panchangam_elements`, `day_divisions`, and optionally `transitions`. This is the same structure consumed by **`messaging.generate_panchangam_template_parameters`** and **`generate_panchangam_template_parameters_short`** to build WhatsApp template body parameters.

## Key files in `panchangam/`

| File                         | Role                                                                                                                                                                                                                                                                                                  |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`panchangam_main.py`**     | `get_sun_moon_times`, `calculate_panchangam_elements`, `calculate_day_divisions`; also `generate_panchangam_json` (standalone API-style generation with lat/lon/date).                                                                                                                                |
| **`calculations.py`**        | Swiss Ephemeris: `get_julian_day`, `get_planet_positions` (with ayanamsa). Element math: `get_tithi`, `get_nakshatra`, `get_yoga`, `get_karana`, `get_paksha`, `get_samvatsara`, `get_masa`, `get_ritu`. Day divisions: `get_rahukalam`, `get_yamagandam`, `get_gulika`, `calculate_abhijit_muhurta`. |
| **`config.py`**              | Constants: ayanamsa values, `TITHI_NAMES`, `NAKSHATRA_NAMES`, `YOGA_NAMES`, `KARANA_NAMES`, segment widths, default location/timezone.                                                                                                                                                                |
| **`transitions.py`**         | `find_transitions(start_dt, end_dt, location, mode)` for tithi/nakshatra/yoga/karana transition times (uses Skyfield).                                                                                                                                                                                |
| **`output.py`**              | Time-formatting helpers (e.g. `format_time`, `format_time_short`) used in template parameter generation and in `app.format_panchangam_whatsapp_message`.                                                                                                                                              |
| **`generate_panchangam.py`** | Legacy/standalone script with its own defaults and location handling; the backend path does not use this file.                                                                                                                                                                                        |

## Where the backend uses the core logic

* **`app.py`** — **`generate_panchangam_with_timezone(latitude, longitude, timezone_name, target_date=None, include_transitions=True, include_horai=1, city_detail=None)`** builds the location, resolves the date in the given timezone, then calls `panchangam_main.get_sun_moon_times`, `get_julian_day`, `calculate_panchangam_elements`, `calculate_day_divisions`, and (if requested) `find_transitions`, and assembles the panchangam dict. Used by:
  * Webhook location handler (immediate panchangam after user shares location).
  * Test and admin routes (e.g. `/test/whatsapp/generate/<phone_number>`, `/test/whatsapp/generate-coords`).
  * **`tasks.send_for_timezone`** (daily 6:30 AM send) — which calls this with the user’s lat/lon, timezone, and current local date.
* **`tasks.py`** — **`send_for_timezone`** runs inside a Celery worker with a Flask app context; for each user in the timezone it calls `generate_panchangam_with_timezone` (with `get_user_local_time(timezone_name)` as `target_date`) and then **`messaging.send_panchangam_template`**.
* **`messaging.py`** — **`send_panchangam_template`** takes the panchangam dict and either uses **`generate_panchangam_template_parameters`** (long template, 42 params) or **`generate_panchangam_template_parameters_short`** (short template, 24 params). Those functions read from the same dict keys (`panchangam_elements`, `sun_moon_times`, `day_divisions`, `transitions`, etc.) and call **`panchangam.output.format_time`** / **`format_time_short`** for time strings. The resulting parameter list is sent via the WhatsApp template message API.

So: **coordinates + timezone + date** go in → **`panchangam_main` + `calculations` + `transitions`** produce the panchangam dict → **`app`** and **`messaging`** use that dict for webhook replies and for Celery-driven daily sends.
