Try Astrologer API

Subscribe to support and grow the project.

Astrological Subject Factory #

The AstrologicalSubjectFactory is the central mechanism in Kerykeion for creating AstrologicalSubjectModel instances. It handles the complex astronomical calculations required to generate a chart, supporting widely used zodiacs, house systems, and coordinate perspectives.

Key Features #

  • Precision: Uses libephemeris by default. A fresh install bundles DE440s coverage for 1849–2150; wider medium/extended data tiers (including the full DE441 range) must be downloaded separately. An optional Swiss Ephemeris (pyswisseph) backend is also available.
  • Flexibility: Supports Tropical/Sidereal zodiacs, multiple House systems (Placidus, Whole Sign, etc.), and various coordinate (Geocentric/Heliocentric) perspectives.
  • Optimization: The active_points argument allows you to calculate only what you need, saving resources.
  • Online/Offline: Can resolve locations automatically via GeoNames (Online) or accept raw coordinates (Offline).

Factory Methods #

1. from_birth_data (Primary) #

Creates a subject from standard civil birth details.

# doc-snippet: no-run — requires your own GeoNames account (online)
from kerykeion import AstrologicalSubjectFactory

# Online mode (requires GeoNames username)
subject = AstrologicalSubjectFactory.from_birth_data(
    name="John Doe",
    year=1990, month=6, day=15,
    hour=14, minute=30,
    city="London", nation="GB",
    geonames_username="your_username",
    zodiac_type="Tropical",
    houses_system_identifier="P"  # Placidus
)

print(f"Sun: {subject.sun.sign} {subject.sun.abs_pos:.2f}°")
print(f"Ascendant: {subject.ascendant.sign} {subject.ascendant.abs_pos:.2f}°")

Parameters:

Parameter Type Default Description
name str "Now" Name or identifier for the subject.
year, month, day Optional[int] None Date components. Defaults to current date if omitted.
hour, minute Optional[int] None Time components. Defaults to current time if omitted.
seconds int 0 Seconds component of the time. Keyword-only.
city Optional[str] None City name (used with online=True).
nation Optional[str] None ISO Country code (e.g., “GB”).
lng, lat Optional[float] None Coordinates (used with online=False or as override).
tz_str Optional[str] None Timezone ID (e.g., “Europe/London”). Required if online=False.
geonames_username Optional[str] None GeoNames username (required for online=True). Can also be set via KERYKEION_GEONAMES_USERNAME env var.
online bool True Whether to fetch location/timezone data from GeoNames API.
zodiac_type ZodiacType "Tropical" “Tropical” or “Sidereal”.
sidereal_mode Optional[SiderealMode] None Ayanamsha mode (e.g. "LAHIRI"). Defaults to FAGAN_BRADLEY when zodiac_type="Sidereal"; setting it with a Tropical zodiac raises KerykeionException.
houses_system_identifier HousesSystemIdentifier "P" House system code (e.g., “P” for Placidus, “W” for Whole Sign).
perspective_type PerspectiveType "Apparent Geocentric" 11 options including Geocentric, Heliocentric, Topocentric, Barycentric, and Planetocentric variants.
active_points Optional[List[str]] None List of points to calculate. If None, uses DEFAULT_ACTIVE_POINTS (14 points).
is_dst Optional[bool] None Which UTC offset to take when a transition makes the wall time non-unique: True = the larger, False = the smaller, None = raise (see FAQ).
cache_expire_after_days int 30 Days to cache online location lookups.
calculate_lunar_phase bool True Whether to calculate lunar phase details.
altitude Optional[float] None Altitude in meters (used with Topocentric perspective).
suppress_geonames_warning bool False Suppress the warning about using the default shared GeoNames username. Keyword-only.
custom_ayanamsa_t0 Optional[float] None Reference epoch (Julian Day) for USER sidereal mode.
custom_ayanamsa_ayan_t0 Optional[float] None Ayanamsa offset in degrees at the reference epoch. Required with USER.
calculate_dignities bool False Compute essential dignity scores for each planet.
calculate_nakshatra bool False Compute Vedic nakshatra, pada, and dasha lord for each point.
nakshatra_ayanamsa Optional[SiderealMode] "LAHIRI" Ayanamsa used to place the nakshatras on a non-sidereal chart. Ignored when the chart is Sidereal. None restores the pre-v6 uncorrected values.
calculate_gauquelin bool False Compute Gauquelin sector (1-36) for each point.
calculate_nutation bool False Compute nutation in longitude and obliquity.
calculate_local_space bool False Compute azimuth and altitude for each point.
active_fixed_stars Optional[List[str]] None Fixed star names to compute (e.g., ["Regulus"]). Access via find_fixed_star().

