Ascendant
Developer guides

Choose a school and settings

Pick an ayanamsa and house system, set them once, and keep KP and Parashari results apart.

Every calculation in Ascendant depends on two settings, the ayanamsa and the house system. Together they are called AstroParams. This guide shows how to choose them for your use case, set them in code or from the environment, and confirm which ones a result used.

Pick settings quickly

You wantAyanamsaHouse systemSchool
KP readings, using cusps, star lords, sub lords, and significatorsKrishnamurtiVP291PlacidusKP
Parashari readings, using signs and divisional chartsLahiriWholeSignParashari
No preferenceLeave the defaultsKP

The library defaults are KrishnamurtiVP291 with Placidus, so if you set nothing, you are working in the KP school. A single judgment should never mix the two schools. If your product offers both, run each one with its own settings, as shown in Use both schools in one app.

What the two settings do

The ayanamsa is the offset that aligns tropical longitudes with the fixed sidereal zodiac. It changes every longitude Ascendant reports, for the Lagna and for each graha.

The house system decides where the twelve house cusps of the D1 chart fall. It affects D1 only. Divisional charts always use whole-sign houses, counted from their mapped Lagna, whichever house system you choose.

AstroParams are not part of the birth moment. They are settings of the calculation, and every chart calculation records the ones it used.

Set them in code

Provide the settings with AstroParams.layer when you build your runtime:

import { AstroParams, Swisseph } from "astro-ascendant";
import { Layer, ManagedRuntime } from "effect";

const runtime = ManagedRuntime.make(
  Layer.mergeAll(
    AstroParams.layer({ ayanamsa: "Lahiri", houseSystem: "WholeSign" }),
    Swisseph.SwissephCachedLayer,
  ),
);

AstroParams.layer takes an Options value, so TypeScript rejects any ayanamsa or house-system name the library does not know. Use AstroParams.DefaultAstroParams for the defaults, which is what Runtime.MainLayer uses.

See what changes

The same birth, calculated under both presets, shows how much the settings matter. The birth is 2000-01-01 12:00 UTC at 12.9716° N, 77.5946° E.

ResultKrishnamurtiVP291 + PlacidusLahiri + WholeSign
Lagna longitude69.684°69.607°
Lagna signGeminiGemini
House 2 cusp in D195.392°90.000°

The ayanamsa moves the Lagna by a fraction of a degree. That is small here, but it is enough to change a star, a sub lord, or a sign at a boundary. The house system moves the cusps. Whole-sign houses always begin at a multiple of 30°, and Placidus cusps do not.

Choose an ayanamsa

Ascendant supports 47 ayanamsas, taken from the Swiss Ephemeris catalog. These are the ones most products use:

NameNotes
KrishnamurtiVP291A variant of the Krishnamurti ayanamsa. The library default, and the KP choice.
KrishnamurtiThe original Krishnamurti ayanamsa.
LahiriThe Chitrapaksha ayanamsa, widely used for Parashari work.
RamanNamed for B. V. Raman.
FaganBradleyThe standard for Western sidereal astrology.
YukteshwarNamed for Sri Yukteshwar.
TrueCitraKeeps the star Chitra fixed at 180°.

All 47 ayanamsas

Pass any of these names exactly as written. They are listed in Swiss Ephemeris catalog order, not by how often they are used.

FaganBradleyLahiriDeLuce
RamanUshashashiKrishnamurti
DjwhalKhulYukteshwarJNBhasin
BabylKugler1BabylKugler2BabylKugler3
BabylHuberBabylEtPSCAldebaran15Tau
HipparchosSassanianGalacticCenter0Sag
J2000J1900B1950
SuryaSiddhantaSuryaSiddhantaMeanSunAryabhata
AryabhataMeanSunSSRevatiSSCitra
TrueCitraTrueRevatiTruePushya
GalacticCenterGilBrandGalacticEquatorIAU1958GalacticEquator
GalacticEquatorMidMulaSkydramTrueMula
DhruvaGalCenterMulaWilhelmAryabhata522BabylBritton
TrueSheoranGalacticCenterCochraneGalacticEquatorFiorenza
ValensMoonLahiri1940LahiriVP285
KrishnamurtiVP291LahiriICRC

The AstroParams reference shows the same list as a type.

Choose a house system

Ascendant supports 13 house systems. Placidus is the default.

NameHow it divides the houses
PlacidusBy time. Unequal houses. The default.
WholeSignOne sign per house. The Lagna's sign is house 1, and every house is 30°.
KochBy time, from the birthplace meridian. Unequal houses.
EqualTwelve 30° houses counted from the Lagna's exact degree.
VehlowEqualEqual 30° houses with the Lagna in the middle of house 1.
PorphyriusDivides each quadrant between the angles into three equal parts.
RegiomontanusA medieval system based on divisions of the celestial equator.
CampanusBased on divisions of the prime vertical.
MeridianAxial rotation: equal in time, measured from the meridian.
MorinusBased on the celestial equator, with equal 30° houses.
AlcabitusA medieval Arabic system.
PolichPageTopocentric, a modern time-based system close to Placidus.
AzimuthalBased on the horizon. For specialized use.

High latitudes

Placidus and Koch are undefined inside the polar circles, where some degrees never rise or set. There, Chart.generate fails with a ChartCalculationError instead of returning bad cusps. In a test, 66° N worked and 68° N failed. Other systems, such as Equal, WholeSign, and Campanus, still return cusps, but they are not meaningful near the poles. If your users may be born far north or south, choose the house system deliberately.

Use both schools in one app

Build one runtime per school and send each judgment to the right one. This keeps KP and Parashari results from mixing:

import { AstroParams, Swisseph } from "astro-ascendant";
import { Layer, ManagedRuntime } from "effect";

export const kp = ManagedRuntime.make(
  Layer.mergeAll(
    AstroParams.layer({ ayanamsa: "KrishnamurtiVP291", houseSystem: "Placidus" }),
    Swisseph.SwissephCachedLayer,
  ),
);

export const parashari = ManagedRuntime.make(
  Layer.mergeAll(
    AstroParams.layer({ ayanamsa: "Lahiri", houseSystem: "WholeSign" }),
    Swisseph.SwissephCachedLayer,
  ),
);

Then run a calculation with the runtime that matches the question, for example kp.runPromise(Chart.generate(located)). Dispose both at shutdown.

Read the settings from the environment

AstroParams.layerConfig reads the settings from Effect Config, so you can choose them per deployment without code changes:

import { AstroParams, Swisseph } from "astro-ascendant";
import { Config, Layer, ManagedRuntime } from "effect";

const settings = AstroParams.layerConfig({
  ayanamsa: Config.schema(AstroParams.Ayanamsa, "AYANAMSA"),
  houseSystem: Config.schema(AstroParams.HouseSystem, "HOUSE_SYSTEM"),
});

const runtime = ManagedRuntime.make(
  Layer.mergeAll(settings, Swisseph.SwissephCachedLayer),
);

Run it with the variables set:

AYANAMSA=Raman HOUSE_SYSTEM=Equal bun run app.ts

A name the library does not know, such as AYANAMSA=Nope, fails the program with a ConfigError whose message lists the accepted values. Your app stops at startup instead of producing a chart with the wrong settings.

Confirm which settings a result used

Each chart calculation carries the settings it was made with:

const calculation = yield* Chart.generate(located);

console.log(calculation.astroParams);
// { ayanamsa: "Lahiri", houseSystem: "WholeSign" }

Store or display this next to every result. A reading is only repeatable if you can say which ayanamsa and house system produced it.

On this page