@typescriptify/sweph 1.0.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/README.md +422 -0
- package/ephe/semo_18.se1 +0 -0
- package/ephe/sepl_18.se1 +0 -0
- package/originalCode/.eslintrc.json +124 -0
- package/originalCode/.gitattributes +2 -0
- package/originalCode/.github/FUNDING.yml +5 -0
- package/originalCode/.github/workflows/test.yml +35 -0
- package/originalCode/LICENSE +840 -0
- package/originalCode/README.md +91 -0
- package/originalCode/binding.gyp +41 -0
- package/originalCode/constants.js +366 -0
- package/originalCode/docs.gif +0 -0
- package/originalCode/index.d.ts +5115 -0
- package/originalCode/index.js +7 -0
- package/originalCode/index.mjs +109 -0
- package/originalCode/package.json +55 -0
- package/originalCode/src/functions/azalt.cpp +39 -0
- package/originalCode/src/functions/azalt_rev.cpp +35 -0
- package/originalCode/src/functions/calc.cpp +29 -0
- package/originalCode/src/functions/calc_pctr.cpp +31 -0
- package/originalCode/src/functions/calc_ut.cpp +29 -0
- package/originalCode/src/functions/close.cpp +6 -0
- package/originalCode/src/functions/cotrans.cpp +26 -0
- package/originalCode/src/functions/cotrans_sp.cpp +26 -0
- package/originalCode/src/functions/cs2degstr.cpp +19 -0
- package/originalCode/src/functions/cs2lonlatstr.cpp +23 -0
- package/originalCode/src/functions/cs2timestr.cpp +23 -0
- package/originalCode/src/functions/csnorm.cpp +15 -0
- package/originalCode/src/functions/csroundsec.cpp +15 -0
- package/originalCode/src/functions/d2l.cpp +15 -0
- package/originalCode/src/functions/date_conversion.cpp +30 -0
- package/originalCode/src/functions/day_of_week.cpp +15 -0
- package/originalCode/src/functions/degnorm.cpp +15 -0
- package/originalCode/src/functions/deltat.cpp +15 -0
- package/originalCode/src/functions/deltat_ex.cpp +24 -0
- package/originalCode/src/functions/difcs2n.cpp +19 -0
- package/originalCode/src/functions/difcsn.cpp +19 -0
- package/originalCode/src/functions/difdeg2n.cpp +19 -0
- package/originalCode/src/functions/difdegn.cpp +19 -0
- package/originalCode/src/functions/fixstar.cpp +32 -0
- package/originalCode/src/functions/fixstar2.cpp +32 -0
- package/originalCode/src/functions/fixstar2_mag.cpp +28 -0
- package/originalCode/src/functions/fixstar2_ut.cpp +32 -0
- package/originalCode/src/functions/fixstar_mag.cpp +28 -0
- package/originalCode/src/functions/fixstar_ut.cpp +32 -0
- package/originalCode/src/functions/gauquelin_sector.cpp +44 -0
- package/originalCode/src/functions/get_ayanamsa.cpp +15 -0
- package/originalCode/src/functions/get_ayanamsa_ex.cpp +27 -0
- package/originalCode/src/functions/get_ayanamsa_ex_ut.cpp +27 -0
- package/originalCode/src/functions/get_ayanamsa_name.cpp +19 -0
- package/originalCode/src/functions/get_ayanamsa_ut.cpp +15 -0
- package/originalCode/src/functions/get_current_file_data.cpp +28 -0
- package/originalCode/src/functions/get_library_path.cpp +8 -0
- package/originalCode/src/functions/get_orbital_elements.cpp +29 -0
- package/originalCode/src/functions/get_planet_name.cpp +19 -0
- package/originalCode/src/functions/get_tid_acc.cpp +7 -0
- package/originalCode/src/functions/heliacal_pheno_ut.cpp +52 -0
- package/originalCode/src/functions/heliacal_ut.cpp +52 -0
- package/originalCode/src/functions/helio_cross.cpp +33 -0
- package/originalCode/src/functions/helio_cross_ut.cpp +33 -0
- package/originalCode/src/functions/house_name.cpp +20 -0
- package/originalCode/src/functions/house_pos.cpp +36 -0
- package/originalCode/src/functions/houses.cpp +35 -0
- package/originalCode/src/functions/houses_armc.cpp +38 -0
- package/originalCode/src/functions/houses_armc_ex2.cpp +47 -0
- package/originalCode/src/functions/houses_ex.cpp +37 -0
- package/originalCode/src/functions/houses_ex2.cpp +46 -0
- package/originalCode/src/functions/jdet_to_utc.cpp +38 -0
- package/originalCode/src/functions/jdut1_to_utc.cpp +38 -0
- package/originalCode/src/functions/julday.cpp +25 -0
- package/originalCode/src/functions/lat_to_lmt.cpp +27 -0
- package/originalCode/src/functions/lmt_to_lat.cpp +27 -0
- package/originalCode/src/functions/lun_eclipse_how.cpp +34 -0
- package/originalCode/src/functions/lun_eclipse_when.cpp +31 -0
- package/originalCode/src/functions/lun_eclipse_when_loc.cpp +39 -0
- package/originalCode/src/functions/lun_occult_when_glob.cpp +35 -0
- package/originalCode/src/functions/lun_occult_when_loc.cpp +43 -0
- package/originalCode/src/functions/lun_occult_where.cpp +34 -0
- package/originalCode/src/functions/mooncross.cpp +26 -0
- package/originalCode/src/functions/mooncross_node.cpp +30 -0
- package/originalCode/src/functions/mooncross_node_ut.cpp +30 -0
- package/originalCode/src/functions/mooncross_ut.cpp +26 -0
- package/originalCode/src/functions/nod_aps.cpp +42 -0
- package/originalCode/src/functions/nod_aps_ut.cpp +42 -0
- package/originalCode/src/functions/orbit_max_min_true_distance.cpp +37 -0
- package/originalCode/src/functions/pheno.cpp +29 -0
- package/originalCode/src/functions/pheno_ut.cpp +29 -0
- package/originalCode/src/functions/radnorm.cpp +15 -0
- package/originalCode/src/functions/refrac.cpp +23 -0
- package/originalCode/src/functions/refrac_extended.cpp +32 -0
- package/originalCode/src/functions/revjul.cpp +33 -0
- package/originalCode/src/functions/rise_trans.cpp +44 -0
- package/originalCode/src/functions/rise_trans_true_hor.cpp +46 -0
- package/originalCode/src/functions/set_delta_t_userdef.cpp +14 -0
- package/originalCode/src/functions/set_ephe_path.cpp +14 -0
- package/originalCode/src/functions/set_jpl_file.cpp +14 -0
- package/originalCode/src/functions/set_sid_mode.cpp +20 -0
- package/originalCode/src/functions/set_tid_acc.cpp +14 -0
- package/originalCode/src/functions/set_topo.cpp +20 -0
- package/originalCode/src/functions/sidtime.cpp +15 -0
- package/originalCode/src/functions/sidtime0.cpp +21 -0
- package/originalCode/src/functions/sol_eclipse_how.cpp +34 -0
- package/originalCode/src/functions/sol_eclipse_when_glob.cpp +31 -0
- package/originalCode/src/functions/sol_eclipse_when_loc.cpp +39 -0
- package/originalCode/src/functions/sol_eclipse_where.cpp +30 -0
- package/originalCode/src/functions/solcross.cpp +26 -0
- package/originalCode/src/functions/solcross_ut.cpp +26 -0
- package/originalCode/src/functions/split_deg.cpp +35 -0
- package/originalCode/src/functions/time_equ.cpp +25 -0
- package/originalCode/src/functions/utc_time_zone.cpp +48 -0
- package/originalCode/src/functions/utc_to_jd.cpp +37 -0
- package/originalCode/src/functions/version.cpp +8 -0
- package/originalCode/src/functions/vis_limit_mag.cpp +50 -0
- package/originalCode/src/sweph.cpp +150 -0
- package/originalCode/src/sweph.h +119 -0
- package/originalCode/swisseph/swecl.c +6428 -0
- package/originalCode/swisseph/swedate.c +588 -0
- package/originalCode/swisseph/swedate.h +81 -0
- package/originalCode/swisseph/swehel.c +3511 -0
- package/originalCode/swisseph/swehouse.c +3143 -0
- package/originalCode/swisseph/swehouse.h +98 -0
- package/originalCode/swisseph/swejpl.c +958 -0
- package/originalCode/swisseph/swejpl.h +103 -0
- package/originalCode/swisseph/swemmoon.c +1930 -0
- package/originalCode/swisseph/swemplan.c +967 -0
- package/originalCode/swisseph/swemptab.h +10640 -0
- package/originalCode/swisseph/swenut2000a.h +2819 -0
- package/originalCode/swisseph/sweodef.h +326 -0
- package/originalCode/swisseph/sweph.c +8614 -0
- package/originalCode/swisseph/sweph.h +849 -0
- package/originalCode/swisseph/swephexp.h +1020 -0
- package/originalCode/swisseph/swephlib.c +4634 -0
- package/originalCode/swisseph/swephlib.h +189 -0
- package/package.json +28 -0
- package/scripts/gen-swemptab.js +177 -0
- package/scripts/gen-swenut2000a.js +106 -0
- package/src/SwissEph/README.md +268 -0
- package/src/SwissEph/UseCases/Ayanamsa.md +363 -0
- package/src/SwissEph/UseCases/AzimuthAltitude.md +408 -0
- package/src/SwissEph/UseCases/CoordinateSystems.md +337 -0
- package/src/SwissEph/UseCases/DateAndTime.md +368 -0
- package/src/SwissEph/UseCases/DeltaT.md +258 -0
- package/src/SwissEph/UseCases/EphemerisFiles.md +338 -0
- package/src/SwissEph/UseCases/FixedStars.md +300 -0
- package/src/SwissEph/UseCases/GauquelinSectors.md +304 -0
- package/src/SwissEph/UseCases/HeliacalEvents.md +396 -0
- package/src/SwissEph/UseCases/HelioCrossings.md +325 -0
- package/src/SwissEph/UseCases/HousePosition.md +254 -0
- package/src/SwissEph/UseCases/HouseSystems.md +279 -0
- package/src/SwissEph/UseCases/LunarEclipse.md +326 -0
- package/src/SwissEph/UseCases/MeridianTransit.md +279 -0
- package/src/SwissEph/UseCases/MoonCrossings.md +373 -0
- package/src/SwissEph/UseCases/NodesAndApsides.md +307 -0
- package/src/SwissEph/UseCases/Occultation.md +352 -0
- package/src/SwissEph/UseCases/OrbitalElements.md +469 -0
- package/src/SwissEph/UseCases/Phenomena.md +328 -0
- package/src/SwissEph/UseCases/PlanetPositions.md +366 -0
- package/src/SwissEph/UseCases/Planetocentric.md +278 -0
- package/src/SwissEph/UseCases/Refraction.md +314 -0
- package/src/SwissEph/UseCases/RiseAndSet.md +433 -0
- package/src/SwissEph/UseCases/SiderealTime.md +302 -0
- package/src/SwissEph/UseCases/SolarEclipse.md +379 -0
- package/src/SwissEph/UseCases/SunCrossings.md +275 -0
- package/src/SwissEph/UseCases/TopocentricCorrection.md +335 -0
- package/src/SwissEph/errors.ts +10 -0
- package/src/SwissEph/index.ts +823 -0
- package/src/SwissEph/types.ts +291 -0
- package/src/constants.ts +762 -0
- package/src/file-reader.ts +147 -0
- package/src/index.ts +10 -0
- package/src/swecl.ts +4526 -0
- package/src/swedate.ts +376 -0
- package/src/swehel.ts +1939 -0
- package/src/swehouse.ts +2167 -0
- package/src/swejpl.ts +470 -0
- package/src/swemmoon.ts +1318 -0
- package/src/swemplan.ts +585 -0
- package/src/swemptab.ts +4448 -0
- package/src/swenut2000a.ts +2763 -0
- package/src/sweph.ts +3993 -0
- package/src/swephlib.ts +2720 -0
- package/src/types.ts +490 -0
- package/tests/c-style/ayanamsa.test.ts +63 -0
- package/tests/c-style/config.test.ts +96 -0
- package/tests/c-style/crossings.test.ts +81 -0
- package/tests/c-style/date-time.test.ts +114 -0
- package/tests/c-style/eclipses.test.ts +84 -0
- package/tests/c-style/fixed-stars.test.ts +66 -0
- package/tests/c-style/heliacal.test.ts +34 -0
- package/tests/c-style/houses.test.ts +135 -0
- package/tests/c-style/math-utils.test.ts +160 -0
- package/tests/c-style/orbital.test.ts +78 -0
- package/tests/c-style/phenomena.test.ts +42 -0
- package/tests/c-style/planetocentric.test.ts +26 -0
- package/tests/c-style/planets.test.ts +117 -0
- package/tests/c-style/rise-set.test.ts +71 -0
- package/tests/helpers.ts +21 -0
- package/tests/modern/ayanamsa.test.ts +47 -0
- package/tests/modern/calc.test.ts +113 -0
- package/tests/modern/config.test.ts +46 -0
- package/tests/modern/crossings.test.ts +45 -0
- package/tests/modern/eclipses.test.ts +81 -0
- package/tests/modern/errors.test.ts +71 -0
- package/tests/modern/heliacal.test.ts +30 -0
- package/tests/modern/houses.test.ts +87 -0
- package/tests/modern/orbital.test.ts +79 -0
- package/tests/modern/phenomena.test.ts +41 -0
- package/tests/modern/rise-set.test.ts +60 -0
- package/tests/modern/statics.test.ts +99 -0
- package/tests/modern/utilities.test.ts +70 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
# Heliacal Events
|
|
2
|
+
|
|
3
|
+
A **heliacal rising** is the first time a star or planet becomes visible on the eastern horizon just before sunrise, after a period of being hidden in the Sun's glare. A **heliacal setting** is the last time it is visible on the western horizon just after sunset, before it disappears into the Sun's light for weeks or months.
|
|
4
|
+
|
|
5
|
+
This may sound like a niche concept, but heliacal events were among the most important astronomical observations in the ancient world:
|
|
6
|
+
|
|
7
|
+
- **Egypt**: The heliacal rising of **Sirius** (called "Sothis" by the Egyptians) coincided with the annual flooding of the Nile and marked the beginning of the Egyptian calendar year. This observation was so important that it anchored their entire calendar system for over 3,000 years.
|
|
8
|
+
- **Babylon**: Babylonian astronomers systematically recorded heliacal risings and settings of planets and stars to make omen-based predictions. Their detailed clay tablet records form the oldest continuous astronomical dataset in human history.
|
|
9
|
+
- **Islam**: The first sighting of the thin **lunar crescent** after a New Moon determines the start of each month in the Islamic calendar. This is a heliacal event -- the Moon must be far enough from the Sun to be visible in the evening twilight.
|
|
10
|
+
- **Greece**: The heliacal rising of the Pleiades cluster marked the beginning of the sailing and farming seasons.
|
|
11
|
+
|
|
12
|
+
The Swiss Ephemeris implements a sophisticated atmospheric model (based on Bradley Schaefer's work) that accounts for sky brightness, atmospheric extinction, the observer's visual acuity, and local conditions like temperature, pressure, and humidity to predict when a celestial object first becomes visible.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Quick Example
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { SwissEph } from '../index';
|
|
20
|
+
import { SE_HELIACAL_RISING } from '../../constants';
|
|
21
|
+
|
|
22
|
+
const swe = new SwissEph();
|
|
23
|
+
|
|
24
|
+
// Find when Venus next rises heliacally after January 1, 2025
|
|
25
|
+
// (first visible in the morning sky before sunrise)
|
|
26
|
+
const jd = SwissEph.julianDay(2025, 1, 1, 0);
|
|
27
|
+
const geo = { longitude: -73.98, latitude: 40.75, altitude: 10 }; // New York
|
|
28
|
+
|
|
29
|
+
const result = swe.heliacalEvent(jd, geo, 'Venus', SE_HELIACAL_RISING);
|
|
30
|
+
|
|
31
|
+
const date = SwissEph.fromJulianDay(result.startVisible);
|
|
32
|
+
console.log(`Venus heliacal rising: ${date.year}-${String(date.month).padStart(2,'0')}-${String(date.day).padStart(2,'0')}`);
|
|
33
|
+
console.log(`Start visible JD: ${result.startVisible.toFixed(6)}`);
|
|
34
|
+
console.log(`Best visible JD: ${result.bestVisible.toFixed(6)}`);
|
|
35
|
+
console.log(`End visible JD: ${result.endVisible.toFixed(6)}`);
|
|
36
|
+
|
|
37
|
+
swe.close();
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Detailed Examples
|
|
43
|
+
|
|
44
|
+
### Sirius heliacal rising from Cairo (the Egyptian observation)
|
|
45
|
+
|
|
46
|
+
The ancient Egyptians observed Sirius rising heliacally from the latitude of Memphis/Cairo (about 30 degrees N). In the modern era, due to precession, the date has shifted from mid-July to early August.
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import { SwissEph } from '../index';
|
|
50
|
+
import { SE_HELIACAL_RISING } from '../../constants';
|
|
51
|
+
|
|
52
|
+
const swe = new SwissEph();
|
|
53
|
+
|
|
54
|
+
// Cairo, Egypt
|
|
55
|
+
const cairo = { longitude: 31.24, latitude: 30.04, altitude: 75 };
|
|
56
|
+
|
|
57
|
+
// Search for the heliacal rising of Sirius in 2025
|
|
58
|
+
const jd = SwissEph.julianDay(2025, 6, 1, 0);
|
|
59
|
+
const result = swe.heliacalEvent(jd, cairo, 'Sirius', SE_HELIACAL_RISING);
|
|
60
|
+
|
|
61
|
+
const date = SwissEph.fromJulianDay(result.startVisible);
|
|
62
|
+
console.log(`Sirius heliacal rising from Cairo in ${date.year}:`);
|
|
63
|
+
console.log(` Date: ${date.year}-${String(date.month).padStart(2,'0')}-${String(date.day).padStart(2,'0')}`);
|
|
64
|
+
|
|
65
|
+
// In ancient Egypt (~3000 BC), this occurred around mid-July
|
|
66
|
+
// and coincided with the Nile flood. Let's check:
|
|
67
|
+
const jdAncient = SwissEph.julianDay(-3000, 5, 1, 0);
|
|
68
|
+
const ancient = swe.heliacalEvent(jdAncient, cairo, 'Sirius', SE_HELIACAL_RISING);
|
|
69
|
+
const ancientDate = SwissEph.fromJulianDay(ancient.startVisible);
|
|
70
|
+
console.log(`\nSirius heliacal rising from Cairo in 3001 BC:`);
|
|
71
|
+
console.log(` Date: ${ancientDate.month}/${ancientDate.day} (Julian calendar)`);
|
|
72
|
+
|
|
73
|
+
swe.close();
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Venus as morning and evening star
|
|
77
|
+
|
|
78
|
+
Venus alternates between being a "morning star" (visible before sunrise) and an "evening star" (visible after sunset). The heliacal events mark these transitions.
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { SwissEph } from '../index';
|
|
82
|
+
import {
|
|
83
|
+
SE_HELIACAL_RISING, SE_HELIACAL_SETTING,
|
|
84
|
+
SE_EVENING_FIRST, SE_MORNING_LAST,
|
|
85
|
+
} from '../../constants';
|
|
86
|
+
|
|
87
|
+
const swe = new SwissEph();
|
|
88
|
+
const geo = { longitude: -118.24, latitude: 34.05, altitude: 90 }; // Los Angeles
|
|
89
|
+
|
|
90
|
+
let jd = SwissEph.julianDay(2025, 1, 1, 0);
|
|
91
|
+
|
|
92
|
+
const fmt = (jd: number) => {
|
|
93
|
+
const d = SwissEph.fromJulianDay(jd);
|
|
94
|
+
return `${d.year}-${String(d.month).padStart(2,'0')}-${String(d.day).padStart(2,'0')}`;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// SE_HELIACAL_RISING = SE_MORNING_FIRST: first visible in the morning
|
|
98
|
+
const morningFirst = swe.heliacalEvent(jd, geo, 'Venus', SE_HELIACAL_RISING);
|
|
99
|
+
console.log(`Venus morning first (heliacal rising): ${fmt(morningFirst.startVisible)}`);
|
|
100
|
+
|
|
101
|
+
// SE_MORNING_LAST: last visible in the morning before moving behind the Sun
|
|
102
|
+
const morningLast = swe.heliacalEvent(jd, geo, 'Venus', SE_MORNING_LAST);
|
|
103
|
+
console.log(`Venus morning last: ${fmt(morningLast.startVisible)}`);
|
|
104
|
+
|
|
105
|
+
// SE_EVENING_FIRST: first visible in the evening after superior conjunction
|
|
106
|
+
const eveningFirst = swe.heliacalEvent(jd, geo, 'Venus', SE_EVENING_FIRST);
|
|
107
|
+
console.log(`Venus evening first: ${fmt(eveningFirst.startVisible)}`);
|
|
108
|
+
|
|
109
|
+
// SE_HELIACAL_SETTING = SE_EVENING_LAST: last visible in the evening
|
|
110
|
+
const eveningLast = swe.heliacalEvent(jd, geo, 'Venus', SE_HELIACAL_SETTING);
|
|
111
|
+
console.log(`Venus evening last (heliacal setting): ${fmt(eveningLast.startVisible)}`);
|
|
112
|
+
|
|
113
|
+
swe.close();
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Lunar crescent visibility (Islamic calendar)
|
|
117
|
+
|
|
118
|
+
The Islamic calendar months begin with the first sighting of the thin crescent Moon in the evening sky after a New Moon. This is a heliacal event for the Moon.
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
import { SwissEph } from '../index';
|
|
122
|
+
import { SE_EVENING_FIRST } from '../../constants';
|
|
123
|
+
|
|
124
|
+
const swe = new SwissEph();
|
|
125
|
+
|
|
126
|
+
// Mecca, Saudi Arabia
|
|
127
|
+
const mecca = { longitude: 39.83, latitude: 21.42, altitude: 277 };
|
|
128
|
+
|
|
129
|
+
// Find the first crescent visibility after each New Moon in 2025
|
|
130
|
+
let jd = SwissEph.julianDay(2025, 1, 1, 0);
|
|
131
|
+
|
|
132
|
+
const fmt = (jd: number) => {
|
|
133
|
+
const d = SwissEph.fromJulianDay(jd);
|
|
134
|
+
return `${d.year}-${String(d.month).padStart(2,'0')}-${String(d.day).padStart(2,'0')}`;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
console.log('Lunar crescent first visibility from Mecca, 2025:');
|
|
138
|
+
for (let i = 0; i < 12; i++) {
|
|
139
|
+
const result = swe.heliacalEvent(jd, mecca, 'Moon', SE_EVENING_FIRST);
|
|
140
|
+
console.log(` ${fmt(result.startVisible)}`);
|
|
141
|
+
// Advance past this lunation to find the next one
|
|
142
|
+
jd = result.startVisible + 25;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
swe.close();
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Heliacal events for multiple planets
|
|
149
|
+
|
|
150
|
+
Find when each visible planet next rises heliacally from a given location.
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import { SwissEph } from '../index';
|
|
154
|
+
import { SE_HELIACAL_RISING } from '../../constants';
|
|
155
|
+
|
|
156
|
+
const swe = new SwissEph();
|
|
157
|
+
const geo = { longitude: 12.50, latitude: 41.89, altitude: 20 }; // Rome
|
|
158
|
+
const jd = SwissEph.julianDay(2025, 1, 1, 0);
|
|
159
|
+
|
|
160
|
+
const objects = ['Mercury', 'Venus', 'Mars', 'Jupiter', 'Saturn'];
|
|
161
|
+
|
|
162
|
+
const fmt = (jd: number) => {
|
|
163
|
+
const d = SwissEph.fromJulianDay(jd);
|
|
164
|
+
return `${d.year}-${String(d.month).padStart(2,'0')}-${String(d.day).padStart(2,'0')}`;
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
console.log('Next heliacal risings from Rome after 2025-01-01:');
|
|
168
|
+
for (const obj of objects) {
|
|
169
|
+
const result = swe.heliacalEvent(jd, geo, obj, SE_HELIACAL_RISING);
|
|
170
|
+
console.log(` ${obj.padEnd(9)} ${fmt(result.startVisible)}`);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
swe.close();
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Customizing atmospheric and observer conditions
|
|
177
|
+
|
|
178
|
+
The visibility calculation depends on atmospheric conditions and the observer's eyesight. You can customize these parameters.
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
import { SwissEph } from '../index';
|
|
182
|
+
import { SE_HELIACAL_RISING } from '../../constants';
|
|
183
|
+
|
|
184
|
+
const swe = new SwissEph();
|
|
185
|
+
const geo = { longitude: -6.26, latitude: 36.70, altitude: 5 }; // Cadiz, Spain
|
|
186
|
+
|
|
187
|
+
const jd = SwissEph.julianDay(2025, 6, 1, 0);
|
|
188
|
+
|
|
189
|
+
// Default conditions (average observer, standard atmosphere)
|
|
190
|
+
const normal = swe.heliacalEvent(jd, geo, 'Mercury', SE_HELIACAL_RISING);
|
|
191
|
+
|
|
192
|
+
// Young observer with excellent eyesight, dry atmosphere, high altitude
|
|
193
|
+
const optimal = swe.heliacalEvent(jd, geo, 'Mercury', SE_HELIACAL_RISING, {
|
|
194
|
+
pressure: 900, // lower pressure (high altitude or low pressure system)
|
|
195
|
+
temperature: 25, // warm (less atmospheric scattering)
|
|
196
|
+
humidity: 20, // dry air (less extinction)
|
|
197
|
+
extinction: 0.20, // excellent atmospheric transparency
|
|
198
|
+
observerAge: 20, // young eyes
|
|
199
|
+
acuity: 1.5, // above-average visual acuity (Snellen ratio)
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// Elderly observer, humid and hazy conditions
|
|
203
|
+
const difficult = swe.heliacalEvent(jd, geo, 'Mercury', SE_HELIACAL_RISING, {
|
|
204
|
+
pressure: 1020,
|
|
205
|
+
temperature: 10,
|
|
206
|
+
humidity: 80,
|
|
207
|
+
extinction: 0.40, // poor transparency (haze, pollution)
|
|
208
|
+
observerAge: 65,
|
|
209
|
+
acuity: 0.7, // below-average eyesight
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
const fmt = (jd: number) => {
|
|
213
|
+
const d = SwissEph.fromJulianDay(jd);
|
|
214
|
+
return `${d.year}-${String(d.month).padStart(2,'0')}-${String(d.day).padStart(2,'0')}`;
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
console.log(`Mercury heliacal rising from Cadiz:`);
|
|
218
|
+
console.log(` Normal conditions: ${fmt(normal.startVisible)}`);
|
|
219
|
+
console.log(` Optimal conditions: ${fmt(optimal.startVisible)}`);
|
|
220
|
+
console.log(` Difficult conditions: ${fmt(difficult.startVisible)}`);
|
|
221
|
+
// Better conditions -> the planet becomes visible earlier
|
|
222
|
+
|
|
223
|
+
swe.close();
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Detailed heliacal phenomena
|
|
227
|
+
|
|
228
|
+
The `heliacalPhenomena()` method returns detailed visibility data: the altitude and azimuth of the object, Sun, and Moon, the elongation, and the arc of vision.
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
import { SwissEph } from '../index';
|
|
232
|
+
import { SE_HELIACAL_RISING } from '../../constants';
|
|
233
|
+
|
|
234
|
+
const swe = new SwissEph();
|
|
235
|
+
const geo = { longitude: 31.24, latitude: 30.04, altitude: 75 }; // Cairo
|
|
236
|
+
|
|
237
|
+
// First find when Sirius rises heliacally
|
|
238
|
+
const jd = SwissEph.julianDay(2025, 6, 1, 0);
|
|
239
|
+
const event = swe.heliacalEvent(jd, geo, 'Sirius', SE_HELIACAL_RISING);
|
|
240
|
+
|
|
241
|
+
// Now get the detailed phenomena at that time
|
|
242
|
+
const pheno = swe.heliacalPhenomena(event.startVisible, geo, 'Sirius', SE_HELIACAL_RISING);
|
|
243
|
+
|
|
244
|
+
console.log('Sirius heliacal rising -- detailed phenomena:');
|
|
245
|
+
console.log(` Object altitude: ${pheno.altObj.toFixed(2)} deg`);
|
|
246
|
+
console.log(` Object azimuth: ${pheno.azObj.toFixed(2)} deg`);
|
|
247
|
+
console.log(` Sun altitude: ${pheno.altSun.toFixed(2)} deg`);
|
|
248
|
+
console.log(` Sun azimuth: ${pheno.azSun.toFixed(2)} deg`);
|
|
249
|
+
console.log(` Elongation: ${pheno.elong.toFixed(2)} deg`);
|
|
250
|
+
console.log(` Best elongation: ${pheno.elongBest.toFixed(2)} deg`);
|
|
251
|
+
console.log(` Arc of vision: ${pheno.eDistArcVis.toFixed(2)} deg`);
|
|
252
|
+
|
|
253
|
+
swe.close();
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Visual limiting magnitude
|
|
257
|
+
|
|
258
|
+
The `visualLimitMagnitude()` method tells you whether a given object is theoretically visible at a specific time and place, based on the sky brightness and the observer's eye.
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
import { SwissEph } from '../index';
|
|
262
|
+
|
|
263
|
+
const swe = new SwissEph();
|
|
264
|
+
const geo = { longitude: -118.24, latitude: 34.05, altitude: 90 }; // Los Angeles
|
|
265
|
+
|
|
266
|
+
// Check Mercury's visibility at a specific time (during morning twilight)
|
|
267
|
+
const jd = SwissEph.julianDay(2025, 3, 15, 5.5); // ~5:30 UT (about 9:30 PM local? -- adjust as needed)
|
|
268
|
+
|
|
269
|
+
const result = swe.visualLimitMagnitude(jd, geo, 'Mercury');
|
|
270
|
+
|
|
271
|
+
console.log('Mercury visibility check:');
|
|
272
|
+
console.log(` Limiting magnitude: ${result.limitingMagnitude.toFixed(2)}`);
|
|
273
|
+
console.log(` Object altitude: ${result.altObject.toFixed(2)} deg`);
|
|
274
|
+
console.log(` Object azimuth: ${result.azObject.toFixed(2)} deg`);
|
|
275
|
+
console.log(` Sun altitude: ${result.altSun.toFixed(2)} deg`);
|
|
276
|
+
console.log(` Moon elongation: ${result.elongMoon.toFixed(2)} deg`);
|
|
277
|
+
|
|
278
|
+
// If the limiting magnitude is brighter (lower number) than Mercury's actual
|
|
279
|
+
// magnitude, then Mercury is visible. Mercury's magnitude ranges from about
|
|
280
|
+
// -2.5 to +5.5 depending on its phase.
|
|
281
|
+
|
|
282
|
+
swe.close();
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## Deep Explanation
|
|
288
|
+
|
|
289
|
+
### What determines visibility?
|
|
290
|
+
|
|
291
|
+
A celestial object becomes visible when its light is bright enough to be detected against the background sky. At twilight, the sky is not fully dark -- the Sun, even below the horizon, still illuminates the atmosphere. An object must be bright enough to stand out against this twilight glow. The key factors are:
|
|
292
|
+
|
|
293
|
+
1. **The object's brightness** (apparent magnitude). Brighter objects (lower magnitude numbers) are easier to see. Venus (mag ~-4) is visible even in fairly bright twilight; Mercury (mag ~0 to +2) requires darker skies.
|
|
294
|
+
|
|
295
|
+
2. **The Sun's depression below the horizon**. The deeper the Sun is below the horizon, the darker the sky. For most objects, the Sun needs to be at least 6 to 12 degrees below the horizon.
|
|
296
|
+
|
|
297
|
+
3. **The angular separation between the object and the Sun** (elongation). Objects very close to the Sun are lost in the Sun's glare regardless of sky brightness.
|
|
298
|
+
|
|
299
|
+
4. **Atmospheric extinction**. The atmosphere absorbs and scatters light. Near the horizon, the light path through the atmosphere is much longer, so objects appear dimmer. Humidity, pollution, and altitude all affect extinction.
|
|
300
|
+
|
|
301
|
+
5. **The observer's visual acuity**. Human eyes vary in sensitivity. Age, in particular, reduces the eye's ability to detect faint objects.
|
|
302
|
+
|
|
303
|
+
### The Schaefer atmospheric model
|
|
304
|
+
|
|
305
|
+
The Swiss Ephemeris uses Bradley Schaefer's model (refined in his 2000 publication) to compute sky brightness and visual limiting magnitude. The model accounts for:
|
|
306
|
+
|
|
307
|
+
- **Rayleigh scattering**: scattering by air molecules (makes the sky blue)
|
|
308
|
+
- **Mie scattering**: scattering by aerosols and dust particles
|
|
309
|
+
- **Ozone absorption**: absorption by the ozone layer
|
|
310
|
+
- **Airglow**: the atmosphere's own faint luminescence
|
|
311
|
+
- **Moon brightness**: when the Moon is above the horizon, it brightens the sky significantly
|
|
312
|
+
- **Twilight brightness**: the gradient of sky brightness during twilight
|
|
313
|
+
|
|
314
|
+
The model takes as input the atmospheric pressure (mbar), temperature (Celsius), relative humidity (%), and an atmospheric extinction coefficient (magnitudes per air mass).
|
|
315
|
+
|
|
316
|
+
### The visibility arc and arcus visionis
|
|
317
|
+
|
|
318
|
+
The **arcus visionis** (literally "arc of vision") is the minimum angular distance between the Sun (below the horizon) and a celestial object (above the horizon) that is required for the object to be visible. Different objects have different arcus visionis values based on their brightness.
|
|
319
|
+
|
|
320
|
+
Historically, Ptolemy and later Arab astronomers compiled tables of arcus visionis values for each planet. Typical values:
|
|
321
|
+
|
|
322
|
+
| Object | Arcus Visionis (approx) |
|
|
323
|
+
|--------|------------------------|
|
|
324
|
+
| Venus | 5-6 deg |
|
|
325
|
+
| Jupiter | 8-10 deg |
|
|
326
|
+
| Mercury | 10-13 deg |
|
|
327
|
+
| Saturn | 11-13 deg |
|
|
328
|
+
| Mars | 12-15 deg |
|
|
329
|
+
| Sirius | 7-8 deg |
|
|
330
|
+
|
|
331
|
+
The Swiss Ephemeris computes these dynamically based on the actual atmospheric model rather than using fixed lookup tables.
|
|
332
|
+
|
|
333
|
+
### Event type constants
|
|
334
|
+
|
|
335
|
+
| Constant | Value | Description |
|
|
336
|
+
|----------|-------|-------------|
|
|
337
|
+
| `SE_HELIACAL_RISING` | 1 | **Morning first**: the object appears for the first time in the morning sky before sunrise. Same as `SE_MORNING_FIRST`. |
|
|
338
|
+
| `SE_HELIACAL_SETTING` | 2 | **Evening last**: the object is seen for the last time in the evening sky after sunset, before disappearing into the Sun's glare. Same as `SE_EVENING_LAST`. |
|
|
339
|
+
| `SE_MORNING_FIRST` | 1 | Same as `SE_HELIACAL_RISING`. |
|
|
340
|
+
| `SE_EVENING_LAST` | 2 | Same as `SE_HELIACAL_SETTING`. |
|
|
341
|
+
| `SE_EVENING_FIRST` | 3 | The object appears for the first time in the **evening** sky. This happens after a planet's superior conjunction with the Sun (when it was behind the Sun). |
|
|
342
|
+
| `SE_MORNING_LAST` | 4 | The object is seen for the last time in the **morning** sky, before it approaches the Sun and disappears. |
|
|
343
|
+
|
|
344
|
+
For inner planets (Mercury and Venus), the full visibility cycle is:
|
|
345
|
+
1. **Evening first** (SE_EVENING_FIRST = 3): appears in the evening after superior conjunction
|
|
346
|
+
2. **Evening last** (SE_EVENING_LAST = 2): disappears from the evening as it approaches inferior conjunction
|
|
347
|
+
3. **Morning first** (SE_MORNING_FIRST = 1): reappears in the morning after inferior conjunction
|
|
348
|
+
4. **Morning last** (SE_MORNING_LAST = 4): disappears from the morning as it approaches superior conjunction
|
|
349
|
+
|
|
350
|
+
For outer planets (Mars through Saturn) and stars, the cycle is simpler:
|
|
351
|
+
1. **Evening last** (SE_EVENING_LAST = 2): disappears from the evening as the Sun approaches
|
|
352
|
+
2. **Morning first** (SE_MORNING_FIRST = 1): reappears in the morning on the other side of the Sun
|
|
353
|
+
|
|
354
|
+
### The object parameter
|
|
355
|
+
|
|
356
|
+
The `object` parameter is a string. For planets, use the planet name: `'Mercury'`, `'Venus'`, `'Mars'`, `'Jupiter'`, `'Saturn'`. For the Moon, use `'Moon'`. For fixed stars, use the star name as it appears in the Swiss Ephemeris star catalog, such as `'Sirius'`, `'Aldebaran'`, `'Spica'`, `'Antares'`, `'Regulus'`, `'Fomalhaut'`, etc.
|
|
357
|
+
|
|
358
|
+
### The return object
|
|
359
|
+
|
|
360
|
+
The `heliacalEvent()` method returns three Julian Day numbers:
|
|
361
|
+
|
|
362
|
+
| Field | Description |
|
|
363
|
+
|-------|-------------|
|
|
364
|
+
| `startVisible` | The moment when the object first becomes visible (the beginning of the visibility window on that day). |
|
|
365
|
+
| `bestVisible` | The moment of best visibility during that twilight (the sky is dark enough and the object is high enough for optimal contrast). |
|
|
366
|
+
| `endVisible` | The moment when the object ceases to be visible (either the sky becomes too bright from the approaching sunrise, or the object sets). |
|
|
367
|
+
|
|
368
|
+
These three times describe a single morning or evening visibility window. For a heliacal rising, `startVisible` is the earliest moment the object can be detected, `bestVisible` is when it is easiest to see, and `endVisible` is when sunrise makes it invisible again.
|
|
369
|
+
|
|
370
|
+
### The options object
|
|
371
|
+
|
|
372
|
+
| Option | Default | Description |
|
|
373
|
+
|--------|---------|-------------|
|
|
374
|
+
| `pressure` | 1013.25 | Atmospheric pressure in millibars. Lower pressure (higher altitude) means less extinction. |
|
|
375
|
+
| `temperature` | 15 | Temperature in degrees Celsius. Affects atmospheric density and refraction. |
|
|
376
|
+
| `humidity` | 40 | Relative humidity in percent. Higher humidity means more scattering and extinction. |
|
|
377
|
+
| `extinction` | 0.25 | Atmospheric extinction coefficient in magnitudes per air mass. 0.20 = excellent transparency (clear mountain air). 0.25 = average. 0.30-0.40 = hazy or polluted. |
|
|
378
|
+
| `observerAge` | 36 | Observer's age in years. Older observers have reduced scotopic (night) vision due to changes in the eye's lens and pupil. |
|
|
379
|
+
| `acuity` | 1.0 | Snellen visual acuity ratio. 1.0 = normal (20/20). 1.5 = excellent. 0.5 = poor. Affects the ability to detect faint objects. |
|
|
380
|
+
| `flags` | 0 | Additional computation flags. |
|
|
381
|
+
|
|
382
|
+
### Historical significance
|
|
383
|
+
|
|
384
|
+
**Egypt and the Sothic cycle**: The heliacal rising of Sirius was so central to Egyptian culture that they developed the concept of the **Sothic cycle** -- a period of 1,461 Egyptian civil years (each of 365 days) after which the heliacal rising of Sirius and the start of the civil year coincide again. This happened because the Egyptian civil year lacked a leap day, causing it to drift against the solar year at a rate of one day every four years. The Sothic cycle provides one of the most important tools for dating events in ancient Egyptian history.
|
|
385
|
+
|
|
386
|
+
**Babylon and the "fixed star" observations**: Babylonian astronomers kept meticulous records of heliacal risings and settings on cuneiform tablets, some dating back to 1600 BC. These records, known as MUL.APIN, cataloged the dates of heliacal risings for dozens of stars and constellations. They were used for agricultural timing, religious festivals, and omens.
|
|
387
|
+
|
|
388
|
+
**Islam and the crescent Moon**: The Islamic calendar is fundamentally based on heliacal events. Each month begins with the first sighting of the new crescent Moon (hilal) in the evening sky. Because visibility depends on local atmospheric conditions and the observer's location, the start of the month can differ by a day between different regions. Modern computational methods, including the Swiss Ephemeris implementation, are used by many Islamic authorities to predict crescent visibility.
|
|
389
|
+
|
|
390
|
+
### Practical tips
|
|
391
|
+
|
|
392
|
+
- **Sirius** is the easiest star to test with because it is the brightest star in the sky (magnitude -1.46). Its heliacal rising is well-documented historically and produces consistent results.
|
|
393
|
+
- **Mercury** is the most challenging planet because it never gets far from the Sun and varies greatly in brightness. Its heliacal events are very sensitive to atmospheric conditions.
|
|
394
|
+
- For the **lunar crescent**, `SE_EVENING_FIRST` (3) is the relevant event type. The crescent must be at least 7-10 degrees from the Sun and the Moon must be at least a few degrees above the horizon.
|
|
395
|
+
- The `heliacalPhenomena()` method is useful for understanding **why** an object is or is not visible at a given time -- it gives you the exact altitudes, azimuths, and elongations.
|
|
396
|
+
- Results are sensitive to the observer's geographic position. Even a few degrees of latitude can shift a heliacal date by a day or more.
|