2. from_iso_utc_time #

Creates a subject from a UTC ISO 8601 timestamp, useful for event charts or standardized data.

# doc-snippet: no-run — requires your own GeoNames account (online)
subject = AstrologicalSubjectFactory.from_iso_utc_time(
    name="Event Chart",
    iso_utc_time="2023-06-21T12:00:00Z",
    city="New York", nation="US",
    geonames_username="your_username"
)

Parameters:

Parameter Type Default Description
name str Required Name or identifier for the subject.
iso_utc_time str Required UTC timestamp in ISO 8601 format (e.g., "2023-06-21T12:00:00Z").
city Optional[str] None City used for online lookup; omitted locations fall back to Greenwich.
nation Optional[str] None ISO country code used for online lookup; omitted locations fall back to "GB".
tz_str str "Etc/GMT" Timezone string.
lng, lat Optional[float] None Explicit coordinates override lookup values. Missing values are looked up online or fall back to 0.0, 51.5074 offline.
online bool True Whether to resolve location via GeoNames API.
zodiac_type ZodiacType "Tropical" "Tropical" or "Sidereal".
sidereal_mode Optional[SiderealMode] None Ayanamsha mode (e.g. "LAHIRI"). Defaults to FAGAN_BRADLEY when zodiac_type="Sidereal"; setting it with a Tropical zodiac raises KerykeionException.
houses_system_identifier HousesSystemIdentifier "P" House system code.
perspective_type PerspectiveType "Apparent Geocentric" Calculation perspective.
active_points Optional[List[str]] None Points to calculate.
suppress_geonames_warning bool False Suppress the default GeoNames username warning.
altitude Optional[float] None Altitude in meters above sea level.
calculate_lunar_phase bool True Whether to calculate lunar phase data.
custom_ayanamsa_t0 Optional[float] None Julian Day epoch for custom ayanamsa (requires sidereal_mode="USER").
custom_ayanamsa_ayan_t0 Optional[float] None Ayanamsa degrees at epoch (requires sidereal_mode="USER").
geonames_username str DEFAULT_GEONAMES_USERNAME GeoNames API username.
calculate_dignities bool False Calculate essential dignities for each point.
calculate_nakshatra bool False Calculate Vedic Nakshatra/Pada/Dasha lord.
nakshatra_ayanamsa Optional[SiderealMode] "LAHIRI" Ayanamsa for the nakshatras on a non-sidereal chart; None = pre-v6 behaviour.
calculate_gauquelin bool False Calculate Gauquelin 36-sector positions.
calculate_nutation bool False Include true/mean obliquity and nutation data.
calculate_local_space bool False Calculate azimuth and altitude for each point.
active_fixed_stars Optional[List[str]] None Fixed stars to compute into subject.fixed_stars. Default None computes none; DEFAULT_FIXED_STARS is an opt-in 23-star preset.

3. from_current_time #

Creates a subject for the current moment (“Now”), useful for Horary astrology or transits. Uses the system clock – does not accept year/month/day/hour/minute parameters.

# doc-snippet: no-run — requires your own GeoNames account (online)
now_chart = AstrologicalSubjectFactory.from_current_time(
    name="Current Transits",
    city="Tokyo", nation="JP",
    geonames_username="your_username"
)

Parameters:

