@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.
Files changed (211) hide show
  1. package/README.md +422 -0
  2. package/ephe/semo_18.se1 +0 -0
  3. package/ephe/sepl_18.se1 +0 -0
  4. package/originalCode/.eslintrc.json +124 -0
  5. package/originalCode/.gitattributes +2 -0
  6. package/originalCode/.github/FUNDING.yml +5 -0
  7. package/originalCode/.github/workflows/test.yml +35 -0
  8. package/originalCode/LICENSE +840 -0
  9. package/originalCode/README.md +91 -0
  10. package/originalCode/binding.gyp +41 -0
  11. package/originalCode/constants.js +366 -0
  12. package/originalCode/docs.gif +0 -0
  13. package/originalCode/index.d.ts +5115 -0
  14. package/originalCode/index.js +7 -0
  15. package/originalCode/index.mjs +109 -0
  16. package/originalCode/package.json +55 -0
  17. package/originalCode/src/functions/azalt.cpp +39 -0
  18. package/originalCode/src/functions/azalt_rev.cpp +35 -0
  19. package/originalCode/src/functions/calc.cpp +29 -0
  20. package/originalCode/src/functions/calc_pctr.cpp +31 -0
  21. package/originalCode/src/functions/calc_ut.cpp +29 -0
  22. package/originalCode/src/functions/close.cpp +6 -0
  23. package/originalCode/src/functions/cotrans.cpp +26 -0
  24. package/originalCode/src/functions/cotrans_sp.cpp +26 -0
  25. package/originalCode/src/functions/cs2degstr.cpp +19 -0
  26. package/originalCode/src/functions/cs2lonlatstr.cpp +23 -0
  27. package/originalCode/src/functions/cs2timestr.cpp +23 -0
  28. package/originalCode/src/functions/csnorm.cpp +15 -0
  29. package/originalCode/src/functions/csroundsec.cpp +15 -0
  30. package/originalCode/src/functions/d2l.cpp +15 -0
  31. package/originalCode/src/functions/date_conversion.cpp +30 -0
  32. package/originalCode/src/functions/day_of_week.cpp +15 -0
  33. package/originalCode/src/functions/degnorm.cpp +15 -0
  34. package/originalCode/src/functions/deltat.cpp +15 -0
  35. package/originalCode/src/functions/deltat_ex.cpp +24 -0
  36. package/originalCode/src/functions/difcs2n.cpp +19 -0
  37. package/originalCode/src/functions/difcsn.cpp +19 -0
  38. package/originalCode/src/functions/difdeg2n.cpp +19 -0
  39. package/originalCode/src/functions/difdegn.cpp +19 -0
  40. package/originalCode/src/functions/fixstar.cpp +32 -0
  41. package/originalCode/src/functions/fixstar2.cpp +32 -0
  42. package/originalCode/src/functions/fixstar2_mag.cpp +28 -0
  43. package/originalCode/src/functions/fixstar2_ut.cpp +32 -0
  44. package/originalCode/src/functions/fixstar_mag.cpp +28 -0
  45. package/originalCode/src/functions/fixstar_ut.cpp +32 -0
  46. package/originalCode/src/functions/gauquelin_sector.cpp +44 -0
  47. package/originalCode/src/functions/get_ayanamsa.cpp +15 -0
  48. package/originalCode/src/functions/get_ayanamsa_ex.cpp +27 -0
  49. package/originalCode/src/functions/get_ayanamsa_ex_ut.cpp +27 -0
  50. package/originalCode/src/functions/get_ayanamsa_name.cpp +19 -0
  51. package/originalCode/src/functions/get_ayanamsa_ut.cpp +15 -0
  52. package/originalCode/src/functions/get_current_file_data.cpp +28 -0
  53. package/originalCode/src/functions/get_library_path.cpp +8 -0
  54. package/originalCode/src/functions/get_orbital_elements.cpp +29 -0
  55. package/originalCode/src/functions/get_planet_name.cpp +19 -0
  56. package/originalCode/src/functions/get_tid_acc.cpp +7 -0
  57. package/originalCode/src/functions/heliacal_pheno_ut.cpp +52 -0
  58. package/originalCode/src/functions/heliacal_ut.cpp +52 -0
  59. package/originalCode/src/functions/helio_cross.cpp +33 -0
  60. package/originalCode/src/functions/helio_cross_ut.cpp +33 -0
  61. package/originalCode/src/functions/house_name.cpp +20 -0
  62. package/originalCode/src/functions/house_pos.cpp +36 -0
  63. package/originalCode/src/functions/houses.cpp +35 -0
  64. package/originalCode/src/functions/houses_armc.cpp +38 -0
  65. package/originalCode/src/functions/houses_armc_ex2.cpp +47 -0
  66. package/originalCode/src/functions/houses_ex.cpp +37 -0
  67. package/originalCode/src/functions/houses_ex2.cpp +46 -0
  68. package/originalCode/src/functions/jdet_to_utc.cpp +38 -0
  69. package/originalCode/src/functions/jdut1_to_utc.cpp +38 -0
  70. package/originalCode/src/functions/julday.cpp +25 -0
  71. package/originalCode/src/functions/lat_to_lmt.cpp +27 -0
  72. package/originalCode/src/functions/lmt_to_lat.cpp +27 -0
  73. package/originalCode/src/functions/lun_eclipse_how.cpp +34 -0
  74. package/originalCode/src/functions/lun_eclipse_when.cpp +31 -0
  75. package/originalCode/src/functions/lun_eclipse_when_loc.cpp +39 -0
  76. package/originalCode/src/functions/lun_occult_when_glob.cpp +35 -0
  77. package/originalCode/src/functions/lun_occult_when_loc.cpp +43 -0
  78. package/originalCode/src/functions/lun_occult_where.cpp +34 -0
  79. package/originalCode/src/functions/mooncross.cpp +26 -0
  80. package/originalCode/src/functions/mooncross_node.cpp +30 -0
  81. package/originalCode/src/functions/mooncross_node_ut.cpp +30 -0
  82. package/originalCode/src/functions/mooncross_ut.cpp +26 -0
  83. package/originalCode/src/functions/nod_aps.cpp +42 -0
  84. package/originalCode/src/functions/nod_aps_ut.cpp +42 -0
  85. package/originalCode/src/functions/orbit_max_min_true_distance.cpp +37 -0
  86. package/originalCode/src/functions/pheno.cpp +29 -0
  87. package/originalCode/src/functions/pheno_ut.cpp +29 -0
  88. package/originalCode/src/functions/radnorm.cpp +15 -0
  89. package/originalCode/src/functions/refrac.cpp +23 -0
  90. package/originalCode/src/functions/refrac_extended.cpp +32 -0
  91. package/originalCode/src/functions/revjul.cpp +33 -0
  92. package/originalCode/src/functions/rise_trans.cpp +44 -0
  93. package/originalCode/src/functions/rise_trans_true_hor.cpp +46 -0
  94. package/originalCode/src/functions/set_delta_t_userdef.cpp +14 -0
  95. package/originalCode/src/functions/set_ephe_path.cpp +14 -0
  96. package/originalCode/src/functions/set_jpl_file.cpp +14 -0
  97. package/originalCode/src/functions/set_sid_mode.cpp +20 -0
  98. package/originalCode/src/functions/set_tid_acc.cpp +14 -0
  99. package/originalCode/src/functions/set_topo.cpp +20 -0
  100. package/originalCode/src/functions/sidtime.cpp +15 -0
  101. package/originalCode/src/functions/sidtime0.cpp +21 -0
  102. package/originalCode/src/functions/sol_eclipse_how.cpp +34 -0
  103. package/originalCode/src/functions/sol_eclipse_when_glob.cpp +31 -0
  104. package/originalCode/src/functions/sol_eclipse_when_loc.cpp +39 -0
  105. package/originalCode/src/functions/sol_eclipse_where.cpp +30 -0
  106. package/originalCode/src/functions/solcross.cpp +26 -0
  107. package/originalCode/src/functions/solcross_ut.cpp +26 -0
  108. package/originalCode/src/functions/split_deg.cpp +35 -0
  109. package/originalCode/src/functions/time_equ.cpp +25 -0
  110. package/originalCode/src/functions/utc_time_zone.cpp +48 -0
  111. package/originalCode/src/functions/utc_to_jd.cpp +37 -0
  112. package/originalCode/src/functions/version.cpp +8 -0
  113. package/originalCode/src/functions/vis_limit_mag.cpp +50 -0
  114. package/originalCode/src/sweph.cpp +150 -0
  115. package/originalCode/src/sweph.h +119 -0
  116. package/originalCode/swisseph/swecl.c +6428 -0
  117. package/originalCode/swisseph/swedate.c +588 -0
  118. package/originalCode/swisseph/swedate.h +81 -0
  119. package/originalCode/swisseph/swehel.c +3511 -0
  120. package/originalCode/swisseph/swehouse.c +3143 -0
  121. package/originalCode/swisseph/swehouse.h +98 -0
  122. package/originalCode/swisseph/swejpl.c +958 -0
  123. package/originalCode/swisseph/swejpl.h +103 -0
  124. package/originalCode/swisseph/swemmoon.c +1930 -0
  125. package/originalCode/swisseph/swemplan.c +967 -0
  126. package/originalCode/swisseph/swemptab.h +10640 -0
  127. package/originalCode/swisseph/swenut2000a.h +2819 -0
  128. package/originalCode/swisseph/sweodef.h +326 -0
  129. package/originalCode/swisseph/sweph.c +8614 -0
  130. package/originalCode/swisseph/sweph.h +849 -0
  131. package/originalCode/swisseph/swephexp.h +1020 -0
  132. package/originalCode/swisseph/swephlib.c +4634 -0
  133. package/originalCode/swisseph/swephlib.h +189 -0
  134. package/package.json +28 -0
  135. package/scripts/gen-swemptab.js +177 -0
  136. package/scripts/gen-swenut2000a.js +106 -0
  137. package/src/SwissEph/README.md +268 -0
  138. package/src/SwissEph/UseCases/Ayanamsa.md +363 -0
  139. package/src/SwissEph/UseCases/AzimuthAltitude.md +408 -0
  140. package/src/SwissEph/UseCases/CoordinateSystems.md +337 -0
  141. package/src/SwissEph/UseCases/DateAndTime.md +368 -0
  142. package/src/SwissEph/UseCases/DeltaT.md +258 -0
  143. package/src/SwissEph/UseCases/EphemerisFiles.md +338 -0
  144. package/src/SwissEph/UseCases/FixedStars.md +300 -0
  145. package/src/SwissEph/UseCases/GauquelinSectors.md +304 -0
  146. package/src/SwissEph/UseCases/HeliacalEvents.md +396 -0
  147. package/src/SwissEph/UseCases/HelioCrossings.md +325 -0
  148. package/src/SwissEph/UseCases/HousePosition.md +254 -0
  149. package/src/SwissEph/UseCases/HouseSystems.md +279 -0
  150. package/src/SwissEph/UseCases/LunarEclipse.md +326 -0
  151. package/src/SwissEph/UseCases/MeridianTransit.md +279 -0
  152. package/src/SwissEph/UseCases/MoonCrossings.md +373 -0
  153. package/src/SwissEph/UseCases/NodesAndApsides.md +307 -0
  154. package/src/SwissEph/UseCases/Occultation.md +352 -0
  155. package/src/SwissEph/UseCases/OrbitalElements.md +469 -0
  156. package/src/SwissEph/UseCases/Phenomena.md +328 -0
  157. package/src/SwissEph/UseCases/PlanetPositions.md +366 -0
  158. package/src/SwissEph/UseCases/Planetocentric.md +278 -0
  159. package/src/SwissEph/UseCases/Refraction.md +314 -0
  160. package/src/SwissEph/UseCases/RiseAndSet.md +433 -0
  161. package/src/SwissEph/UseCases/SiderealTime.md +302 -0
  162. package/src/SwissEph/UseCases/SolarEclipse.md +379 -0
  163. package/src/SwissEph/UseCases/SunCrossings.md +275 -0
  164. package/src/SwissEph/UseCases/TopocentricCorrection.md +335 -0
  165. package/src/SwissEph/errors.ts +10 -0
  166. package/src/SwissEph/index.ts +823 -0
  167. package/src/SwissEph/types.ts +291 -0
  168. package/src/constants.ts +762 -0
  169. package/src/file-reader.ts +147 -0
  170. package/src/index.ts +10 -0
  171. package/src/swecl.ts +4526 -0
  172. package/src/swedate.ts +376 -0
  173. package/src/swehel.ts +1939 -0
  174. package/src/swehouse.ts +2167 -0
  175. package/src/swejpl.ts +470 -0
  176. package/src/swemmoon.ts +1318 -0
  177. package/src/swemplan.ts +585 -0
  178. package/src/swemptab.ts +4448 -0
  179. package/src/swenut2000a.ts +2763 -0
  180. package/src/sweph.ts +3993 -0
  181. package/src/swephlib.ts +2720 -0
  182. package/src/types.ts +490 -0
  183. package/tests/c-style/ayanamsa.test.ts +63 -0
  184. package/tests/c-style/config.test.ts +96 -0
  185. package/tests/c-style/crossings.test.ts +81 -0
  186. package/tests/c-style/date-time.test.ts +114 -0
  187. package/tests/c-style/eclipses.test.ts +84 -0
  188. package/tests/c-style/fixed-stars.test.ts +66 -0
  189. package/tests/c-style/heliacal.test.ts +34 -0
  190. package/tests/c-style/houses.test.ts +135 -0
  191. package/tests/c-style/math-utils.test.ts +160 -0
  192. package/tests/c-style/orbital.test.ts +78 -0
  193. package/tests/c-style/phenomena.test.ts +42 -0
  194. package/tests/c-style/planetocentric.test.ts +26 -0
  195. package/tests/c-style/planets.test.ts +117 -0
  196. package/tests/c-style/rise-set.test.ts +71 -0
  197. package/tests/helpers.ts +21 -0
  198. package/tests/modern/ayanamsa.test.ts +47 -0
  199. package/tests/modern/calc.test.ts +113 -0
  200. package/tests/modern/config.test.ts +46 -0
  201. package/tests/modern/crossings.test.ts +45 -0
  202. package/tests/modern/eclipses.test.ts +81 -0
  203. package/tests/modern/errors.test.ts +71 -0
  204. package/tests/modern/heliacal.test.ts +30 -0
  205. package/tests/modern/houses.test.ts +87 -0
  206. package/tests/modern/orbital.test.ts +79 -0
  207. package/tests/modern/phenomena.test.ts +41 -0
  208. package/tests/modern/rise-set.test.ts +60 -0
  209. package/tests/modern/statics.test.ts +99 -0
  210. package/tests/modern/utilities.test.ts +70 -0
  211. package/tsconfig.json +20 -0
