caelus 0.18.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/chart.d.ts +38 -0
- package/dist/src/chart.js +63 -0
- package/dist/src/interpret.d.ts +11 -0
- package/dist/src/interpret.js +13 -0
- package/dist/src/interpretation.d.ts +39 -2
- package/dist/src/interpretation.js +21 -1
- package/package.json +1 -1
package/dist/src/chart.d.ts
CHANGED
|
@@ -242,6 +242,44 @@ export declare class Engine {
|
|
|
242
242
|
* @returns Sorted catalog star names.
|
|
243
243
|
*/
|
|
244
244
|
starNames(): string[];
|
|
245
|
+
/**
|
|
246
|
+
* Fixed-star conjunctions in a chart: each body within `orb` of a catalog
|
|
247
|
+
* star, in the chart's own zodiac. Feed the result to
|
|
248
|
+
* {@link interpretationContext} as `stars` to project `star` fact atoms (the
|
|
249
|
+
* Chart itself carries no star catalog).
|
|
250
|
+
*
|
|
251
|
+
* @param chart A chart from {@link Engine.chart} / {@link Engine.chartAt}.
|
|
252
|
+
* @param opts `orb` (default 1°); `stars` to restrict to named stars (then no
|
|
253
|
+
* magnitude filter); else `maxMag` keeps only stars brighter than it
|
|
254
|
+
* (default 2.5) so obscure catalog entries do not flood the result.
|
|
255
|
+
* @returns Conjunctions sorted by increasing orb.
|
|
256
|
+
*/
|
|
257
|
+
starConjunctions(chart: Chart, opts?: {
|
|
258
|
+
orb?: number;
|
|
259
|
+
maxMag?: number;
|
|
260
|
+
stars?: string[];
|
|
261
|
+
}): {
|
|
262
|
+
body: string;
|
|
263
|
+
star: string;
|
|
264
|
+
orb: number;
|
|
265
|
+
}[];
|
|
266
|
+
/**
|
|
267
|
+
* The seven Hermetic lots of a chart, each placed by sign and house. Sect is
|
|
268
|
+
* read from the Sun (above the horizon -> a day chart). Feed the result to
|
|
269
|
+
* {@link interpretationContext} as `lots` to project `lot` fact atoms.
|
|
270
|
+
*
|
|
271
|
+
* @param chart A chart from {@link Engine.chart} / {@link Engine.chartAt}; it
|
|
272
|
+
* must carry the seven classical planets.
|
|
273
|
+
* @returns One entry per lot with its longitude, sign, `signDeg`, and house,
|
|
274
|
+
* or an empty array if a required planet is absent.
|
|
275
|
+
*/
|
|
276
|
+
lots(chart: Chart): {
|
|
277
|
+
lot: string;
|
|
278
|
+
lon: number;
|
|
279
|
+
sign: string;
|
|
280
|
+
signDeg: number;
|
|
281
|
+
house: number;
|
|
282
|
+
}[];
|
|
245
283
|
private lonOnly;
|
|
246
284
|
/**
|
|
247
285
|
* Apparent geocentric ecliptic longitude of a body, in degrees `[0, 360)`,
|
package/dist/src/chart.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** astroengine chart -- public API: natal charts, aspects, retrogrades. */
|
|
2
2
|
import { DEG, mod, jdTT, julianDay, ChebSeries, planetApparent, sunApparent, moonApparentSeries, moonApparentPrecise, plutoApparent, chironApparent, meanNode, trueNodeSeries, trueNodePrecise, equatorial, ayanamsa, AYANAMSA_J2000, meanLilith, topocentricEcl, oscApogeePrecise, oscApogeeSeries, KeplerOrbit, trueObliquity, nutation, plutoHeliocentric, vsopHeliocentric, precessEcliptic, J2000, } from "./core.js";
|
|
3
3
|
import { starApparent } from "./stars.js";
|
|
4
|
+
import { hermeticLots, HERMETIC_LOTS } from "./lots.js";
|
|
4
5
|
import * as H from "./houses.js";
|
|
5
6
|
const TWO_PI = 2 * Math.PI;
|
|
6
7
|
export const BODIES = [
|
|
@@ -295,6 +296,68 @@ export class Engine {
|
|
|
295
296
|
starNames() {
|
|
296
297
|
return Object.keys(this.data.fixedStars?.stars ?? {}).sort();
|
|
297
298
|
}
|
|
299
|
+
/**
|
|
300
|
+
* Fixed-star conjunctions in a chart: each body within `orb` of a catalog
|
|
301
|
+
* star, in the chart's own zodiac. Feed the result to
|
|
302
|
+
* {@link interpretationContext} as `stars` to project `star` fact atoms (the
|
|
303
|
+
* Chart itself carries no star catalog).
|
|
304
|
+
*
|
|
305
|
+
* @param chart A chart from {@link Engine.chart} / {@link Engine.chartAt}.
|
|
306
|
+
* @param opts `orb` (default 1°); `stars` to restrict to named stars (then no
|
|
307
|
+
* magnitude filter); else `maxMag` keeps only stars brighter than it
|
|
308
|
+
* (default 2.5) so obscure catalog entries do not flood the result.
|
|
309
|
+
* @returns Conjunctions sorted by increasing orb.
|
|
310
|
+
*/
|
|
311
|
+
starConjunctions(chart, opts = {}) {
|
|
312
|
+
const catalog = this.data.fixedStars?.stars;
|
|
313
|
+
if (!catalog)
|
|
314
|
+
return [];
|
|
315
|
+
const orbLimit = opts.orb ?? 1.0;
|
|
316
|
+
const names = opts.stars ?? Object.keys(catalog);
|
|
317
|
+
const useMag = opts.stars === undefined;
|
|
318
|
+
const maxMag = opts.maxMag ?? 2.5;
|
|
319
|
+
const out = [];
|
|
320
|
+
for (const name of names) {
|
|
321
|
+
const s = catalog[name];
|
|
322
|
+
if (!s || (useMag && s.mag > maxMag))
|
|
323
|
+
continue;
|
|
324
|
+
const starLon = this.fixedStar(name, chart.jdUt, { zodiac: chart.zodiac }).lon;
|
|
325
|
+
for (const [body, p] of Object.entries(chart.bodies)) {
|
|
326
|
+
if (!p)
|
|
327
|
+
continue;
|
|
328
|
+
const sep = Math.abs(mod(p.lon - starLon + 180, 360) - 180);
|
|
329
|
+
if (sep <= orbLimit)
|
|
330
|
+
out.push({ body, star: name, orb: sep });
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
out.sort((a, b) => a.orb - b.orb);
|
|
334
|
+
return out;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* The seven Hermetic lots of a chart, each placed by sign and house. Sect is
|
|
338
|
+
* read from the Sun (above the horizon -> a day chart). Feed the result to
|
|
339
|
+
* {@link interpretationContext} as `lots` to project `lot` fact atoms.
|
|
340
|
+
*
|
|
341
|
+
* @param chart A chart from {@link Engine.chart} / {@link Engine.chartAt}; it
|
|
342
|
+
* must carry the seven classical planets.
|
|
343
|
+
* @returns One entry per lot with its longitude, sign, `signDeg`, and house,
|
|
344
|
+
* or an empty array if a required planet is absent.
|
|
345
|
+
*/
|
|
346
|
+
lots(chart) {
|
|
347
|
+
const b = chart.bodies;
|
|
348
|
+
const need = ["sun", "moon", "mercury", "venus", "mars", "jupiter", "saturn"];
|
|
349
|
+
if (need.some((k) => !b[k]))
|
|
350
|
+
return [];
|
|
351
|
+
const day = (b.sun.house >= 7); // Sun above the horizon (houses 7-12)
|
|
352
|
+
const h = hermeticLots(chart.angles.asc, day, b.sun.lon, b.moon.lon, b.mercury.lon, b.venus.lon, b.mars.lon, b.jupiter.lon, b.saturn.lon);
|
|
353
|
+
return HERMETIC_LOTS.map((lot) => {
|
|
354
|
+
const lon = mod(h[lot], 360);
|
|
355
|
+
return {
|
|
356
|
+
lot, lon, sign: SIGNS[Math.floor(lon / 30)], signDeg: mod(lon, 30),
|
|
357
|
+
house: houseIndex(lon, chart.cusps),
|
|
358
|
+
};
|
|
359
|
+
});
|
|
360
|
+
}
|
|
298
361
|
lonOnly(body, jdUt, mode, topo) {
|
|
299
362
|
const jde = jdTT(jdUt);
|
|
300
363
|
let [lon, lat, dist] = this.ecliptic(body, jde);
|
package/dist/src/interpret.d.ts
CHANGED
|
@@ -63,6 +63,17 @@ export declare function hasDispositor(filter?: {
|
|
|
63
63
|
export declare function hasReception(filter?: {
|
|
64
64
|
body?: string;
|
|
65
65
|
}): Selector;
|
|
66
|
+
/** Matches a fixed-star conjunction by the catalog star and/or the body on it. */
|
|
67
|
+
export declare function hasStar(filter?: {
|
|
68
|
+
body?: string;
|
|
69
|
+
star?: string;
|
|
70
|
+
}): Selector;
|
|
71
|
+
/** Matches a Hermetic lot by name, and/or its sign or house. */
|
|
72
|
+
export declare function hasLot(filter?: {
|
|
73
|
+
lot?: string;
|
|
74
|
+
sign?: string;
|
|
75
|
+
house?: number;
|
|
76
|
+
}): Selector;
|
|
66
77
|
/** Matches only when every selector matches; returns the union of their atoms. */
|
|
67
78
|
export declare function matchAll(...sels: Selector[]): Selector;
|
|
68
79
|
/** Matches when any selector matches; returns the atoms from those that did. */
|
package/dist/src/interpret.js
CHANGED
|
@@ -61,6 +61,19 @@ export function hasReception(filter = {}) {
|
|
|
61
61
|
return (ctx) => hit(ctx.atoms.filter((a) => a.kind === "reception"
|
|
62
62
|
&& (filter.body === undefined || a.bodies.includes(filter.body))));
|
|
63
63
|
}
|
|
64
|
+
/** Matches a fixed-star conjunction by the catalog star and/or the body on it. */
|
|
65
|
+
export function hasStar(filter = {}) {
|
|
66
|
+
return (ctx) => hit(ctx.atoms.filter((a) => a.kind === "star"
|
|
67
|
+
&& (filter.body === undefined || a.body === filter.body)
|
|
68
|
+
&& (filter.star === undefined || a.star === filter.star)));
|
|
69
|
+
}
|
|
70
|
+
/** Matches a Hermetic lot by name, and/or its sign or house. */
|
|
71
|
+
export function hasLot(filter = {}) {
|
|
72
|
+
return (ctx) => hit(ctx.atoms.filter((a) => a.kind === "lot"
|
|
73
|
+
&& (filter.lot === undefined || a.lot === filter.lot)
|
|
74
|
+
&& (filter.sign === undefined || a.sign === filter.sign)
|
|
75
|
+
&& (filter.house === undefined || a.house === filter.house)));
|
|
76
|
+
}
|
|
64
77
|
// ----------------------------------------------------------------- combinators
|
|
65
78
|
/** Matches only when every selector matches; returns the union of their atoms. */
|
|
66
79
|
export function matchAll(...sels) {
|
|
@@ -4,7 +4,7 @@ import { ChartPattern } from "./patterns.js";
|
|
|
4
4
|
import { ChartSignature } from "./signature.js";
|
|
5
5
|
import type { Realm, Certainty } from "./provenance.js";
|
|
6
6
|
/** Atom kinds in an {@link InterpretationContext}. */
|
|
7
|
-
export type FactKind = "placement" | "aspect" | "pattern" | "signature" | "angle" | "dispositor" | "reception";
|
|
7
|
+
export type FactKind = "placement" | "aspect" | "pattern" | "signature" | "angle" | "dispositor" | "reception" | "star" | "lot";
|
|
8
8
|
interface FactAtomBase {
|
|
9
9
|
/** Stable, content-addressable id, e.g. `"placement:mars"` or
|
|
10
10
|
* `"aspect:mars~saturn:square"`. Interpretations cite this. */
|
|
@@ -72,7 +72,24 @@ export interface ReceptionAtom extends FactAtomBase {
|
|
|
72
72
|
* else a sorted pair for a mixed reception (e.g. `"domicile-exaltation"`). */
|
|
73
73
|
by: string;
|
|
74
74
|
}
|
|
75
|
-
export
|
|
75
|
+
export interface StarAtom extends FactAtomBase {
|
|
76
|
+
kind: "star";
|
|
77
|
+
/** The body conjunct the fixed star. */
|
|
78
|
+
body: string;
|
|
79
|
+
/** Catalog star name (see {@link Engine.starNames}). */
|
|
80
|
+
star: string;
|
|
81
|
+
/** Orb from exact conjunction, degrees. */
|
|
82
|
+
orb: number;
|
|
83
|
+
}
|
|
84
|
+
export interface LotAtom extends FactAtomBase {
|
|
85
|
+
kind: "lot";
|
|
86
|
+
/** Hermetic lot name, e.g. `"fortune"` (see {@link HERMETIC_LOTS}). */
|
|
87
|
+
lot: string;
|
|
88
|
+
sign: string;
|
|
89
|
+
signDeg: number;
|
|
90
|
+
house: number;
|
|
91
|
+
}
|
|
92
|
+
export type FactAtom = PlacementAtom | AspectAtom | PatternAtom | SignatureAtom | AngleAtom | DispositorAtom | ReceptionAtom | StarAtom | LotAtom;
|
|
76
93
|
/** A chart as a flat, ranked list of {@link FactAtom}s. */
|
|
77
94
|
export interface InterpretationContext {
|
|
78
95
|
jdUt: number;
|
|
@@ -108,6 +125,10 @@ export interface SalienceWeights {
|
|
|
108
125
|
dispositor: number;
|
|
109
126
|
/** Added to a mutual reception. */
|
|
110
127
|
reception: number;
|
|
128
|
+
/** Added to a body's conjunction with a fixed star. */
|
|
129
|
+
star: number;
|
|
130
|
+
/** Added to a Hermetic lot (the Part of Fortune and its companions). */
|
|
131
|
+
lot: number;
|
|
111
132
|
}
|
|
112
133
|
export declare const DEFAULT_SALIENCE: SalienceWeights;
|
|
113
134
|
export interface ContextOptions {
|
|
@@ -122,6 +143,22 @@ export interface ContextOptions {
|
|
|
122
143
|
realm?: Realm;
|
|
123
144
|
certainty?: Certainty;
|
|
124
145
|
};
|
|
146
|
+
/** Fixed-star conjunctions to project as `star` atoms. The engine does not
|
|
147
|
+
* compute these from a bare {@link Chart} (the star catalog lives in the
|
|
148
|
+
* data pack), so a caller supplies them, e.g. from
|
|
149
|
+
* {@link Engine.starConjunctions}. */
|
|
150
|
+
stars?: {
|
|
151
|
+
body: string;
|
|
152
|
+
star: string;
|
|
153
|
+
orb: number;
|
|
154
|
+
}[];
|
|
155
|
+
/** Hermetic lots to project as `lot` atoms, e.g. from {@link Engine.lots}. */
|
|
156
|
+
lots?: {
|
|
157
|
+
lot: string;
|
|
158
|
+
sign: string;
|
|
159
|
+
signDeg: number;
|
|
160
|
+
house: number;
|
|
161
|
+
}[];
|
|
125
162
|
}
|
|
126
163
|
/**
|
|
127
164
|
* Project a {@link Chart} into a ranked list of {@link FactAtom}s -- the
|
|
@@ -53,6 +53,7 @@ const DIGNITY_RANK = { domicile: 3, exaltation: 2, triplicity: 1 };
|
|
|
53
53
|
export const DEFAULT_SALIENCE = {
|
|
54
54
|
base: 1, luminary: 1.5, angular: 1, chartRuler: 1,
|
|
55
55
|
dignity: 0.5, hardAspect: 1, pattern: 4, dispositor: 0.5, reception: 2,
|
|
56
|
+
star: 2, lot: 2,
|
|
56
57
|
};
|
|
57
58
|
/** How much to keep of a time-sensitive atom's salience at each certainty -- the
|
|
58
59
|
* Moon and the angles move fastest, so an uncertain instant trusts them least. */
|
|
@@ -62,7 +63,7 @@ const TIME_SENSITIVE_KEEP = {
|
|
|
62
63
|
/** Time-sensitive atoms: the angles (rotate ~15°/h) and anything about the Moon
|
|
63
64
|
* (~13°/day), the fastest-shifting facts under a time error. */
|
|
64
65
|
function timeSensitive(atom) {
|
|
65
|
-
return atom.kind === "angle" || atom.bodies.includes("moon");
|
|
66
|
+
return atom.kind === "angle" || atom.kind === "lot" || atom.bodies.includes("moon");
|
|
66
67
|
}
|
|
67
68
|
function title(body) {
|
|
68
69
|
return body.split("_").map((w) => w[0].toUpperCase() + w.slice(1)).join(" ");
|
|
@@ -234,6 +235,25 @@ export function interpretationContext(chart, opts = {}) {
|
|
|
234
235
|
angleAtom("mc", chart.angles.mc);
|
|
235
236
|
angleAtom("vertex", chart.angles.vertex);
|
|
236
237
|
angleAtom("eastPoint", chart.angles.eastPoint);
|
|
238
|
+
// Fixed-star conjunctions (caller-supplied; the catalog is not on the Chart).
|
|
239
|
+
for (const sc of opts.stars ?? []) {
|
|
240
|
+
let salience = w.base + w.star;
|
|
241
|
+
if (LUMINARIES.has(sc.body))
|
|
242
|
+
salience += w.luminary;
|
|
243
|
+
atoms.push({
|
|
244
|
+
id: `star:${sc.body}:${sc.star}`, kind: "star", bodies: [sc.body], salience,
|
|
245
|
+
body: sc.body, star: sc.star, orb: sc.orb,
|
|
246
|
+
text: `${title(sc.body)} conjunct ${sc.star} (orb ${sc.orb.toFixed(1)}°)`,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
// Hermetic lots (caller-supplied; computed from the chart's points + sect).
|
|
250
|
+
for (const l of opts.lots ?? []) {
|
|
251
|
+
atoms.push({
|
|
252
|
+
id: `lot:${l.lot}`, kind: "lot", bodies: [], salience: w.base + w.lot,
|
|
253
|
+
lot: l.lot, sign: l.sign, signDeg: l.signDeg, house: l.house,
|
|
254
|
+
text: `Lot of ${title(l.lot)} in ${l.sign}, house ${l.house}`,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
237
257
|
// An inexact instant trusts the fast-moving facts least.
|
|
238
258
|
const prov = opts.provenance;
|
|
239
259
|
if (prov?.certainty && prov.certainty !== "exact") {
|