Parameter Type Default Description
name str "Now" Name or identifier.
city Optional[str] None City name (used with online=True).
nation Optional[str] None ISO Country code.
lng, lat Optional[float] None Coordinates (used with online=False).
tz_str Optional[str] None Timezone string. Required if online=False.
online bool True Whether to resolve location via GeoNames API.
zodiac_type ZodiacType "Tropical" "Tropical" or "Sidereal".
sidereal_mode Optional[SiderealMode] None Ayanamsha mode (e.g. "LAHIRI"). Defaults to FAGAN_BRADLEY when zodiac_type="Sidereal"; setting it with a Tropical zodiac raises KerykeionException.
houses_system_identifier HousesSystemIdentifier "P" House system code.
perspective_type PerspectiveType "Apparent Geocentric" Calculation perspective.
active_points Optional[List[str]] None Points to calculate.
suppress_geonames_warning bool False Suppress the default GeoNames username warning.
geonames_username Optional[str] None GeoNames API username.
calculate_lunar_phase bool True Whether to calculate lunar phase data.
custom_ayanamsa_t0 Optional[float] None Julian Day epoch for custom ayanamsa (requires sidereal_mode="USER").
custom_ayanamsa_ayan_t0 Optional[float] None Ayanamsa degrees at epoch (requires sidereal_mode="USER").
altitude Optional[float] None Observer altitude in meters (used by Topocentric calculations).
active_fixed_stars Optional[List[str]] None Fixed-star catalog names to compute into subject.fixed_stars.
calculate_dignities bool False Calculate essential dignities for each point.
calculate_nakshatra bool False Calculate Vedic Nakshatra/Pada/Dasha lord data.
nakshatra_ayanamsa Optional[SiderealMode] "LAHIRI" Ayanamsa for the nakshatras on a non-sidereal chart; None = pre-v6 behaviour.
calculate_gauquelin bool False Calculate Gauquelin 36-sector positions.
calculate_nutation bool False Include true/mean obliquity and nutation data.
calculate_local_space bool False Calculate azimuth and altitude for each point.

Understanding Position Fields #

Every KerykeionPointModel (planet, angle, etc.) has two position fields:

Field Range Description
position 0° - 30° Degree within the sign (e.g., 22.54° of Cancer).
abs_pos 0° - 360° Absolute ecliptic longitude (e.g., 112.54° on the zodiac).

Use position for display purposes and abs_pos for calculations (aspect detection, midpoints, etc.).

Configuration Options #

House Systems (houses_system_identifier) #

Identifier System Description
“P” Placidus Default. Time-based system, standard in modern Western astrology.
“K” Koch Time-based, often used in German schools.
“W” Whole Sign Each house is exactly 30°, matching signs. Standard in Hellenistic/Vedic.
“R” Regiomontanus Standard for Horary astrology.
“A” Equal Equal 30° houses starting from Ascendant.
“M” Morinus Space-based system.

subject.coincident_house_cusps (list[list[int]]) groups the house numbers whose cusps fall on the same longitude, leaving the houses between them with no width. It is empty for every chart whose twelve cusps are twelve distinct points, which is every ordinary chart; some systems crowd cusps together at extreme latitudes, and the cusps are reported as computed rather than repaired, so this field is where that shows.

Zodiac Types #

  • Tropical (Default): Fixed to seasons (0° Aries = Vernal Equinox). Standard in Western astrology.
  • Sidereal: Fixed to constellations. Standard in Vedic astrology. Requires sidereal_mode.
    • 48 modes total: 47 named + USER for custom ayanamsa definitions.
    • Common Modes: LAHIRI (most common), FAGAN_BRADLEY, RAMAN.
    • USER mode: Requires custom_ayanamsa_t0 (Julian Day epoch) and custom_ayanamsa_ayan_t0 (degrees at epoch).
    • The computed ayanamsa offset is available via subject.ayanamsa_value (degrees, None for tropical).

