# Choose a school and settings (/docs/guides/settings)

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 [#pick-settings-quickly]

| You want | Ayanamsa | House system | School |
| --- | --- | --- | --- |
| KP readings, using cusps, star lords, sub lords, and significators | `KrishnamurtiVP291` | `Placidus` | KP |
| Parashari readings, using signs and divisional charts | `Lahiri` | `WholeSign` | Parashari |
| No preference | Leave the defaults | | KP |

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](#use-both-schools-in-one-app).

## What the two settings do [#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 [#set-them-in-code]

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

```ts
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 [#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`.

| Result | `KrishnamurtiVP291` + `Placidus` | `Lahiri` + `WholeSign` |
| --- | --- | --- |
| Lagna longitude | 69.684° | 69.607° |
| Lagna sign | Gemini | Gemini |
| House 2 cusp in D1 | 95.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 [#choose-an-ayanamsa]

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

| Name | Notes |
| --- | --- |
| `KrishnamurtiVP291` | A variant of the Krishnamurti ayanamsa. The library default, and the KP choice. |
| `Krishnamurti` | The original Krishnamurti ayanamsa. |
| `Lahiri` | The Chitrapaksha ayanamsa, widely used for Parashari work. |
| `Raman` | Named for B. V. Raman. |
| `FaganBradley` | The standard for Western sidereal astrology. |
| `Yukteshwar` | Named for Sri Yukteshwar. |
| `TrueCitra` | Keeps the star Chitra fixed at 180°. |

### All 47 ayanamsas [#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.

<table>
  <tbody>
    <tr>
      <td><code>FaganBradley</code></td>
      <td><code>Lahiri</code></td>
      <td><code>DeLuce</code></td>
    </tr>
    <tr>
      <td><code>Raman</code></td>
      <td><code>Ushashashi</code></td>
      <td><code>Krishnamurti</code></td>
    </tr>
    <tr>
      <td><code>DjwhalKhul</code></td>
      <td><code>Yukteshwar</code></td>
      <td><code>JNBhasin</code></td>
    </tr>
    <tr>
      <td><code>BabylKugler1</code></td>
      <td><code>BabylKugler2</code></td>
      <td><code>BabylKugler3</code></td>
    </tr>
    <tr>
      <td><code>BabylHuber</code></td>
      <td><code>BabylEtPSC</code></td>
      <td><code>Aldebaran15Tau</code></td>
    </tr>
    <tr>
      <td><code>Hipparchos</code></td>
      <td><code>Sassanian</code></td>
      <td><code>GalacticCenter0Sag</code></td>
    </tr>
    <tr>
      <td><code>J2000</code></td>
      <td><code>J1900</code></td>
      <td><code>B1950</code></td>
    </tr>
    <tr>
      <td><code>SuryaSiddhanta</code></td>
      <td><code>SuryaSiddhantaMeanSun</code></td>
      <td><code>Aryabhata</code></td>
    </tr>
    <tr>
      <td><code>AryabhataMeanSun</code></td>
      <td><code>SSRevati</code></td>
      <td><code>SSCitra</code></td>
    </tr>
    <tr>
      <td><code>TrueCitra</code></td>
      <td><code>TrueRevati</code></td>
      <td><code>TruePushya</code></td>
    </tr>
    <tr>
      <td><code>GalacticCenterGilBrand</code></td>
      <td><code>GalacticEquatorIAU1958</code></td>
      <td><code>GalacticEquator</code></td>
    </tr>
    <tr>
      <td><code>GalacticEquatorMidMula</code></td>
      <td><code>Skydram</code></td>
      <td><code>TrueMula</code></td>
    </tr>
    <tr>
      <td><code>DhruvaGalCenterMulaWilhelm</code></td>
      <td><code>Aryabhata522</code></td>
      <td><code>BabylBritton</code></td>
    </tr>
    <tr>
      <td><code>TrueSheoran</code></td>
      <td><code>GalacticCenterCochrane</code></td>
      <td><code>GalacticEquatorFiorenza</code></td>
    </tr>
    <tr>
      <td><code>ValensMoon</code></td>
      <td><code>Lahiri1940</code></td>
      <td><code>LahiriVP285</code></td>
    </tr>
    <tr>
      <td><code>KrishnamurtiVP291</code></td>
      <td><code>LahiriICRC</code></td>
      <td></td>
    </tr>
  </tbody>
</table>

The [AstroParams reference](/docs/api-reference/astro-params) shows the same list
as a type.

## Choose a house system [#choose-a-house-system]

Ascendant supports 13 house systems. `Placidus` is the default.

| Name | How it divides the houses |
| --- | --- |
| `Placidus` | By time. Unequal houses. The default. |
| `WholeSign` | One sign per house. The Lagna's sign is house 1, and every house is 30°. |
| `Koch` | By time, from the birthplace meridian. Unequal houses. |
| `Equal` | Twelve 30° houses counted from the Lagna's exact degree. |
| `VehlowEqual` | Equal 30° houses with the Lagna in the middle of house 1. |
| `Porphyrius` | Divides each quadrant between the angles into three equal parts. |
| `Regiomontanus` | A medieval system based on divisions of the celestial equator. |
| `Campanus` | Based on divisions of the prime vertical. |
| `Meridian` | Axial rotation: equal in time, measured from the meridian. |
| `Morinus` | Based on the celestial equator, with equal 30° houses. |
| `Alcabitus` | A medieval Arabic system. |
| `PolichPage` | Topocentric, a modern time-based system close to Placidus. |
| `Azimuthal` | Based on the horizon. For specialized use. |

<Callout type="warn" title="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.
</Callout>

## Use both schools in one app [#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:

```ts
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 [#read-the-settings-from-the-environment]

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

```ts
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:

```bash
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 [#confirm-which-settings-a-result-used]

Each chart calculation carries the settings it was made with:

```ts
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.