@@ -0,0 +1,338 @@
1
+ # Ephemeris Files
2
+
3
+ The Swiss Ephemeris supports three different ephemeris modes, each offering a different tradeoff between convenience, precision, and resource requirements:
4
+
5
+ - **Moshier** (default): A purely analytical ephemeris built into the library. No external files needed. Accuracy is about 1 arcsecond for planets and a few arcseconds for the Moon over the period 3000 BCE to 3000 CE. This is the easiest to use and is sufficient for most astrological applications.
6
+
7
+ - **Swiss Ephemeris (SWIEPH)**: Compressed data derived from NASA's JPL ephemerides, stored in `.se1` binary files. Accuracy is about 0.001 arcsecond (1 milliarcsecond) -- roughly 1000 times more precise than Moshier. Covers about 10,800 years (5400 BCE to 5400 CE). File sizes are modest (a few hundred KB each).
8
+
9
+ - **JPL Development Ephemeris**: NASA's own ephemeris files (DE441, DE440, etc.), the gold standard used for space mission navigation. Accuracy is limited only by the observations used to construct it. File sizes are large (hundreds of MB to several GB). Covers up to 26,000 years (DE441).
10
+
11
+ For most applications, the built-in Moshier ephemeris is perfectly adequate. You only need external files if you require milliarcsecond precision or have specific research needs.
12
+
13
+ ---
14
+
15
+ ## Quick Example
16
+
17
+ ```typescript
18
+ import { SwissEph } from '../index';
19
+ import { SE_MARS } from '../../constants';
20
+
21
+ // Default: Moshier analytical ephemeris (no files needed)
22
+ const swe = new SwissEph();
23
+ const jd = SwissEph.julianDay(2024, 6, 21, 12);
24
+ const mars = swe.calc(jd, SE_MARS);
25
+ console.log(`Mars (Moshier): ${mars.longitude.toFixed(6)} deg`);
26
+ swe.close();
27
+ ```
28
+
29
+ ---
30
+
31
+ ## Detailed Examples
32
+
33
+ ### Using the Moshier ephemeris (default)
34
+
35
+ No setup required. Just create a SwissEph instance and start calculating:
36
+
37
+ ```typescript
38
+ import { SwissEph } from '../index';
39
+ import { SE_SUN, SE_MOON, SE_MARS } from '../../constants';
40
+
41
+ const swe = new SwissEph(); // Default: Moshier
42
+
43
+ const jd = SwissEph.julianDay(2024, 1, 1, 12);
44
+ console.log(`Sun: ${swe.calc(jd, SE_SUN).longitude.toFixed(6)} deg`);
45
+ console.log(`Moon: ${swe.calc(jd, SE_MOON).longitude.toFixed(6)} deg`);
46
+ console.log(`Mars: ${swe.calc(jd, SE_MARS).longitude.toFixed(6)} deg`);
47
+
48
+ swe.close();
49
+ ```
50
+
51
+ ### Loading Swiss Ephemeris (SE1) files
52
+
53
+ SE1 files contain compressed Chebyshev polynomial coefficients for very high precision. You need separate files for planets, the Moon, and asteroids:
54
+
55
+ | File pattern | Contents |
56
+ |-----------------|-----------------------|
57
+ | `sepl_*.se1` | Major planets |
58
+ | `semo_*.se1` | The Moon |
59
+ | `seas_*.se1` | Asteroids |
60
+
61
+ ```typescript
62
+ import { SwissEph } from '../index';
63
+ import { SE_SUN, SE_MOON, SE_MARS } from '../../constants';
64
+
65
+ // Create instance configured for Swiss Ephemeris mode
66
+ const swe = new SwissEph({ ephemeris: 'swisseph' });
67
+
68
+ // Load the SE1 files (you must provide the ArrayBuffer data)
69
+ // In Node.js:
70
+ import { readFileSync } from 'fs';
71
+ const planetData = readFileSync('ephe/sepl_18.se1');
72
+ const moonData = readFileSync('ephe/semo_18.se1');
73
+
74
+ swe.loadEphemerisFile(planetData.buffer, 'sepl_18.se1');
75
+ swe.loadEphemerisFile(moonData.buffer, 'semo_18.se1');
76
+
77
+ // In a browser, you would fetch the files:
78
+ // const resp = await fetch('/ephe/sepl_18.se1');
79
+ // const planetData = await resp.arrayBuffer();
80
+ // swe.loadEphemerisFile(planetData, 'sepl_18.se1');
81
+
82
+ // Now calculate with milliarcsecond precision
83
+ const jd = SwissEph.julianDay(2024, 1, 1, 12);
84
+ console.log(`Sun (SWIEPH): ${swe.calc(jd, SE_SUN).longitude.toFixed(6)} deg`);
85
+ console.log(`Moon (SWIEPH): ${swe.calc(jd, SE_MOON).longitude.toFixed(6)} deg`);
86
+ console.log(`Mars (SWIEPH): ${swe.calc(jd, SE_MARS).longitude.toFixed(6)} deg`);
87
+
88
+ swe.close();
89
+ ```
90
+
91
+ ### Loading JPL ephemeris files
92
+
93
+ JPL files (like DE441) provide the ultimate in precision:
94
+
95
+ ```typescript
96
+ import { SwissEph } from '../index';
97
+ import { SE_SUN, SE_MOON, SE_MARS } from '../../constants';
98
+ import { readFileSync } from 'fs';
99
+
100
+ const swe = new SwissEph({ ephemeris: 'jpl' });
101
+
102
+ // Load the JPL file
103
+ const jplData = readFileSync('ephe/de441.eph');
104
+ swe.loadJplFile(jplData.buffer, 'de441.eph');
105
+
106
+ const jd = SwissEph.julianDay(2024, 1, 1, 12);
107
+ console.log(`Sun (JPL): ${swe.calc(jd, SE_SUN).longitude.toFixed(6)} deg`);
108
+ console.log(`Moon (JPL): ${swe.calc(jd, SE_MOON).longitude.toFixed(6)} deg`);
109
+ console.log(`Mars (JPL): ${swe.calc(jd, SE_MARS).longitude.toFixed(6)} deg`);
110
+
111
+ swe.close();
112
+ ```
113
+
114
+ ### Fallback behavior
115
+
116
+ If you request a higher-precision ephemeris but the necessary file is not loaded, the engine silently falls back:
117
+
118
+ - JPL mode falls back to SWIEPH (if SE1 files loaded), then to Moshier
119
+ - SWIEPH mode falls back to Moshier
120
+
121
+ You can detect the actual ephemeris used by checking the returned `flags`:
122
+
123
+ ```typescript
124
+ import { SwissEph } from '../index';
125
+ import { SE_MARS, SEFLG_MOSEPH, SEFLG_SWIEPH, SEFLG_JPLEPH } from '../../constants';
126
+
127
+ // Request SWIEPH but do not load any files
128
+ const swe = new SwissEph({ ephemeris: 'swisseph' });
129
+
130
+ const jd = SwissEph.julianDay(2024, 1, 1, 12);
131
+ const mars = swe.calc(jd, SE_MARS);
132
+
133
+ // Check which ephemeris was actually used
134
+ if (mars.flags & SEFLG_JPLEPH) {
135
+ console.log('Used: JPL');
136
+ } else if (mars.flags & SEFLG_SWIEPH) {
137
+ console.log('Used: Swiss Ephemeris (SE1 files)');
138
+ } else {
139
+ console.log('Used: Moshier (fallback)');
140
+ }
141
+ // Output: "Used: Moshier (fallback)" because no SE1 files were loaded
142
+
143
+ swe.close();
144
+ ```
145
+
146
+ ### Comparing precision between ephemeris modes
147
+
148
+ ```typescript
149
+ import { SwissEph } from '../index';
150
+ import { SE_MARS } from '../../constants';
151
+ import { readFileSync } from 'fs';
152
+
153
+ const jd = SwissEph.julianDay(2024, 1, 1, 12);
154
+
155
+ // Moshier
156
+ const mosh = new SwissEph();
157
+ const marsMosh = mosh.calc(jd, SE_MARS);
158
+
159
+ // Swiss Ephemeris
160
+ const swi = new SwissEph({ ephemeris: 'swisseph' });
161
+ const planetData = readFileSync('ephe/sepl_18.se1');
162
+ swi.loadEphemerisFile(planetData.buffer, 'sepl_18.se1');
163
+ const marsSwi = swi.calc(jd, SE_MARS);
164
+
165
+ // Compare
166
+ const diffArcsec = Math.abs(marsMosh.longitude - marsSwi.longitude) * 3600;
167
+ console.log(`Mars (Moshier): ${marsMosh.longitude.toFixed(8)} deg`);
168
+ console.log(`Mars (SWIEPH): ${marsSwi.longitude.toFixed(8)} deg`);
169
+ console.log(`Difference: ${diffArcsec.toFixed(4)} arcseconds`);
170
+
171
+ mosh.close();
172
+ swi.close();
173
+ ```
174
+
175
+ ### Setting the ephemeris file path
176
+
177
+ For systems that read files from disk (not applicable to in-memory ArrayBuffer loading, but useful if the underlying engine supports path-based loading):
178
+
179
+ ```typescript
180
+ import { SwissEph } from '../index';
181
+
182
+ const swe = new SwissEph({ ephemeris: 'swisseph' });
183
+
184
+ // Tell the engine where to look for ephemeris files
185
+ swe.setEphePath('/path/to/ephemeris/files');
186
+
187
+ swe.close();
188
+ ```
189
+
190
+ ---
191
+
192
+ ## Deep Explanation
193
+
194
+ ### The JPL Development Ephemeris series
195
+
196
+ NASA's Jet Propulsion Laboratory (JPL) has been producing numerical ephemerides since the 1960s. Each version (called a "Development Ephemeris" or DE) incorporates improved observations and models. The major versions:
197
+
198
+ | Version | Year | Time span | Notes |
199
+ |---------|------|------------------------|---------------------------------------------------------|
200
+ | DE200 | 1981 | 1600-2169 | First widely used modern ephemeris. Based on optical and radar observations. |
201
+ | DE405 | 1998 | 1600-2200 | Major improvement incorporating VLBI data and LLR (Lunar Laser Ranging). Used as reference for many years. |
202
+ | DE406 | 1998 | -3000 to +3000 | Long-span version of DE405 with slightly reduced precision. |
203
+ | DE421 | 2008 | 1900-2050 | Updated with additional LLR data and Mars spacecraft tracking. |
204
+ | DE430 | 2014 | 1550-2650 | Incorporated MESSENGER data at Mercury and improved Mars data. |
205
+ | DE431 | 2014 | -13200 to +17191 | Long-span version of DE430 for historical research. |
206
+ | DE440 | 2020 | 1550-2650 | Latest short-span ephemeris with Juno data at Jupiter. |
207
+ | DE441 | 2020 | -13200 to +17191 | Long-span version of DE440. Current standard. |
208
+
209
+ Short-span versions (DE440) are slightly more accurate than their long-span counterparts (DE441) because they can include the effect of the Moon's liquid core-mantle interaction, which dissipates over long timescales but matters for the highest precision over short intervals. The difference is sub-milliarcsecond and irrelevant for nearly all applications.
210
+
211
+ ### What the files contain
212
+
213
+ All three ephemeris formats store the same fundamental data: positions (and sometimes velocities) of solar system bodies as functions of time. The difference is in representation and precision:
214
+
215
+ **JPL files** store **Chebyshev polynomial coefficients** in fixed-length records. Each record covers a specific time interval (typically 32 days) and contains sets of polynomial coefficients for each body. To get a position at any time, the engine evaluates the Chebyshev polynomial for the relevant interval. The polynomials are fitted to the output of JPL's numerical integration to the full precision of the integration. Velocities are obtained by differentiating the polynomial.
216
+
217
+ Bodies covered: Sun, Moon, Mercury through Pluto, lunar librations, and (in newer versions) the Earth-Moon nutation angles.
218
+
219
+ **SE1 files** use the same Chebyshev polynomial approach but with compressed coefficients. The Swiss Ephemeris developers took the JPL data, verified it, and repackaged it with data compression (reducing precision from ~10 significant digits to ~8, still yielding milliarcsecond accuracy) and split it into separate files for planets, Moon, and asteroids. This dramatically reduces file sizes.
220
+
221
+ **Moshier** uses completely different analytical expressions -- series expansions in powers of time fitted to the JPL ephemeris. No Chebyshev polynomials, no external data. The series terms are hard-coded in the library. For the planets, Moshier's implementation is based on Steve Moshier's adaptation of Jean Meeus's algorithms (themselves based on the VSOP87 planetary theory for planets and ELP 2000-85 for the Moon). The limited number of terms in the series expansion is what limits accuracy to about 1 arcsecond.
222
+
223
+ ### File sizes
224
+
225
+ | Ephemeris | Files needed | Total size (approx) |
226
+ |---------------|------------------------------------|-----------------------|
227
+ | Moshier | None | 0 (built-in) |
228
+ | SE1 (planets) | `sepl_18.se1` | ~500 KB |
229
+ | SE1 (Moon) | `semo_18.se1` | ~1.2 MB |
230
+ | SE1 (asteroids) | `seas_18.se1` | varies |
231
+ | DE405 | `de405.eph` (or segments) | ~55 MB |
232
+ | DE406 | `de406.eph` | ~190 MB |
233
+ | DE441 | `de441.eph` | ~2.6 GB |
234
+ | DE440 | `de440.eph` | ~115 MB |
235
+
236
+ ### Accuracy comparison
237
+
238
+ | Ephemeris | Planet accuracy (modern dates) | Moon accuracy | Time range |
239
+ |-----------|-------------------------------|----------------|---------------------|
240
+ | Moshier | ~1 arcsecond | ~3 arcseconds | ~3000 BCE-3000 CE |
241
+ | SE1 | ~0.001 arcsecond | ~0.001 arcsec | ~5400 BCE-5400 CE |
242
+ | DE441 | ~0.0001 arcsecond (inner planets) | ~0.001 arcsec | 13200 BCE-17191 CE |
243
+
244
+ To put 1 arcsecond in perspective: at the distance of the Moon, 1 arcsecond corresponds to about 1.9 km on the lunar surface. At the distance of Mars at closest approach, it corresponds to about 530 km. For astrology, where positions are meaningful to about 1 arcminute (60 arcseconds), Moshier's 1-arcsecond accuracy is more than adequate.
245
+
246
+ ### Tidal acceleration and DE versions
247
+
248
+ Different JPL ephemeris versions use different values for the tidal acceleration of the Moon (which affects long-term lunar motion). The Swiss Ephemeris automatically adjusts its internal tidal acceleration parameter to match the loaded ephemeris:
249
+
250
+ | DE version | Tidal acceleration (arcsec/cy^2) |
251
+ |----------------|----------------------------------|
252
+ | DE200 | -23.8946 |
253
+ | DE405/DE406 | -25.826 |
254
+ | DE421 | -25.85 |
255
+ | DE430/DE431 | -25.82 |
256
+ | DE440/DE441 | -25.936 |
257
+
258
+ This parameter affects Delta-T calculations and long-term lunar motion predictions. When a JPL or SE1 file is loaded, the appropriate value is set automatically.
259
+
260
+ ### When to use which ephemeris
261
+
262
+ **Moshier (default)** -- Use for:
263
+ - General astrological software
264
+ - Mobile/web applications where you want to minimize download size
265
+ - Quick calculations where sub-arcsecond precision is not needed
266
+ - Dates within about 3000 BCE to 3000 CE
267
+
268
+ **Swiss Ephemeris (SE1 files)** -- Use for:
269
+ - Professional astrological software requiring milliarcsecond precision
270
+ - Applications where you need both high precision and moderate file sizes
271
+ - Date ranges up to about 5400 BCE to 5400 CE
272
+ - Research requiring highly accurate historical positions
273
+
274
+ **JPL (DE441 etc.)** -- Use for:
275
+ - Scientific research
276
+ - Verifying calculations against the "gold standard"
277
+ - Space mission planning and navigation
278
+ - Very long time spans (DE441 covers 26,000 years)
279
+ - When you need the absolute highest precision available
280
+
281
+ ### Loading files in different environments
282
+
283
+ **Node.js:**
284
+ ```typescript
285
+ import { readFileSync } from 'fs';
286
+
287
+ const data = readFileSync('ephe/sepl_18.se1');
288
+ swe.loadEphemerisFile(data.buffer, 'sepl_18.se1');
289
+ ```
290
+
291
+ **Browser (fetch):**
292
+ ```typescript
293
+ const response = await fetch('/ephe/sepl_18.se1');
294
+ const data = await response.arrayBuffer();
295
+ swe.loadEphemerisFile(data, 'sepl_18.se1');
296
+ ```
297
+
298
+ **Bundled (import):**
299
+ If your build tool supports importing binary files as ArrayBuffers, you can bundle the SE1 files directly into your application. This is convenient for small files like `sepl_18.se1` (~500 KB).
300
+
301
+ ### SE1 file naming convention
302
+
303
+ SE1 files follow a naming pattern where the number indicates the century range:
304
+
305
+ | File | Century coverage |
306
+ |-------------|-----------------------------------|
307
+ | `sepl_18.se1` | Planets, covering centuries 18-27 (1800-2700 CE) |
308
+ | `semo_18.se1` | Moon, covering centuries 18-27 |
309
+ | `sepl_06.se1` | Planets, covering centuries 6-17 (600-1800 CE) |
310
+
311
+ For most modern-date applications, the `_18` files are sufficient. For historical work you may need additional files covering earlier centuries.
312
+
313
+ ### Multiple files can be loaded
314
+
315
+ You can load multiple SE1 files simultaneously. The engine will use whichever file covers the requested date:
316
+
317
+ ```typescript
318
+ import { readFileSync } from 'fs';
319
+
320
+ // Load planet files for two century ranges
321
+ swe.loadEphemerisFile(readFileSync('ephe/sepl_06.se1').buffer, 'sepl_06.se1');
322
+ swe.loadEphemerisFile(readFileSync('ephe/sepl_18.se1').buffer, 'sepl_18.se1');
323
+
324
+ // This works for dates in both ranges
325
+ const jd1 = SwissEph.julianDay(1200, 6, 15, 12); // Uses sepl_06
326
+ const jd2 = SwissEph.julianDay(2024, 6, 15, 12); // Uses sepl_18
327
+ ```
328
+
329
+ ### JPL file auto-detection
330
+
331
+ When loading a JPL file, the library automatically detects the DE version, time span, and endianness. You do not need to specify which DE version you are loading -- the library reads this from the file header.
332
+
333
+ ```typescript
334
+ swe.loadJplFile(data, 'de441.eph');
335
+ // Internally, the library reads the header and configures itself for DE441
336
+ ```
337
+
338
+ If the file name is not provided, the library attempts to use a default name. It is best practice to always provide the name.
@@ -0,0 +1,300 @@
1
+ # Fixed Stars
2
+
3
+ Fixed stars are the distant suns that form the constellations. Despite the name "fixed," they are not truly stationary -- they have proper motion (their own movement through space), and their apparent positions shift slowly due to precession of the equinoxes. However, compared to planets, their motion is extremely slow (typically fractions of an arcsecond per year), so for most practical purposes they appear fixed against the celestial background.
4
+
5
+ In astrology, certain bright stars have been considered significant for thousands of years. Conjunctions of planets with prominent stars like Regulus, Spica, Aldebaran, Antares, and Sirius are interpreted in natal and mundane astrology. In Vedic astrology, specific stars define the sidereal zodiac (the nakshatras).
6
+
7
+ The Swiss Ephemeris includes a catalog of thousands of fixed stars with their positions, proper motions, and visual magnitudes.
8
+
9
+ ---
10
+
11
+ ## Quick Example
12
+
13
+ ```typescript
14
+ import { SwissEph } from '../index';
15
+
16
+ const swe = new SwissEph();
17
+ const jd = SwissEph.julianDay(2024, 1, 1, 12);
18
+
19
+ // Look up Spica
20
+ const spica = swe.fixedStar('Spica', jd);
21
+ console.log(`Spica: ${spica.longitude.toFixed(4)} deg, magnitude visible from fixedStarMagnitude()`);
22
+ console.log(`Full name: ${spica.starName}`);
23
+ // Full name: "Spica,alVir" (traditional name, Bayer designation)
24
+
25
+ // Get visual magnitude
26
+ const mag = swe.fixedStarMagnitude('Spica');
27
+ console.log(`Spica magnitude: ${mag.toFixed(2)}`);
28
+
29
+ swe.close();
30
+ ```
31
+
32
+ ---
33
+
34
+ ## Detailed Examples
35
+
36
+ ### Looking up several well-known stars
37
+
38
+ ```typescript
39
+ import { SwissEph } from '../index';
40
+
41
+ const swe = new SwissEph();
42
+ const jd = SwissEph.julianDay(2024, 6, 21, 12); // Summer solstice 2024
43
+
44
+ const starNames = [
45
+ 'Aldebaran', // alpha Tauri, "Eye of the Bull"
46
+ 'Regulus', // alpha Leonis, "Heart of the Lion"
47
+ 'Spica', // alpha Virginis
48
+ 'Antares', // alpha Scorpii, "Heart of the Scorpion"
49
+ 'Sirius', // alpha Canis Majoris, brightest star in the sky
50
+ 'Fomalhaut', // alpha Piscis Austrini, one of the "Royal Stars"
51
+ 'Algol', // beta Persei, the "Demon Star"
52
+ 'Polaris', // alpha Ursae Minoris, the North Star
53
+ 'Vega', // alpha Lyrae
54
+ 'Canopus', // alpha Carinae, second-brightest star
55
+ ];
56
+
57
+ for (const name of starNames) {
58
+ const star = swe.fixedStar(name, jd);
59
+ const mag = swe.fixedStarMagnitude(name);
60
+ console.log(
61
+ `${name.padEnd(12)} lon: ${star.longitude.toFixed(4).padStart(9)} deg` +
62
+ ` lat: ${star.latitude.toFixed(4).padStart(8)} deg` +
63
+ ` mag: ${mag.toFixed(2)}`
64
+ );
65
+ }
66
+
67
+ swe.close();
68
+ ```
69
+
70
+ ### The starName field format
71
+
72
+ When you call `fixedStar()`, the returned `starName` field contains the canonical name in the format `"traditional,Bayer"`. The traditional name is the common name (e.g., "Spica"), and the Bayer designation uses the Greek letter abbreviation and constellation abbreviation (e.g., "alVir" for alpha Virginis).
73
+
74
+ ```typescript
75
+ import { SwissEph } from '../index';
76
+
77
+ const swe = new SwissEph();
78
+ const jd = SwissEph.julianDay(2024, 1, 1, 12);
79
+
80
+ const star = swe.fixedStar('Regulus', jd);
81
+ console.log(star.starName);
82
+ // "Regulus,alLeo"
83
+ // "Regulus" = traditional name
84
+ // "alLeo" = alpha Leonis (Bayer designation)
85
+
86
+ swe.close();
87
+ ```
88
+
89
+ ### Searching by partial name
90
+
91
+ You can pass a partial name and the engine will find the first matching star. The search is case-insensitive for the traditional name portion.
92
+
93
+ ```typescript
94
+ import { SwissEph } from '../index';
95
+
96
+ const swe = new SwissEph();
97
+ const jd = SwissEph.julianDay(2024, 1, 1, 12);
98
+
99
+ // Search by partial traditional name
100
+ const result = swe.fixedStar('Alde', jd);
101
+ console.log(result.starName); // "Aldebaran,alTau"
102
+
103
+ swe.close();
104
+ ```
105
+
106
+ ### Searching by Bayer/Flamsteed designation
107
+
108
+ You can also search by the Bayer designation. Prefix the search string with a comma to search the designation field:
109
+
110
+ ```typescript
111
+ import { SwissEph } from '../index';
112
+
113
+ const swe = new SwissEph();
114
+ const jd = SwissEph.julianDay(2024, 1, 1, 12);
115
+
116
+ // Search by Bayer designation: comma prefix tells the engine
117
+ // to search the designation field
118
+ const result = swe.fixedStar(',alTau', jd);
119
+ console.log(result.starName); // "Aldebaran,alTau"
120
+
121
+ const result2 = swe.fixedStar(',alCMa', jd);
122
+ console.log(result2.starName); // "Sirius,alCMa"
123
+
124
+ swe.close();
125
+ ```
126
+
127
+ ### Stars used for sidereal ayanamsas
128
+
129
+ Several ayanamsa systems are defined by the position of a specific star. These stars are built into the engine and are used internally when computing star-based ayanamsas:
130
+
131
+ ```typescript
132
+ import { SwissEph } from '../index';
133
+ import { SE_SIDM_TRUE_CITRA, SE_SIDM_TRUE_REVATI, SE_SIDM_TRUE_PUSHYA } from '../../constants';
134
+
135
+ const swe = new SwissEph();
136
+ const jd = SwissEph.julianDay(2024, 1, 1, 12);
137
+
138
+ // Spica (Citra in Sanskrit) -- defines SE_SIDM_TRUE_CITRA
139
+ // In this system, Spica is fixed at exactly 0 deg Libra (180 deg)
140
+ const spica = swe.fixedStar('Spica', jd);
141
+ console.log(`Spica (Citra): ${spica.longitude.toFixed(4)} deg`);
142
+
143
+ // Revati (zeta Piscium) -- defines SE_SIDM_TRUE_REVATI
144
+ // In this system, Revati is fixed at exactly 29d50' Pisces (359.833 deg)
145
+ const revati = swe.fixedStar(',zePs', jd);
146
+ console.log(`Revati: ${revati.longitude.toFixed(4)} deg (${revati.starName})`);
147
+
148
+ // Pushya (delta Cancri) -- defines SE_SIDM_TRUE_PUSHYA
149
+ // In this system, Pushya is fixed at exactly 16 deg Cancer (106 deg)
150
+ const pushya = swe.fixedStar(',deCnc', jd);
151
+ console.log(`Pushya: ${pushya.longitude.toFixed(4)} deg (${pushya.starName})`);
152
+
153
+ swe.close();
154
+ ```
155
+
156
+ ### Getting equatorial coordinates of a star
157
+
158
+ ```typescript
159
+ import { SwissEph } from '../index';
160
+ import { SEFLG_EQUATORIAL } from '../../constants';
161
+
162
+ const swe = new SwissEph();
163
+ const jd = SwissEph.julianDay(2024, 1, 1, 12);
164
+
165
+ const sirius = swe.fixedStar('Sirius', jd, SEFLG_EQUATORIAL);
166
+ // longitude -> Right Ascension (degrees)
167
+ // latitude -> Declination (degrees)
168
+ const raHours = sirius.longitude / 15;
169
+ console.log(`Sirius RA: ${raHours.toFixed(4)} hours`);
170
+ console.log(`Sirius Dec: ${sirius.latitude.toFixed(4)} deg`);
171
+
172
+ swe.close();
173
+ ```
174
+
175
+ ### fixedStar vs fixedStar2
176
+
177
+ Both `fixedStar()` and `fixedStar2()` compute fixed star positions and accept the same parameters. They are functionally equivalent in this wrapper. The distinction comes from the original C library where `swe_fixstar2` used a slightly different internal search algorithm. You can use either one interchangeably.
178
+
179
+ ```typescript
180
+ import { SwissEph } from '../index';
181
+
182
+ const swe = new SwissEph();
183
+ const jd = SwissEph.julianDay(2024, 1, 1, 12);
184
+
185
+ const r1 = swe.fixedStar('Regulus', jd);
186
+ const r2 = swe.fixedStar2('Regulus', jd);
187
+
188
+ console.log(`fixedStar: ${r1.longitude.toFixed(6)}`);
189
+ console.log(`fixedStar2: ${r2.longitude.toFixed(6)}`);
190
+ // Both return identical results
191
+
192
+ swe.close();
193
+ ```
194
+
195
+ ### Visual magnitude
196
+
197
+ Visual magnitude measures how bright a star appears from Earth. Lower numbers are brighter. Negative magnitudes are very bright. The scale is logarithmic: a difference of 5 magnitudes corresponds to a factor of 100 in brightness.
198
+
199
+ ```typescript
200
+ import { SwissEph } from '../index';
201
+
202
+ const swe = new SwissEph();
203
+
204
+ // Some notable magnitudes for reference:
205
+ const stars = ['Sirius', 'Canopus', 'Vega', 'Polaris', 'Algol', 'Spica'];
206
+
207
+ for (const name of stars) {
208
+ const mag = swe.fixedStarMagnitude(name);
209
+ console.log(`${name.padEnd(10)} magnitude: ${mag.toFixed(2)}`);
210
+ }
211
+ // Sirius is about -1.46 (very bright)
212
+ // Polaris is about 2.02 (moderately bright)
213
+
214
+ swe.close();
215
+ ```
216
+
217
+ ---
218
+
219
+ ## Deep Explanation
220
+
221
+ ### What positions mean for fixed stars
222
+
223
+ The return values for fixed stars are the same as for planets:
224
+
225
+ | Field | Meaning for fixed stars |
226
+ |-------------------|----------------------------------------------------------------------------|
227
+ | `longitude` | Ecliptic longitude in degrees (0-360), or RA if `SEFLG_EQUATORIAL` |
228
+ | `latitude` | Ecliptic latitude in degrees, or Declination if `SEFLG_EQUATORIAL` |
229
+ | `distance` | Distance in AU (very large numbers for stars; 1 parsec = 206265 AU) |
230
+ | `longitudeSpeed` | Annual proper motion in longitude, expressed as degrees per day |
231
+ | `latitudeSpeed` | Annual proper motion in latitude, expressed as degrees per day |
232
+ | `distanceSpeed` | Radial velocity contribution to distance change (degrees per day) |
233
+ | `starName` | Canonical name: `"TraditionalName,BayerDesignation"` |
234
+
235
+ ### Why fixed star positions change
236
+
237
+ Even though stars appear "fixed," their calculated ecliptic longitude changes over time for two reasons:
238
+
239
+ 1. **Precession of the equinoxes** (~50.3 arcseconds/year): The Earth's axis wobbles like a top with a period of about 25,800 years. This shifts the reference point (vernal equinox) that defines 0 degrees Aries in the tropical zodiac. All star longitudes increase by about 50.3"/year due to precession alone. This is by far the dominant effect.
240
+
241
+ 2. **Proper motion**: Each star has its own velocity through space. Most proper motions are tiny (under 1"/year), but a few nearby stars move noticeably. Barnard's Star has the largest proper motion at about 10.3"/year.
242
+
243
+ ### The Four Royal Stars
244
+
245
+ In ancient Persian (Zoroastrian) astrology, four bright stars were considered the "Watchers" or "Royal Stars," roughly marking the four cardinal directions of the zodiac around 3000 BCE:
246
+
247
+ - **Aldebaran** (Watcher of the East) -- currently ~10 degrees Gemini
248
+ - **Regulus** (Watcher of the North) -- currently ~0 degrees Virgo
249
+ - **Antares** (Watcher of the West) -- currently ~10 degrees Sagittarius
250
+ - **Fomalhaut** (Watcher of the South) -- currently ~4 degrees Pisces
251
+
252
+ Due to precession, these stars have moved about 40 degrees since the system was established.
253
+
254
+ ### Bayer designation abbreviations
255
+
256
+ The Bayer designation uses abbreviated Greek letters and constellation names:
257
+
258
+ | Abbreviation | Greek Letter | Example |
259
+ |-------------|--------------|---------------------|
260
+ | al | alpha | alVir = alpha Virginis (Spica) |
261
+ | be | beta | bePer = beta Persei (Algol) |
262
+ | ga | gamma | gaOri = gamma Orionis |
263
+ | de | delta | deCnc = delta Cancri |
264
+ | ep | epsilon | epCMa = epsilon Canis Majoris |
265
+ | ze | zeta | zePs = zeta Piscium (Revati) |
266
+
267
+ Constellation abbreviations follow the standard IAU three-letter codes: Vir (Virgo), Leo (Leo), Tau (Taurus), Ori (Orion), CMa (Canis Major), etc.
268
+
269
+ ### Applicable flags
270
+
271
+ Most flags that work with planets also work with fixed stars:
272
+
273
+ - `SEFLG_EQUATORIAL` -- get Right Ascension and Declination
274
+ - `SEFLG_XYZ` -- get Cartesian coordinates
275
+ - `SEFLG_SIDEREAL` -- get sidereal position (requires `siderealMode` configured)
276
+ - `SEFLG_J2000` -- refer to J2000 equinox
277
+ - `SEFLG_NONUT` -- mean equinox of date (no nutation)
278
+ - `SEFLG_RADIANS` -- angles in radians
279
+
280
+ Flags that do not apply to fixed stars (they are silently ignored):
281
+ - `SEFLG_HELCTR` -- stars are so distant that heliocentric/geocentric makes no difference
282
+ - `SEFLG_TOPOCTR` -- similarly, topocentric parallax is negligible for stars
283
+ - `SEFLG_TRUEPOS`, `SEFLG_NOABERR`, `SEFLG_NOGDEFL` -- aberration and light deflection do apply and can be toggled
284
+
285
+ ### Magnitude scale reference
286
+
287
+ | Magnitude | Example |
288
+ |-----------|----------------------------------|
289
+ | -1.46 | Sirius (brightest star) |
290
+ | -0.72 | Canopus (second brightest) |
291
+ | 0.03 | Vega |
292
+ | 0.08 | Capella |
293
+ | 0.85 | Aldebaran |
294
+ | 1.00 | Spica |
295
+ | 1.06 | Antares |
296
+ | 1.35 | Regulus |
297
+ | 2.02 | Polaris |
298
+ | 6.0 | Approximate naked-eye limit |
299
+
300
+ Lower magnitude = brighter. Each step of 1 magnitude = ~2.512x brightness difference.