Perspectives #

  • Apparent Geocentric (Default): Earth-centered, includes light-time correction.
  • True Geocentric: Earth-centered, geometric position only.
  • Heliocentric: Sun-centered. Earth becomes a planet.
  • Topocentric: Observer-centered (surface of Earth), accounts for parallax.
  • Barycentric: Solar system barycenter.
  • Selenocentric: Moon-centered.
  • Mercurycentric, Venuscentric, Marscentric, Jupitercentric, Saturncentric: Planet-centered.

V6 Optional Enrichments #

These opt-in features add extra data to the subject model. All are disabled by default and have zero overhead when not enabled.

Essential Dignities (calculate_dignities=True) #

Adds five fields to each point: essential_dignity (the strongest dignity held: "Domicile", "Exaltation", "Triplicity", "Term", "Face", or, when only a debility applies, "Detriment" or "Fall", and "Peregrine" when none applies), dignity_score (the summed Ptolemaic weights), term_ruler, decan_ruler, and decan_number.

subject = AstrologicalSubjectFactory.from_birth_data(
    "Alice", 1990, 6, 15, 12, 0,
    lng=-0.1276, lat=51.5074, tz_str="Europe/London", online=False,
    calculate_dignities=True
)
print(subject.sun.essential_dignity)  # e.g. "Domicile"

Vedic Nakshatras (calculate_nakshatra=True) #

Adds nakshatra, nakshatra_number, nakshatra_pada, and nakshatra_lord fields to every point.

The nakshatras divide the sidereal zodiac. A sidereal chart supplies those longitudes itself. Any other chart does not, so its longitudes are rotated by nakshatra_ayanamsa (default "LAHIRI" — the ayanamsa Jyotish uses, not the FAGAN_BRADLEY default of sidereal_mode) for the 27-fold division only: the chart stays tropical, and its nakshatras match the sidereal chart cast in the same mode exactly.

The subject records what was used, in nakshatra_ayanamsa and nakshatra_ayanamsa_value. Both are None on a sidereal chart — where the parameter is ignored and sidereal_mode / ayanamsa_value are the answer — and on a chart that computed no nakshatras.

nakshatra_ayanamsa=None restores the pre-v6 behaviour: tropical longitudes fed straight to the sidereal division, every value about two nakshatras off, and one warning per subject. It exists only to reproduce values computed by earlier versions.

tropical = AstrologicalSubjectFactory.from_birth_data(
    "Alice", 1990, 6, 15, 12, 0,
    lng=-0.1276, lat=51.5074, tz_str="Europe/London", online=False,
    calculate_nakshatra=True
)
sidereal = AstrologicalSubjectFactory.from_birth_data(
    "Alice", 1990, 6, 15, 12, 0,
    lng=-0.1276, lat=51.5074, tz_str="Europe/London", online=False,
    zodiac_type="Sidereal", sidereal_mode="LAHIRI",
    calculate_nakshatra=True
)
print(f"{tropical.moon.nakshatra}, pada {tropical.moon.nakshatra_pada}")
print(tropical.nakshatra_ayanamsa, round(tropical.nakshatra_ayanamsa_value, 4))
print(tropical.moon.nakshatra == sidereal.moon.nakshatra)   # True

Derived charts inherit the setting: PlanetaryReturnFactory (which also accepts nakshatra_ayanamsa of its own — an explicit value outranks the natal, None included) and SecondaryProgressionFactory copy the natal’s nakshatra_ayanamsa, and a Davison composite adopts it only when both parents agree — otherwise it warns and falls back to the default. For "USER", agreeing means agreeing on the definition (custom_ayanamsa_t0 and custom_ayanamsa_ayan_t0), which the composite carries over with the mode: the name alone is not an ayanamsa. What is inherited is a mode that was actually used: a natal that computed no nakshatras also records None, and that None is not the legacy opt-out. PlanetaryReturnFactory(..., calculate_nakshatra=True) on such a natal therefore starts from the "LAHIRI" default, exactly as casting the same instant directly would.

Gauquelin Sectors (calculate_gauquelin=True) #

Adds gauquelin_sector (Optional[float], 1-36, fractional within the sector) to each point, plus gauquelin_sector_cusps on the subject.

