Jyotish Calculations Explained: A Technical Deep-Dive
Master the mathematics behind Vedic astrology. Complete guide to planetary calculations, ayanamsa, divisional charts, dasha systems, and house computations.
Introduction to Jyotish Mathematics
Vedic astrology (Jyotish) is fundamentally a mathematical science. Unlike Western psychological astrology, Jyotish relies on precise astronomical calculations. This guide explains the core formulas, algorithms, and mathematical principles that power every Vedic astrology application.
Prerequisites for Understanding
- Astronomy Basics: Celestial sphere, ecliptic, precession
- Coordinate Systems: Ecliptic longitude/latitude
- Time Systems: UTC, Julian Day, sidereal time
- Mathematics: Trigonometry, modular arithmetic
Part 1: Julian Day Calculation
All astronomical calculations start with converting dates to Julian Day Number (JD) - a continuous count of days since January 1, 4713 BCE.
Julian Day Formula
def date_to_julian_day(year, month, day, hour, minute, second):
"""
Convert Gregorian calendar date to Julian Day Number
Args:
year: Year (e.g., 2025)
month: Month (1-12)
day: Day of month (1-31)
hour: Hour (0-23)
minute: Minute (0-59)
second: Second (0-59)
Returns:
Julian Day as float
"""
# Adjust for January and February
if month <= 2:
year -= 1
month += 12
# Calculate Julian Day at midnight
A = int(year / 100)
B = 2 - A + int(A / 4)
JD = int(365.25 * (year + 4716)) + \
int(30.6001 * (month + 1)) + \
day + B - 1524.5
# Add time component
day_fraction = (hour + minute/60 + second/3600) / 24
JD += day_fraction
return JD
# Example: December 23, 2025, 14:30:00
jd = date_to_julian_day(2025, 12, 23, 14, 30, 0)
print(f"Julian Day: {jd}") # 2460666.104166667
Why Julian Day Matters
Swiss Ephemeris and all astronomical libraries use JD as input. It eliminates calendar complexities (leap years, varying month lengths) and provides a linear time scale for calculations.
Part 2: Planetary Positions
Calculating accurate planetary positions is the foundation of Jyotish. We use Swiss Ephemeris for highest accuracy.
Using Swiss Ephemeris
import swisseph as swe
# Set ephemeris files path
swe.set_ephe_path('/usr/share/ephe')
def get_planet_position(jd, planet_id, tropical=True):
"""
Get planetary position using Swiss Ephemeris
Args:
jd: Julian Day
planet_id: Planet constant (swe.SUN, swe.MOON, etc.)
tropical: True for tropical, False for sidereal
Returns:
Dictionary with position data
"""
# Calculate position
# Flag: SEFLG_SWIEPH (Swiss Ephemeris) + SEFLG_SPEED
flags = swe.FLG_SWIEPH | swe.FLG_SPEED
result, ret_flag = swe.calc_ut(jd, planet_id, flags)
longitude = result[0] # Ecliptic longitude (0-360°)
latitude = result[1] # Ecliptic latitude
distance = result[2] # Distance in AU
speed = result[3] # Daily motion in degrees
return {
'longitude': longitude,
'latitude': latitude,
'distance': distance,
'speed': speed,
'retrograde': speed < 0
}
# Calculate Sun position
jd = date_to_julian_day(2025, 12, 23, 14, 30, 0)
sun_pos = get_planet_position(jd, swe.SUN)
print(f"Sun Longitude: {sun_pos['longitude']:.4f}°")
print(f"Sun Speed: {sun_pos['speed']:.4f}°/day")
print(f"Retrograde: {sun_pos['retrograde']}")
All Planets and Points
# Planet constants in Swiss Ephemeris
PLANETS = {
'Sun': swe.SUN, # 0
'Moon': swe.MOON, # 1
'Mercury': swe.MERCURY, # 2
'Venus': swe.VENUS, # 3
'Mars': swe.MARS, # 4
'Jupiter': swe.JUPITER, # 5
'Saturn': swe.SATURN, # 6
'Rahu': swe.MEAN_NODE, # 10 (Mean North Node)
'Ketu': swe.MEAN_NODE, # 10 (Ketu = Rahu + 180°)
'Uranus': swe.URANUS, # 7
'Neptune': swe.NEPTUNE, # 8
'Pluto': swe.PLUTO # 9
}
def get_all_planets(jd):
"""Get positions of all planets"""
positions = {}
for name, planet_id in PLANETS.items():
pos = get_planet_position(jd, planet_id)
# Special handling for Ketu (opposite of Rahu)
if name == 'Ketu':
pos['longitude'] = (pos['longitude'] + 180) % 360
positions[name] = pos
return positions
Part 3: Ayanamsa Calculation
Ayanamsa converts tropical (Western) positions to sidereal (Vedic). It represents the precession of equinoxes - Earth's 26,000-year wobble.
Popular Ayanamsas
Implementing Ayanamsa
def convert_to_sidereal(tropical_longitude, jd, ayanamsa='lahiri'):
"""
Convert tropical longitude to sidereal
Args:
tropical_longitude: Tropical ecliptic longitude (0-360°)
jd: Julian Day
ayanamsa: 'lahiri', 'raman', 'krishnamurti', etc.
Returns:
Sidereal longitude (0-360°)
"""
# Set ayanamsa mode
ayanamsa_modes = {
'lahiri': swe.SIDM_LAHIRI,
'raman': swe.SIDM_RAMAN,
'krishnamurti': swe.SIDM_KRISHNAMURTI,
'yukteshwar': swe.SIDM_YUKTESHWAR,
'jn_bhasin': swe.SIDM_JN_BHASIN
}
swe.set_sid_mode(ayanamsa_modes.get(ayanamsa, swe.SIDM_LAHIRI))
# Get ayanamsa value for this Julian Day
ayanamsa_value = swe.get_ayanamsa_ut(jd)
# Convert to sidereal
sidereal_longitude = (tropical_longitude - ayanamsa_value) % 360
return sidereal_longitude, ayanamsa_value
# Example
tropical_sun = 271.5436 # Sun at ~271° tropical
jd = date_to_julian_day(2025, 12, 23, 14, 30, 0)
sidereal_sun, ayanamsa = convert_to_sidereal(tropical_sun, jd, 'lahiri')
print(f"Tropical: {tropical_sun:.4f}°")
print(f"Ayanamsa: {ayanamsa:.4f}°")
print(f"Sidereal: {sidereal_sun:.4f}°")
Understanding Zodiac Signs
def longitude_to_sign(longitude):
"""
Convert longitude to zodiac sign
Args:
longitude: Ecliptic longitude (0-360°)
Returns:
Dictionary with sign info
"""
signs = [
"Aries", "Taurus", "Gemini", "Cancer",
"Leo", "Virgo", "Libra", "Scorpio",
"Sagittarius", "Capricorn", "Aquarius", "Pisces"
]
sign_num = int(longitude / 30) # 0-11
degree_in_sign = longitude % 30
# DMS format (Degrees, Minutes, Seconds)
degrees = int(degree_in_sign)
minutes = int((degree_in_sign - degrees) * 60)
seconds = int(((degree_in_sign - degrees) * 60 - minutes) * 60)
return {
'sign': signs[sign_num],
'sign_num': sign_num,
'degree': degree_in_sign,
'dms': f"{degrees}°{minutes}'{seconds}\""
}
# Example
sun_sign = longitude_to_sign(sidereal_sun)
print(f"Sun in {sun_sign['sign']} at {sun_sign['dms']}")
Part 4: Ascendant (Lagna) Calculation
The Ascendant is the zodiac degree rising on the eastern horizon at birth time. It requires precise location (latitude/longitude) and time.
def calculate_ascendant(jd, latitude, longitude, ayanamsa='lahiri'):
"""
Calculate Ascendant and house cusps
Args:
jd: Julian Day
latitude: Birth latitude in degrees
longitude: Birth longitude in degrees
ayanamsa: Ayanamsa system
Returns:
Dictionary with Ascendant and house cusps
"""
# Set ayanamsa
ayanamsa_modes = {
'lahiri': swe.SIDM_LAHIRI,
'raman': swe.SIDM_RAMAN,
'krishnamurti': swe.SIDM_KRISHNAMURTI
}
swe.set_sid_mode(ayanamsa_modes.get(ayanamsa, swe.SIDM_LAHIRI))
# House system: 'P' = Placidus, 'W' = Whole Sign, 'E' = Equal
# Most Vedic astrologers use 'W' (Whole Sign)
house_system = b'W'
# Calculate houses
cusps, ascmc = swe.houses_ex(
jd,
latitude,
longitude,
house_system
)
# ASCMC array contains:
# [0] = Ascendant
# [1] = MC (Midheaven)
# [2] = ARMC (sidereal time)
# [3] = Vertex
ascendant_tropical = ascmc[0]
mc_tropical = ascmc[1]
# Convert to sidereal
ayanamsa_value = swe.get_ayanamsa_ut(jd)
ascendant = (ascendant_tropical - ayanamsa_value) % 360
mc = (mc_tropical - ayanamsa_value) % 360
# Calculate all 12 house cusps (Whole Sign)
ascendant_sign = int(ascendant / 30)
houses = [(ascendant_sign + i) % 12 * 30 for i in range(12)]
return {
'ascendant': ascendant,
'mc': mc,
'houses': houses,
'ascendant_sign': longitude_to_sign(ascendant)
}
# Example: Mumbai coordinates
jd = date_to_julian_day(1995, 3, 15, 8, 30, 0)
latitude = 19.0760 # Mumbai latitude
longitude = 72.8777 # Mumbai longitude
lagna = calculate_ascendant(jd, latitude, longitude, 'lahiri')
print(f"Ascendant: {lagna['ascendant']:.4f}°")
print(f"Lagna in: {lagna['ascendant_sign']['sign']}")
print(f"MC: {lagna['mc']:.4f}°")
Part 5: Nakshatra Calculation
The 27 Nakshatras (lunar mansions) divide the zodiac into 13°20' segments. Critical for Dasha calculations and compatibility matching.
NAKSHATRAS = [
"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", "Dhanishta", "Shatabhisha",
"Purva Bhadrapada", "Uttara Bhadrapada", "Revati"
]
NAKSHATRA_LORDS = [
"Ketu", "Venus", "Sun", "Moon", "Mars",
"Rahu", "Jupiter", "Saturn", "Mercury", "Ketu",
"Venus", "Sun", "Moon", "Mars", "Rahu",
"Jupiter", "Saturn", "Mercury", "Ketu", "Venus",
"Sun", "Moon", "Mars", "Rahu", "Jupiter",
"Saturn", "Mercury"
]
def calculate_nakshatra(longitude):
"""
Calculate Nakshatra from sidereal longitude
Args:
longitude: Sidereal ecliptic longitude (0-360°)
Returns:
Dictionary with nakshatra details
"""
# Each nakshatra = 13°20' = 13.333...°
nakshatra_length = 360 / 27
nakshatra_num = int(longitude / nakshatra_length)
# Each nakshatra has 4 padas (quarters)
pada_length = nakshatra_length / 4
degree_in_nakshatra = longitude % nakshatra_length
pada = int(degree_in_nakshatra / pada_length) + 1
return {
'nakshatra': NAKSHATRAS[nakshatra_num],
'nakshatra_num': nakshatra_num,
'lord': NAKSHATRA_LORDS[nakshatra_num],
'pada': pada,
'degree_in_nakshatra': degree_in_nakshatra
}
# Example: Moon at 247.8° sidereal
moon_nakshatra = calculate_nakshatra(247.8)
print(f"Nakshatra: {moon_nakshatra['nakshatra']}")
print(f"Lord: {moon_nakshatra['lord']}")
print(f"Pada: {moon_nakshatra['pada']}")
Part 6: Divisional Charts (Vargas)
Divisional charts divide each sign into smaller segments to analyze specific life areas. D9 (Navamsa) is second most important after D1 (Rasi).
Navamsa (D9) Calculation
def calculate_navamsa(longitude):
"""
Calculate Navamsa (D9) position
Each sign (30°) is divided into 9 parts of 3°20' each
Args:
longitude: Sidereal longitude (0-360°)
Returns:
Navamsa longitude
"""
sign_num = int(longitude / 30)
degree_in_sign = longitude % 30
# Each navamsa = 3°20' = 3.333...°
navamsa_in_sign = int(degree_in_sign / (30/9))
# Navamsa sign calculation
# Aries, Leo, Sagittarius (Fire): start from Aries
# Taurus, Virgo, Capricorn (Earth): start from Capricorn
# Gemini, Libra, Aquarius (Air): start from Libra
# Cancer, Scorpio, Pisces (Water): start from Cancer
sign_element = sign_num % 3
if sign_element == 0: # Fire signs (0, 3, 6, 9)
start_sign = (sign_num // 3) * 3 # 0, 3, 6, 9
elif sign_element == 1: # Earth signs (1, 4, 7, 10)
start_sign = 9 # Capricorn
else: # Water/Air
start_sign = 6 if sign_num % 4 == 2 else 3
navamsa_sign = (start_sign + navamsa_in_sign) % 12
navamsa_longitude = navamsa_sign * 30
return navamsa_longitude
# Simplified universal formula
def calculate_divisional_chart(longitude, division):
"""
Universal divisional chart calculator
Args:
longitude: Sidereal longitude (0-360°)
division: D9, D10, D12, D16, D20, D24, D27, D30, D40, D45, D60
Returns:
Divisional chart longitude
"""
sign_num = int(longitude / 30)
degree_in_sign = longitude % 30
# Division within sign
part = int(degree_in_sign / (30 / division))
# Most divisional charts follow this pattern
# For odd sign (0, 2, 4, 6, 8, 10): start from Aries
# For even sign (1, 3, 5, 7, 9, 11): start from Libra (for odd divisions)
if division % 2 == 1: # Odd divisions (D9, D27, etc.)
if sign_num % 2 == 0:
divisional_sign = part
else:
divisional_sign = (6 + part) % 12
else: # Even divisions
divisional_sign = ((sign_num * division) + part) % 12
return divisional_sign * 30
# Example
sun_d9 = calculate_navamsa(271.5)
sun_d10 = calculate_divisional_chart(271.5, 10)
print(f"Sun D9 (Navamsa): {longitude_to_sign(sun_d9)['sign']}")
print(f"Sun D10 (Dashamsa): {longitude_to_sign(sun_d10)['sign']}")
All Major Divisional Charts
Part 7: Vimshottari Dasha Calculation
Dasha system calculates planetary periods based on Moon's nakshatra at birth. Most complex and critical calculation in Jyotish.
from datetime import datetime, timedelta
# Vimshottari period lengths (in years)
DASHA_YEARS = {
'Ketu': 7,
'Venus': 20,
'Sun': 6,
'Moon': 10,
'Mars': 7,
'Rahu': 18,
'Jupiter': 16,
'Saturn': 19,
'Mercury': 17
}
# Dasha sequence
DASHA_SEQUENCE = ['Ketu', 'Venus', 'Sun', 'Moon', 'Mars', 'Rahu', 'Jupiter', 'Saturn', 'Mercury']
def calculate_vimshottari_dasha(moon_longitude, birth_datetime):
"""
Calculate Vimshottari Dasha periods
Args:
moon_longitude: Moon's sidereal longitude at birth
birth_datetime: Birth datetime object
Returns:
List of dasha periods with dates
"""
# Get Moon's nakshatra
moon_nak = calculate_nakshatra(moon_longitude)
nakshatra_num = moon_nak['nakshatra_num']
degree_in_nak = moon_nak['degree_in_nakshatra']
# Determine starting Mahadasha lord
lord_index = nakshatra_num % 9
starting_lord = NAKSHATRA_LORDS[nakshatra_num]
# Calculate balance of starting Mahadasha
nakshatra_length = 360 / 27 # 13.333...°
completed_fraction = degree_in_nak / nakshatra_length
total_years = DASHA_YEARS[starting_lord]
balance_years = total_years * (1 - completed_fraction)
# Generate all Mahadashas
dashas = []
current_date = birth_datetime
# First Mahadasha (balance period)
end_date = current_date + timedelta(days=balance_years * 365.25)
dashas.append({
'planet': starting_lord,
'start_date': current_date,
'end_date': end_date,
'years': balance_years
})
current_date = end_date
# Remaining Mahadashas (complete 120-year cycle)
lord_idx = DASHA_SEQUENCE.index(starting_lord)
for i in range(1, 9): # 8 more periods to complete cycle
lord = DASHA_SEQUENCE[(lord_idx + i) % 9]
years = DASHA_YEARS[lord]
end_date = current_date + timedelta(days=years * 365.25)
dashas.append({
'planet': lord,
'start_date': current_date,
'end_date': end_date,
'years': years
})
current_date = end_date
return dashas
def calculate_antardasha(mahadasha_planet, maha_start, maha_end):
"""
Calculate Antardasha (sub-periods) within a Mahadasha
Args:
mahadasha_planet: Mahadasha lord
maha_start: Mahadasha start date
maha_end: Mahadasha end date
Returns:
List of Antardasha periods
"""
antardashas = []
total_days = (maha_end - maha_start).days
maha_years = DASHA_YEARS[mahadasha_planet]
# Antardasha sequence starts with Mahadasha lord
lord_idx = DASHA_SEQUENCE.index(mahadasha_planet)
current_date = maha_start
for i in range(9):
antar_lord = DASHA_SEQUENCE[(lord_idx + i) % 9]
antar_years = DASHA_YEARS[antar_lord]
# Antardasha duration = (Antar_years × Maha_years) / 120
antar_duration_years = (antar_years * maha_years) / 120
antar_days = int(antar_duration_years * 365.25)
end_date = current_date + timedelta(days=antar_days)
# Ensure we don't exceed Mahadasha end
if end_date > maha_end:
end_date = maha_end
antardashas.append({
'planet': antar_lord,
'start_date': current_date,
'end_date': end_date,
'months': antar_duration_years * 12
})
current_date = end_date
if current_date >= maha_end:
break
return antardashas
# Example
moon_long = 247.8 # Moon at Jyeshtha
birth_date = datetime(1995, 3, 15, 8, 30, 0)
dashas = calculate_vimshottari_dasha(moon_long, birth_date)
print("Vimshottari Mahadasha Timeline:")
print("=" * 60)
for d in dashas[:5]: # First 5 periods
print(f"{d['planet']:10} {d['start_date'].year}-{d['end_date'].year} ({d['years']:.2f} years)")
Part 8: Yogas (Planetary Combinations)
Yogas are specific planetary combinations that produce results. Calculating yogas requires analyzing planet positions, aspects, and house ownership.
def check_raja_yoga(planets, ascendant):
"""
Check for Raja Yoga (combinations of success/power)
Raja Yoga occurs when:
- Lords of Kendra (1,4,7,10) and Trikona (1,5,9) are conjunct
- Or aspect each other
Args:
planets: Dictionary of planetary positions
ascendant: Ascendant degree
Returns:
List of Raja Yogas present
"""
yogas = []
# Determine house ownership based on ascendant sign
asc_sign = int(ascendant / 30)
# Kendra houses: 1, 4, 7, 10
# Trikona houses: 1, 5, 9
# Simplified example: Jupiter-Venus conjunction
jupiter_sign = int(planets['Jupiter']['longitude'] / 30)
venus_sign = int(planets['Venus']['longitude'] / 30)
if jupiter_sign == venus_sign:
yogas.append({
'name': 'Guru-Shukra Yoga',
'description': 'Jupiter-Venus conjunction - wealth and wisdom',
'strength': 'Strong'
})
return yogas
def check_gaja_kesari_yoga(planets):
"""
Check for Gaja Kesari Yoga
Occurs when Jupiter is in Kendra (1,4,7,10) from Moon
One of the most auspicious yogas
"""
moon_sign = int(planets['Moon']['longitude'] / 30)
jupiter_sign = int(planets['Jupiter']['longitude'] / 30)
# Calculate houses from Moon
houses_from_moon = (jupiter_sign - moon_sign) % 12
# Kendra from Moon: 0, 3, 6, 9 (1st, 4th, 7th, 10th houses)
if houses_from_moon in [0, 3, 6, 9]:
return {
'present': True,
'description': 'Jupiter in Kendra from Moon - fame, intelligence, prosperity',
'strength': 'Strong' if houses_from_moon == 0 else 'Moderate'
}
return {'present': False}
def check_neecha_bhanga_yoga(planets):
"""
Check for Neecha Bhanga Raja Yoga
Cancellation of debilitation - turns weakness into strength
"""
# Debilitation signs for each planet
debilitation = {
'Sun': 6, # Libra
'Moon': 7, # Scorpio
'Mars': 3, # Cancer
'Mercury': 11, # Pisces
'Jupiter': 9, # Capricorn
'Venus': 5, # Virgo
'Saturn': 0 # Aries
}
yogas = []
for planet, deb_sign in debilitation.items():
if planet in planets:
planet_sign = int(planets[planet]['longitude'] / 30)
if planet_sign == deb_sign:
# Check for cancellation conditions
# (simplified - actual calculation is more complex)
yogas.append({
'planet': planet,
'debilitated': True,
'cancellation': 'Partial' # Would check actual conditions
})
return yogas
Complete Birth Chart Calculator
Putting it all together - a complete birth chart calculator with all components:
class VedicBirthChart:
def __init__(self, date, time, latitude, longitude, ayanamsa='lahiri'):
"""Complete Vedic birth chart calculator"""
self.date = date
self.time = time
self.latitude = latitude
self.longitude = longitude
self.ayanamsa = ayanamsa
# Calculate Julian Day
self.jd = self._date_to_jd()
# Calculate all components
self.planets = self._calculate_planets()
self.ascendant_data = self._calculate_ascendant()
self.houses = self._calculate_houses()
self.nakshatras = self._calculate_nakshatras()
self.divisional_charts = self._calculate_divisional_charts()
self.dashas = self._calculate_dashas()
self.yogas = self._detect_yogas()
def _date_to_jd(self):
"""Convert datetime to Julian Day"""
year = self.date.year
month = self.date.month
day = self.date.day
hour = self.time.hour
minute = self.time.minute
return date_to_julian_day(year, month, day, hour, minute, 0)
def _calculate_planets(self):
"""Calculate all planetary positions"""
planets = {}
for name, planet_id in PLANETS.items():
pos = get_planet_position(self.jd, planet_id)
# Convert to sidereal
sidereal_long, _ = convert_to_sidereal(
pos['longitude'],
self.jd,
self.ayanamsa
)
planets[name] = {
'longitude': sidereal_long,
'latitude': pos['latitude'],
'speed': pos['speed'],
'retrograde': pos['retrograde'],
'sign': longitude_to_sign(sidereal_long)
}
return planets
def to_json(self):
"""Export complete chart as JSON"""
return {
'birthDetails': {
'date': self.date.isoformat(),
'time': self.time.isoformat(),
'latitude': self.latitude,
'longitude': self.longitude
},
'planets': self.planets,
'ascendant': self.ascendant_data,
'houses': self.houses,
'nakshatras': self.nakshatras,
'divisionalCharts': self.divisional_charts,
'dashas': self.dashas[:5], # First 5 Mahadashas
'yogas': self.yogas
}
# Usage
from datetime import datetime, time
birth_date = datetime(1995, 3, 15)
birth_time = time(8, 30, 0)
chart = VedicBirthChart(
date=birth_date,
time=birth_time,
latitude=19.0760, # Mumbai
longitude=72.8777,
ayanamsa='lahiri'
)
# Get complete chart
import json
print(json.dumps(chart.to_json(), indent=2))
Performance Optimization Tips
Calculation Optimization
- Cache Swiss Ephemeris results: Planet positions don't change for the same JD
- Batch calculations: Calculate all planets in one Swiss Ephemeris call
- Precompute divisional charts: Store in database, recalculate only on chart updates
- Use lookup tables: For nakshatra lords, sign rulers, aspect angles
- Lazy loading: Calculate Dashas/Yogas only when requested
Common Calculation Errors to Avoid
Timezone Issues
Always convert birth time to UTC before calculating JD. Ignoring timezones causes 30-minute to 5-hour errors in Ascendant.
Wrong Ayanamsa
Using tropical positions for Vedic calculations. Always subtract ayanamsa. Difference is ~24° currently.
Modular Arithmetic Errors
Forgetting to apply % 360 or % 12 can cause longitude values outside valid ranges.
Floating Point Precision
Using integers for degree calculations loses precision. Use float64 for all astronomical calculations.
Skip the Complexity - Use Vedika API
Implementing accurate Jyotish calculations takes months of development. Vedika API provides Swiss Ephemeris accuracy, all divisional charts, dasha systems, and yoga detection via simple REST calls.
Frequently Asked Questions
What is ayanamsa in Vedic astrology?
Ayanamsa is the precession correction applied to convert tropical (Western) planetary positions to sidereal (Vedic) positions. Lahiri ayanamsa is most popular in India (24°09' in 2025). It accounts for the 23.4° axial precession of Earth, which causes a ~1° shift every 72 years.
How are divisional charts (Vargas) calculated?
Divisional charts divide each zodiac sign into equal parts. D9 (Navamsa) divides each 30° sign into 9 parts of 3°20' each. Formula: Navamsa_sign = ((sign_num × 9) + int(degree_in_sign / 3.333)) % 12. D10, D12, D16, D20, D24, D27, D30, D40, D45, D60 follow similar division patterns.
What is the difference between tropical and sidereal zodiac?
Tropical zodiac (Western) is fixed to seasons - Aries starts at spring equinox. Sidereal zodiac (Vedic) is fixed to constellations. Due to Earth's precession, they differ by ~24° (ayanamsa). Most Vedic astrologers use Lahiri ayanamsa for sidereal calculations.
How accurate are Swiss Ephemeris calculations?
Swiss Ephemeris provides planetary positions accurate to 0.001 arcseconds (milliarcsecond precision) for dates 3000 BCE to 3000 CE. It's the gold standard for astrology software, used by NASA and professional astronomers. Accuracy degrades slightly outside this range.
What house system should I use for Vedic astrology?
Most Vedic astrologers use Whole Sign houses where each house = one zodiac sign starting from Ascendant. Some use Equal House (30° divisions from Ascendant degree). Placidus, used in Western astrology, is rarely used in Jyotish. Whole Sign is simplest and most traditional.