Astrolabe object
The fields of Astrolabe, its lookup methods, and the surrounded-palace predicates.
Astrolabe is what charting produces and the entry point for every query. It is a frozen=True
dataclass holding all the data of the twelve palaces along with chart-level information such as the
four pillars, the soul and body stars and the five elements class.
chart = Astro().by_solar("2000-8-16", 2, "female", language="en-US")The examples on this page all chart in en-US, so the display values in the output are the English
translations. Charting in another language changes those strings and nothing else — the *_key
identifiers and the results of every predicate method stay the same.
Fields
palace
Purpose Fetch a palace by index, by name, or as the body or original palace.
Zi Wei meaning The twelve palaces are the skeleton of a chart. Once the Soul palace is fixed the other eleven follow counterclockwise in a fixed order. The "body palace" is whichever of the twelve also carries that flag, marking where acquired effort concentrates; the "palace of origin" is the one whose stem matches the birth-year stem, marking where matters originate.
Signature
def palace(self, index_or_name: int | PalaceName | str) -> Palace | NoneParameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
index_or_name | int | str | Yes | — | Four spellings, see the table below |
| Spelling | Example | Meaning |
|---|---|---|
| Index | chart.palace(0) | Palace index 0–11, where 0 is the Yin palace |
| Name key | chart.palace("soulPalace") | One of the twelve palace-name keys, i.e. the value set of PalaceName |
| Palace name in the charting language | chart.palace("soul") | The palace-name text as translated for the chart's language |
| Body palace | chart.palace("bodyPalace") | Whichever palace carries the body-palace flag |
| Palace of origin | chart.palace("originalPalace") | The palace whose stem matches the birth-year stem |
Return value Palace | None. An out-of-range index or a misspelled name returns None; the
name, body-palace and origin-palace spellings all resolve on any chart as long as they are spelled
correctly.
Example
soul = chart.palace("soulPalace")
print(soul.name, soul.heavenly_stem + soul.earthly_branch)
print("body palace falls in", chart.palace("bodyPalace").name)
print("palace of origin is", chart.palace("originalPalace").name)
print("the Yin palace is", chart.palace(0).name)Output
soul renwoo
body palace falls in career
palace of origin is spouse
the Yin palace is wealthEdge cases and pitfalls
star / star_in_palace
Purpose Find a star by key, or get it together with the palace it sits in.
Signature
def star(self, star: str) -> Star | None
def star_in_palace(self, star: str) -> tuple[Star, Palace] | NoneParameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
star | str | Yes | — | A star key (such as "ziweiMaj"), or the star name in the chart's charting language (such as "emperor") |
Return value None when the star is not on this chart.
star_in_palace returns a (star, palace) tuple, sparing a further call to star.palace().
Example
ziwei = chart.star("ziweiMaj")
print(ziwei.name, "sits in", ziwei.palace().name)
print("its opposite palace is", ziwei.opposite_palace().name)
print("brightness", ziwei.brightness, "mutagen", ziwei.mutagen)
star, palace = chart.star_in_palace("ziweiMaj")
print(star.key, palace.name_key)Output
emperor sits in soul
its opposite palace is surface
brightness [+3] mutagen None
ziweiMaj soulPalaceEdge cases and pitfalls
The search covers only the three groups of major, minor and adjective stars. The Changsheng, Boshi,
Sui-qian and Jiang-qian gods are one-per-palace marks rather than star lists — read them from fields
like palace.changsheng12_key.
surrounded_palaces
Purpose Fetch the surrounded palaces of a target palace.
Zi Wei meaning The surrounded set is the most commonly used reading scope in Zi Wei Dou Shu: the palace itself, its opposite (index +6), the career position (+4) and the wealth position (+8). The four are read together rather than the palace alone, because the stars of the opposite and trine palaces bear on the palace's affairs just as much.
Signature
def surrounded_palaces(self, index_or_name: int | PalaceName | str) -> SurroundedPalaces | NoneParameters Same as palace; all four spellings are supported.
Return value SurroundedPalaces | None, holding the four Palaces target / opposite /
wealth / career. Returns None when the palace cannot be located (out-of-range index or
misspelled name). Its predicates are on Surrounded palaces.
Example
sp = chart.surrounded_palaces("soulPalace")
print(sp.target.name, sp.opposite.name, sp.wealth.name, sp.career.name)
print("Ziwei in the surrounded set:", sp.have(["ziweiMaj"]))Output
soul surface wealth career
Ziwei in the surrounded set: Trueis_surrounded / is_surrounded_one_of / not_surrounded
Purpose Test the surrounded palaces of a palace straight from the chart, skipping the step of fetching the set first.
Signature
def is_surrounded(self, index_or_name: int | PalaceName | str, stars: list[str]) -> bool
def is_surrounded_one_of(self, index_or_name: int | PalaceName | str, stars: list[str]) -> bool
def not_surrounded(self, index_or_name: int | PalaceName | str, stars: list[str]) -> boolParameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
index_or_name | int | str | Yes | — | Located the same way as in palace |
stars | list[str] | Yes | — | A list of star keys |
Return value
| Method | Meaning |
|---|---|
is_surrounded | Every star in the list is in the surrounded set |
is_surrounded_one_of | At least one star in the list is in the surrounded set |
not_surrounded | None of the stars in the list is in the surrounded set |
Example
print(chart.is_surrounded("soulPalace", ["ziweiMaj", "tianxiangMaj"]))
print(chart.is_surrounded_one_of("soulPalace", ["qishaMaj", "pojunMaj"]))
print(chart.not_surrounded("soulPalace", ["huoxingMin"]))Output
True
False
TrueThe Soul palace holds only Ziwei, while Tianxiang sits in the Wealth palace, one of the trine — hence the first line is true. Neither Qisha nor Pojun is in any of the four, hence the second is false.
Edge cases and pitfalls
What an empty list returns
With an empty stars list, is_surrounded and not_surrounded return True ("all elements satisfy"
and "no element fails" both hold vacuously) while is_surrounded_one_of returns False.
Make sure the list is non-empty before calling.
horoscope
Purpose Compute the horoscope for a target date, starting from this chart.
Signature
def horoscope(
self,
target_date: str | None = None,
target_time_index: int | None = None,
) -> HoroscopeParameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
target_date | str | None | No | None | Target solar date; today when omitted |
target_time_index | int | None | No | None | Target hour index; the current hour when omitted |
Return value Horoscope — a horoscope object holding this chart, so palace lookups across the six
scopes need not be passed the astrolabe again.
Details on the horoscope object.
Example
h = chart.horoscope("2025-6-1", 0)
print("decadal", h.decadal.heavenly_stem + h.decadal.earthly_branch)
print("yearly ", h.yearly.heavenly_stem + h.yearly.earthly_branch)
# both parameters can be omitted for right now
now = chart.horoscope()Output
decadal gengchen
yearly yisito_text
Purpose The chart's semantic text: a complete description for language models and people;
str(chart) is equivalent.
Signature
def to_text(self) -> strReturn value str — sectioned plain text in the charting language: basic info, the twelve
palaces, and the pattern hits. The full format is on Semantic text.
Example
print(chart.to_text()[:77])Output
=== Basic Info ===
Gender: female
Solar Date: 2000-8-16
Lunar Date: 二〇〇〇年七月十七For single-palace and surrounded-palace text see palace(...).to_text() and
surrounded_palaces(...).to_text(); for pattern text see patterns_to_text on
Patterns.
to_dict / to_json
Purpose Export the chart as JSON matching the field contract of JS iztro.
Signature
def to_dict(self) -> dict[str, Any]
def to_json(self, **kwargs: Any) -> strParameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
kwargs | — | No | — | to_json only: forwarded to json.dumps, e.g. indent=2, sort_keys=True |
to_json defaults to ensure_ascii=False, so non-ASCII characters land in the output directly rather
than as \uXXXX.
Return value to_dict returns a deep copy of the underlying DTO — camelCase keys, values
translated for the charting language, plus the *Key language-independent identifiers and the
charting context. Mutating it does not affect the chart.
to_json returns the same data as a JSON string, matching iztro's
JSON.stringify(astrolabe) key for key and value for value.
Example
d = chart.to_dict()
print(d["solarDate"], d["palaces"][4]["nameKey"])
print(d["config"]["yearDivide"], d["genderKey"], d["timeIndex"])
import json
print(json.dumps({k: d[k] for k in ("gender", "solarDate", "lunarDate")},
ensure_ascii=False))
print(len(chart.to_json()) > 10000, chart.to_json()[:1])Output
2000-8-16 soulPalace
normal female 2
{"gender": "female", "solarDate": "2000-8-16", "lunarDate": "二〇〇〇年七月十七"}
True {The key order is lexicographic
When the native extension converts the underlying DTO into a Python dict the keys come out sorted by
name, so the top-level keys of to_dict() / to_json() run body, bodyKey, chineseDate, … rather
than in iztro's declaration order. The names and values correspond one for one; only the arrangement
differs. For a fixed order, pick out the keys you need yourself.
Edge cases and pitfalls
Do not export with dataclasses.asdict
Astrolabe, Palace and Star are all dataclasses, but palaces and stars each hold a reference back
to the chart (_astrolabe / _palace). dataclasses.asdict(chart) follows that back-reference into
infinite recursion and ends in RecursionError.
Always export through to_dict() / to_json() — they take the underlying DTO directly, so they
neither recurse nor lose fields.
The override tables are not in the export
config echoes only the six switches. The custom mutagen and brightness tables passed in at charting
time are input rather than result and do not enter the DTO — matching the field contract of JS
iztro. To record which tables were used, keep your ChartConfig on your own call site.
Horoscope carries a pair of methods by the same names and the same shape; see
the horoscope object.