- Dharmagya
- panchang docs
- Birth Charts
Birth Charts
panchang · v5.4.0 · MIT
Planetary positions, Lagna, Bhava under three house systems, D1 and seven divisional charts, and planetary dignity.
Planetary positions
computePlanetaryPositions gives you all nine grahas at one moment, sidereal. Each one is a GrahaPosition: rashi, nakshatra and pada, degree within the sign, and a retrograde flag.
The library does not carry rashi or nakshatra names for this call. You pass your own name lookups as the third and fourth arguments.
import { computePlanetaryPositions, GRAHA_ABBR } from 'panchang-ts';
// The library does not name rashis or nakshatras here — supply the lists.
const RASHI = ['Mesha','Vrishabha','Mithuna','Karka','Simha','Kanya',
'Tula','Vrischika','Dhanus','Makara','Kumbha','Meena'];
const NAK = ['Ashwini','Bharani','Krittika','Rohini','Mrigashira','Ardra','Punarvasu',
'Pushya','Ashlesha','Magha','Purva Phalguni','Uttara Phalguni','Hasta',
'Chitra','Swati','Vishakha','Anuradha','Jyeshtha','Mula','Purva Ashadha',
'Uttara Ashadha','Shravana','Dhanishtha','Shatabhisha',
'Purva Bhadrapada','Uttara Bhadrapada','Revati'];
const nakName = (i: number) => NAK[i], rashiName = (i: number) => RASHI[i];
const at = new Date('2026-09-02T00:00:00Z');
const g = computePlanetaryPositions(at, 'lahiri', nakName, rashiName);
console.log(g.jupiter.rashi.name); // Karka
console.log(g.jupiter.degreeInRashi.toFixed(2)); // 19.67
console.log(g.jupiter.nakshatra.name); // Ashlesha
console.log(g.jupiter.nakshatra.pada); // 1
console.log(g.saturn.isRetrograde); // true
console.log(GRAHA_ABBR['Jupiter']); // Ju
// True node (sharper Rahu/Ketu) — the fifth argument.
const gT = computePlanetaryPositions(at, 'lahiri', nakName, rashiName, 'true');
console.log(g.rahu.siderealLongitude.toFixed(4), gT.rahu.siderealLongitude.toFixed(4));
// 305.0122 305.6174package main
import (
"fmt"
"time"
"github.com/ishankgupta95/panchang/source/go/v5/panchang"
"github.com/ishankgupta95/panchang/source/go/v5/types"
)
// must unwraps (value, error) and panics on error. Reused by the examples below.
func must[T any](v T, err error) T {
if err != nil {
panic(err)
}
return v
}
// The library does not name rashis or nakshatras here — supply the lists.
var rashi = []string{"Mesha", "Vrishabha", "Mithuna", "Karka", "Simha", "Kanya",
"Tula", "Vrischika", "Dhanus", "Makara", "Kumbha", "Meena"}
var nak = []string{"Ashwini", "Bharani", "Krittika", "Rohini", "Mrigashira", "Ardra",
"Punarvasu", "Pushya", "Ashlesha", "Magha", "Purva Phalguni", "Uttara Phalguni",
"Hasta", "Chitra", "Swati", "Vishakha", "Anuradha", "Jyeshtha", "Mula",
"Purva Ashadha", "Uttara Ashadha", "Shravana", "Dhanishtha", "Shatabhisha",
"Purva Bhadrapada", "Uttara Bhadrapada", "Revati"}
func nakName(i int) string { return nak[i] }
func rashiName(i int) string { return rashi[i] }
func main() {
s := panchang.New()
at := time.Date(2026, 9, 2, 0, 0, 0, 0, time.UTC)
g := must(s.ComputePlanetaryPositions(at, types.Lahiri, nakName, rashiName, types.NodeMean))
fmt.Println(g.Jupiter.Rashi.Name) // Karka
fmt.Printf("%.2f\n", g.Jupiter.DegreeInRashi) // 19.67
fmt.Println(g.Jupiter.Nakshatra.Name) // Ashlesha
fmt.Println(g.Jupiter.Nakshatra.Pada) // 1
fmt.Println(g.Saturn.IsRetrograde) // true
fmt.Println(panchang.GrahaAbbr()[types.GrahaJupiter]) // Ju
// True node (sharper Rahu/Ketu).
gT := must(s.ComputePlanetaryPositions(at, types.Lahiri, nakName, rashiName, types.NodeTrue))
fmt.Printf("%.4f %.4f\n", g.Rahu.SiderealLongitude, gT.Rahu.SiderealLongitude)
// 305.0122 305.6174
}isRetrograde is always false for the Sun and Moon, and always true for Rahu and Ketu. The node model defaults to the mean node; the last argument switches it to the true node.
Lagna and Bhava
computeLagna gives you the ascendant — rashi, nakshatra and pada. computeBhava gives you the twelve house cusps and the MC longitude, under whichever house system you ask for.
import { computeLagna, computeBhava, PanchangError } from 'panchang-ts';
const birth = new Date('1995-08-15T05:30:00Z');
const loc = { latitude: 28.6139, longitude: 77.2090 };
const lagna = computeLagna(birth, loc, 'lahiri', 'en');
console.log(lagna.rashi.name, lagna.nakshatra.name, lagna.pada); // Tula Chitra 4
// houseSystem: 'whole-sign' (default) | 'equal' | 'placidus-kp'.
const houses = computeBhava(birth, loc, { houseSystem: 'whole-sign' });
console.log(houses.system, houses.houses[0].cuspLongitude); // whole-sign 180
console.log(houses.mcLongitude.toFixed(4)); // 96.8589
// Placidus-KP is undefined beyond the polar circles (about ±66.56°).
try {
computeBhava(birth, { latitude: 78, longitude: 15 }, { houseSystem: 'placidus-kp' });
} catch (e) {
console.log((e as PanchangError).code); // CIRCUMPOLAR
}// Inside func main(); must() is the helper from the first example.
s := panchang.New()
birth := time.Date(1995, 8, 15, 5, 30, 0, 0, time.UTC)
loc := types.GeoLocation{Latitude: 28.6139, Longitude: 77.2090}
lagna := must(s.ComputeLagna(birth, loc, types.Lahiri, types.LanguageEn))
fmt.Println(lagna.Rashi.Name, lagna.Nakshatra.Name, lagna.Pada) // Tula Chitra 4
// HouseSystem takes a named constant: HouseSystemWholeSign, HouseSystemEqual
// or HouseSystemPlacidusKP.
houses := must(s.ComputeBhava(birth, loc, types.BirthChartOptions{HouseSystem: types.HouseSystemWholeSign}))
fmt.Println(houses.System, houses.Houses[0].CuspLongitude) // whole-sign 180
fmt.Printf("%.4f\n", houses.MCLongitude) // 96.8589
// Placidus-KP is undefined beyond the polar circles (about ±66.56°).
_, err := s.ComputeBhava(birth, types.GeoLocation{Latitude: 78, Longitude: 15},
types.BirthChartOptions{HouseSystem: types.HouseSystemPlacidusKP})
if panchang.IsCode(err, types.ErrCircumpolar) {
fmt.Println("circumpolar: no Placidus-KP cusps here")
}In Go the house system is a named types.HouseSystem constant rather than a bare string, and an empty field means whole-sign. In TypeScript an omitted houseSystem means whole-sign too, but an empty string is an unknown house system.
Rashi chart and divisional charts
computeRashiChart casts the D1: lagna, bhava, and the nine grahas placed in houses. chart.planets is the ordered list. chart.byPlanet is the same nine placements keyed by graha, so you can read one without scanning the list.
computeNavamsa gives you the D9. computeDivisionalChart gives you any of D2 Hora, D3 Drekkana, D7 Saptamsa, D9 Navamsa, D10 Dasamsa, D12 Dwadasamsa and D30 Trimsamsa.
import { computeRashiChart, computeNavamsa, computeDivisionalChart, computeDignity }
from 'panchang-ts';
const birth = new Date('1995-08-15T05:30:00Z');
const loc = { latitude: 28.6139, longitude: 77.2090 };
const opts = { houseSystem: 'whole-sign' } as const;
// byPlanet is the keyed lookup; planets is the ordered list.
const d1 = computeRashiChart(birth, loc, opts);
console.log(d1.divisional, d1.byPlanet.Mars.house); // D1 12
console.log(d1.byPlanet.Jupiter.house, d1.byPlanet.Saturn.isRetrograde); // 2 true
const jup = d1.planets.find(p => p.planet === 'Jupiter')!;
console.log('scan:', jup.planet, jup.rashi.name, jup.house); // scan: Jupiter Vrischika 2
// Divisional charts (D2, D3, D7, D9, D10, D12, D30).
const d9 = computeNavamsa(birth, loc, opts);
const d10 = computeDivisionalChart(birth, loc, 'D10', opts);
const d30 = computeDivisionalChart(birth, loc, 'D30', opts);
console.log(d9.divisional, d9.lagnaRashi.name); // D9 Vrischika
console.log(d10.divisional, d10.lagnaRashi.name); // D10 Vrischika
console.log(d30.divisional, d30.lagnaRashi.name); // D30 Mesha
// Planetary dignity (BPHS Ch. 3-4).
console.log(computeDignity('Mars', 0)); // moolatrikona
console.log(computeDignity('Mars', 9)); // exalted
console.log(computeDignity('Sun', 6)); // debilitated// Inside func main(); must() is the helper from the first example.
s := panchang.New()
birth := time.Date(1995, 8, 15, 5, 30, 0, 0, time.UTC)
loc := types.GeoLocation{Latitude: 28.6139, Longitude: 77.2090}
opts := types.BirthChartOptions{HouseSystem: types.HouseSystemWholeSign}
// ByPlanet is the keyed lookup; Planets is the ordered slice.
d1 := must(s.ComputeRashiChart(birth, loc, opts))
fmt.Println(d1.Divisional, d1.ByPlanet.Mars.House) // D1 12
fmt.Println(d1.ByPlanet.Jupiter.House, d1.ByPlanet.Saturn.IsRetrograde) // 2 true
for _, p := range d1.Planets {
if p.Planet == types.GrahaJupiter { // compare to the constant, not to 4
fmt.Println("scan:", p.Planet, p.Rashi.Name, p.House) // scan: Jupiter Vrischika 2
}
}
// Divisional charts.
d9 := must(s.ComputeNavamsa(birth, loc, opts))
d10 := must(s.ComputeDivisionalChart(birth, loc, types.DivisionalD10, opts))
d30 := must(s.ComputeDivisionalChart(birth, loc, types.DivisionalD30, opts))
fmt.Println(d9.Divisional, d9.LagnaRashi.Name) // D9 Vrischika
fmt.Println(d10.Divisional, d10.LagnaRashi.Name) // D10 Vrischika
fmt.Println(d30.Divisional, d30.LagnaRashi.Name) // D30 Mesha
// Planetary dignity (BPHS Ch. 3-4).
fmt.Println(must(panchang.ComputeDignity(types.GrahaMars, 0))) // moolatrikona
fmt.Println(must(panchang.ComputeDignity(types.GrahaMars, 9))) // exalted
fmt.Println(must(panchang.ComputeDignity(types.GrahaSun, 6))) // debilitatedcomputeRashiChart returns a BirthChart: divisional, lagna, bhava, planets, byPlanet. The divisional helpers return a DivisionalChart — divisional, lagnaRashi, planets — whole-sign anchored to their own lagna, with no cusps and no keyed lookup. So the helpers downstream (Ashtakavarga, yogas, doshas, Arudhas, Argala) all take a d1 straight from computeRashiChart. Shadbala and Bhava Bala are the exception: they take the birth date and location, like computeRashiChart itself.
| Option | Values | Default |
|---|---|---|
houseSystem | 'whole-sign' · 'equal' · 'placidus-kp' | 'whole-sign' |
ayanamsa | all five — 'lahiri', 'raman', 'krishnamurti', 'true-chitra', 'thirukanitham' | 'lahiri' |
language | 'en' · 'hi' | 'en' |
nodeType | Rahu/Ketu node model — 'mean' · 'true' | 'mean' |
An unknown house system, divisional or graha name throws a PanchangError with code INVALID_INPUT. For a house system or divisional the message lists the values it accepts, for example unknown divisional "D60"; expected one of D2, D3, D7, D9, D10, D12, D30. Before 5.4 TypeScript failed on these with a raw TypeError; Go already returned the error. An Invalid Date throws INVALID_DATE, including in computePlanetaryPositions, which used to return NaN longitudes for one.
