- Dharmagya
- panchang docs
- Matching & Doshas
Matching & Doshas
panchang · v5.4.0 · MIT
Ashtakoot 36-point matching, Tamil Pathu Porutham, pairwise Mangal dosha verdicts, Kaal Sarp subtypes, and Pitru dosha.
Ashtakoot — 36-point matching
Ashtakoot scores a couple out of 36 across eight koots: Varna, Vashya, Tara, Yoni, Graha Maitri, Gana, Bhakoot and Nadi, worth 1, 2, 3, 4, 5, 6, 7 and 8 points. You pass one NatalMoon per partner. That is a rashi index and a nakshatra index, both 0-based.
import { computeAshtakoot } from 'panchang-ts';
// North Indian, 36-point — Varna, Vashya, Tara, Yoni,
// Graha Maitri, Gana, Bhakoot, Nadi (max 1/2/3/4/5/6/7/8).
const match = computeAshtakoot(
{ rashi: 4, nakshatra: 9 },
{ rashi: 0, nakshatra: 1 },
);
// → { totalScore: 0..36, koots: KootScore[8], cancellations: string[] }
match.totalScore; // 26
match.cancellations; // ['Bhakoot: mutual friendship of rashi-lords']
// Two Bhakoot cancellation rules need extra natal data:
// `lagnaRashi` enables same-lagna-lord + same-7th-lord;
// `navamsaRashi` enables same-Navamsa-lord.
const richer = computeAshtakoot(
{ rashi: 4, nakshatra: 9, lagnaRashi: 7, navamsaRashi: 2 },
{ rashi: 0, nakshatra: 1, lagnaRashi: 1, navamsaRashi: 5 },
);
// Gana-dosha cancellation is opt-in (5.1+, default off):
const boy = { rashi: 4, nakshatra: 9 };
const girl = { rashi: 0, nakshatra: 1 };
const withGana = computeAshtakoot(boy, girl, { ganaCancellation: true });
withGana.totalScore; // 32import (
"github.com/ishankgupta95/panchang/source/go/v5/panchang"
"github.com/ishankgupta95/panchang/source/go/v5/types"
)
// North Indian, 36-point - Varna, Vashya, Tara, Yoni,
// Graha Maitri, Gana, Bhakoot, Nadi (max 1/2/3/4/5/6/7/8).
match, err := panchang.ComputeAshtakoot(
types.NatalMoon{Rashi: 4, Nakshatra: 9},
types.NatalMoon{Rashi: 0, Nakshatra: 1},
types.AshtakootOptions{})
if err != nil {
panic(err)
}
fmt.Println(match.TotalScore, len(match.Koots), match.Cancellations)
// 26 8 [Bhakoot: mutual friendship of rashi-lords]
// LagnaRashi / NavamsaRashi are *int, so nil means "not supplied".
rashi, navamsa := 7, 2
girlLagna, girlNavamsa := 1, 5
richer, _ := panchang.ComputeAshtakoot(
types.NatalMoon{Rashi: 4, Nakshatra: 9, LagnaRashi: &rashi, NavamsaRashi: &navamsa},
types.NatalMoon{Rashi: 0, Nakshatra: 1, LagnaRashi: &girlLagna, NavamsaRashi: &girlNavamsa},
types.AshtakootOptions{})
fmt.Println(richer.TotalScore) // 26
// Gana-dosha cancellation is opt-in (default off):
boy := types.NatalMoon{Rashi: 4, Nakshatra: 9}
girl := types.NatalMoon{Rashi: 0, Nakshatra: 1}
withGana, _ := panchang.ComputeAshtakoot(boy, girl, types.AshtakootOptions{GanaCancellation: true})
fmt.Println(withGana.TotalScore) // 32Every cancellation that fired is written into cancellations as a readable line, so you can show the user why a score went up.
Yoni koota
Each janma nakshatra has one of fourteen animals, and Yoni scores the pair of animals on five levels. The table is the Yoni chakra of Mahidhar Sharma's Hindi tika on the Muhurta Chintamani, the lineage Frawley and PyJHora (the Python port of Jagannatha Hora) also follow. It matches PyJHora cell for cell except horse and deer (3) and tiger and lion (2), where it keeps the printed chakra's value. The Muhurta Chintamani itself fixes only the seven enemy pairs; the chakra fills in every other cell.
| Score | Relation | Animal pairs |
|---|---|---|
| 4 | same animal | 14 |
| 3 | friendly | 15 |
| 2 | neutral | 44 |
| 1 | unfriendly | 25 |
| 0 | enemy | 7: horse and buffalo, elephant and lion, sheep and monkey, snake and mongoose, dog and deer, cat and rat, cow and tiger |
import { computeAshtakoot } from 'panchang-ts';
// Magha (rat) and Bharani (elephant): neutral.
const match = computeAshtakoot({ rashi: 4, nakshatra: 9 }, { rashi: 0, nakshatra: 1 });
match.koots.find(k => k.name === 'Yoni');
// → { name: 'Yoni', score: 2, maxScore: 4, description: 'rat ↔ elephant' }
// Ashwini (horse) and Rohini (snake): friendly.
const friends = computeAshtakoot({ rashi: 0, nakshatra: 0 }, { rashi: 1, nakshatra: 3 });
friends.koots.find(k => k.name === 'Yoni')!.score; // 3
friends.totalScore; // 23.5import (
"github.com/ishankgupta95/panchang/source/go/v5/panchang"
"github.com/ishankgupta95/panchang/source/go/v5/types"
)
// Magha (rat) and Bharani (elephant): neutral.
match, err := panchang.ComputeAshtakoot(
types.NatalMoon{Rashi: 4, Nakshatra: 9},
types.NatalMoon{Rashi: 0, Nakshatra: 1},
types.AshtakootOptions{})
if err != nil {
panic(err)
}
for _, k := range match.Koots {
if k.Name == types.KootYoni {
fmt.Printf("%+v\n", k) // {Name:Yoni Score:2 MaxScore:4 Description:rat ↔ elephant}
}
}
// Ashwini (horse) and Rohini (snake): friendly.
friends, _ := panchang.ComputeAshtakoot(
types.NatalMoon{Rashi: 0, Nakshatra: 0},
types.NatalMoon{Rashi: 1, Nakshatra: 3},
types.AshtakootOptions{})
for _, k := range friends.Koots {
if k.Name == types.KootYoni {
fmt.Println(k.Score, friends.TotalScore) // 3 23.5
}
}This table is new in 5.4. The one before it never awarded 3 and matched no published chakra. Of the 1,296 pairs of natal Moons that can occur, 550 now total differently: 372 lose a point, 166 gain one and 12 gain two, and 27 of them cross the usual 18-point threshold. Only the Yoni koota moved, so the Ashwini and Rohini couple above went from 21.5 to 23.5. Recompute any score you stored. See Upgrading 5.3 → 5.4.
Pathu Porutham — Tamil ten-fold matching
The Tamil system checks ten koots and each one either passes or fails. Three of them — Yoni, Rajju and Vedha — are vetoes. A veto sets recommended to false no matter how many of the ten passed.
import { computePathuPorutham } from 'panchang-ts';
// Binary pass/fail per koot. Three vetoes (Yoni, Rajju, Vedha)
// flip `recommended` regardless of count.
const tp = computePathuPorutham(
{ rashi: 4, nakshatra: 9 },
{ rashi: 0, nakshatra: 1 },
);
tp.totalPasses; // 6, of 10
tp.recommended; // true — no veto + ≥5 passes
// Yoni fails only on the seven enemy pairs, and a failure is a veto.
tp.poruthams.find(p => p.name === 'Yoni');
// → { name: 'Yoni', passes: true, description: 'rat ↔ elephant, not enemies' }
// Anuradha (deer) and Mula (dog) are enemies.
const enemies = computePathuPorutham(
{ rashi: 7, nakshatra: 16 },
{ rashi: 8, nakshatra: 18 },
);
enemies.poruthams.find(p => p.name === 'Yoni');
// → { name: 'Yoni', passes: false, description: 'deer ↔ dog, enemies', veto: true }
enemies.totalPasses; // 7
enemies.recommended; // false: seven passes, but Yoni vetoesimport (
"github.com/ishankgupta95/panchang/source/go/v5/panchang"
"github.com/ishankgupta95/panchang/source/go/v5/types"
)
// Binary pass/fail per koot. Three vetoes (Yoni, Rajju, Vedha)
// flip Recommended regardless of count.
tp, err := panchang.ComputePathuPorutham(
types.NatalMoon{Rashi: 4, Nakshatra: 9},
types.NatalMoon{Rashi: 0, Nakshatra: 1})
if err != nil {
panic(err)
}
fmt.Println(tp.TotalPasses, tp.Recommended) // 6 true
// Yoni fails only on the seven enemy pairs. Veto is nil when it passes.
for _, p := range tp.Poruthams {
if p.Name == types.PoruthamYoni {
fmt.Println(p.Passes, p.Description, p.Veto == nil) // true rat ↔ elephant, not enemies true
}
}
// Anuradha (deer) and Mula (dog) are enemies.
enemies, _ := panchang.ComputePathuPorutham(
types.NatalMoon{Rashi: 7, Nakshatra: 16},
types.NatalMoon{Rashi: 8, Nakshatra: 18})
for _, p := range enemies.Poruthams {
if p.Name == types.PoruthamYoni {
fmt.Println(p.Passes, p.Description, *p.Veto) // false deer ↔ dog, enemies true
}
}
fmt.Println(enemies.TotalPasses, enemies.Recommended) // 7 falseYoni here is the Tamil test, not the Ashtakoot score. It fails only when the two animals are one of the seven enemy pairs in the Yoni table, and a failure is a veto. Its description names the two animals and the verdict. Some Tamil lists add snake and rat as an eighth enemy pair; the library does not.
Since 5.4 it no longer reads the Ashtakoot Yoni score. Before, it passed on a score of 2 or more, so a pair scoring 1 failed without being enemies. Across the 1,296 pairs of natal Moons that turns 52 Yoni failures into passes and moves 5 couples from not recommended to recommended. No veto changes. Every Yoni description changed as well: it used to end with the Ashtakoot score, as in 'rat ↔ elephant (Ashtakoot Yoni score 2/4)'.
Mangal dosha — a pairwise verdict
Manglik is a verdict about a couple, not about one person. When both partners are Manglik the two afflictions cancel each other out, so the pair comes back clean where a Manglik / non-Manglik pair does not. Use computeMangalCompatibility for the pair and computeMangalDosha when you want one chart on its own.
import {
computeRashiChart, computeMangalDosha, computeMangalCompatibility,
} from 'panchang-ts';
const girlChart = computeRashiChart(new Date('1997-03-26T10:20:00Z'), loc);
const m = computeMangalCompatibility(d1, girlChart);
m.afflicted; // false — both are Manglik
m.cancellations; // ['both natives Manglik, mutual cancellation']
m.boy; m.girl; // each native's own MangalDoshaInfo, severity included
// Per-chart detail:
computeMangalDosha(d1);
// Mars in 1/2/4/7/8/12 from Lagna, Moon, AND Venus (reference-almanac rule set).
// Cancellations: Mars in own sign/exalted, conjunct Jup/Moon/Venus,
// or aspected by Jupiter (5/7/9 sign-aspect).
// Severity (anshik/purna) is computed pre-cancellation.import (
"github.com/ishankgupta95/panchang/source/go/v5/panchang"
"github.com/ishankgupta95/panchang/source/go/v5/types"
)
// s, birth, loc, d1 as on Birth Charts.
girlBirth, _ := time.Parse(time.RFC3339, "1997-03-26T10:20:00Z")
girlChart, _ := s.ComputeRashiChart(girlBirth, loc, types.BirthChartOptions{})
m := panchang.ComputeMangalCompatibility(&d1, &girlChart)
fmt.Println(m.Afflicted, m.Cancellations)
// false [both natives Manglik, mutual cancellation]
fmt.Println(m.Boy.Afflicted, m.Girl.Afflicted, m.Boy.Severity) // true true anshik
// Per-chart detail:
fmt.Printf("%+v\n", panchang.ComputeMangalDosha(&d1))
// {Afflicted:true Severity:anshik FromLagna:{Afflicted:true House:12}
// FromMoon:{Afflicted:true House:7} FromVenus:{Afflicted:false House:3}
// Cancellations:[]}Severity is worked out before cancellations are applied, so a chart can report 'purna' and still end up unafflicted.
Kaal Sarp and Pitru dosha
Both take a D1 chart and return an afflicted flag. Kaal Sarp also names one of twelve subtypes, picked from the house Rahu sits in; Pitru dosha lists the triggers that matched.
import { computeKaalSarp, computePitruDosha } from 'panchang-ts';
computeKaalSarp(d1);
// → { afflicted: false, subtype: null, partial: false, rahuHouse: 1, ketuHouse: 7 }
// 12 subtypes by Rahu's house: anant, kulik, vasuki, shankhpal, padma,
// mahapadma, takshak, karkotak, shankhachud, ghatak, vishdhar, sheshnag.
computePitruDosha(d1);
// → { afflicted: false, reasons: [] }
// Pandit-consensus 4-trigger set: Sun+Rahu conjunction (any house),
// Sun+Saturn conjunction (any house), Rahu in 9th house, 9th-lord
// conjunct Rahu. Minority/expansive rules are intentionally excluded.import "github.com/ishankgupta95/panchang/source/go/v5/panchang"
// s, birth, loc, d1 as on Birth Charts.
ks := panchang.ComputeKaalSarp(&d1)
fmt.Println(ks.Afflicted, ks.RahuHouse, ks.KetuHouse) // false 1 7
// Subtype is *types.KaalSarpSubtype: nil when Afflicted is false.
// AllKaalSarpSubtypes returns the twelve in Rahu-house order.
subtypes := panchang.AllKaalSarpSubtypes()
fmt.Println(len(subtypes), subtypes[0]) // 12 anant
pd := panchang.ComputePitruDosha(&d1)
fmt.Println(pd.Afflicted, pd.Reasons) // false []Limitations
| Area | Limitation |
|---|---|
| Ashtakoot Vashya | uses a single vashya per rashi |
| Bhakoot Parivartana | the rashi-lord-exchange cancellation needs per-graha positions that NatalMoon does not carry, so it is not applied |