Nutation (calculate_nutation=True) #

Adds subject.nutation with true_obliquity, mean_obliquity, nutation_longitude, and nutation_obliquity.

Local Space (calculate_local_space=True) #

Adds azimuth and altitude_above_horizon fields for each point. Useful for astro-locality work.

Motion State #

Always computed for the ten planets (Sun through Pluto) in Earth-centred perspectives. Access via subject.sun.motion_state. Returns a MotionState literal: "stationary_retrograde", "stationary_direct" or "stationary" (inside the band of < 5% of mean motion, either direction), "retrograde" (backward, outside that band), "slow" (< 80%), "average" (80-120%), or "fast" (> 120%). None for nodes, asteroids, fixed stars, and non-geocentric perspectives.

The stationary band brackets zero speed and is tested before the sign, so a planet edging backwards at a hundredth of its mean motion is reported as a station instead of a plain retrograde. Which station it is comes from the trend rather than the sign: the factory samples the speed again a day later, and a speed falling through the band opens the retrograde phase ("stationary_retrograde") while a speed rising through it closes the phase ("stationary_direct"). The extra sample is only ever spent on a body already inside the band; where it is unavailable the generic "stationary" stands.

from kerykeion import AstrologicalSubjectFactory

subject = AstrologicalSubjectFactory.from_birth_data(
    "Mercury Station", 1990, 8, 25, 12, 0,
    lng=-0.1276, lat=51.5074, tz_str="Europe/London",
    online=False, suppress_geonames_warning=True,
)
print(subject.mercury.motion_state)  # stationary_retrograde
print(subject.mercury.speed)         # 0.0123... — still forward, already turning

For the instants of the stations themselves rather than the state of one chart, see Retrograde Stations, which reports the same two events as SR and SD.

Declination & Out-of-Bounds #

Always computed. Access via subject.sun.declination and subject.sun.is_out_of_bounds. A planet is out-of-bounds when its declination exceeds the Sun’s maximum (~23.44°).

Lilith Variants & Priapus #

Enable via active_points: "Mean_Lilith", "True_Lilith", "Interpolated_Lilith", "Mean_Priapus", "True_Priapus". None of these are in DEFAULT_ACTIVE_POINTS — every Lilith/Priapus variant is opt-in.

Performance & Optimization #

Subject creation involves complex calculations. For high-performance applications (e.g., scanning thousands of dates), limit the active_points to only what you need.

# Minimal calculation (approx. 3-4x faster than full)
fast_chart = AstrologicalSubjectFactory.from_birth_data(
    name="Research Point",
    year=2000, month=1, day=1,
    hour=12, minute=0,
    lng=-0.1276, lat=51.5074, tz_str="Europe/London", online=False,
    # Only calculate luminaries and angles
    active_points=["Sun", "Moon", "Ascendant", "Medium_Coeli"]
)

Internal Types #

These @dataclass structures are used internally but are exposed for reference.

ChartConfiguration #

Dataclass holding chart calculation settings. Fields: zodiac_type, sidereal_mode, houses_system_identifier, perspective_type, custom_ayanamsa_t0, custom_ayanamsa_ayan_t0, calculate_dignities, calculate_nakshatra, nakshatra_ayanamsa, calculate_gauquelin, calculate_nutation, calculate_local_space, active_fixed_stars.

LocationData #

Dataclass carrying raw location information. Fields: city, nation, lng, lat, tz_str, altitude, city_data.

ephemeris_context #

Helper context manager for thread-safe ephemeris calculations. Not intended for public use.

Memory Usage:

  • Full Chart: ~50KB
  • Minimal Chart: ~15KB

Thread Safety Note #

Kerykeion serializes all ephemeris access internally through a process-wide lock, so AstrologicalSubjectFactory is safe to call from multiple threads (e.g., Gunicorn/Uvicorn workers). The lock does mean concurrent calculations within one process run sequentially; for CPU-bound throughput, prefer multiple worker processes. Kerykeion result objects are self-contained and can be shared freely once created.