libephemeris 0.1.6__py3-none-any.whl
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.
- libephemeris/__init__.py +151 -0
- libephemeris/angles.py +106 -0
- libephemeris/arabic_parts.py +232 -0
- libephemeris/constants.py +318 -0
- libephemeris/crossing.py +326 -0
- libephemeris/fixed_stars.py +228 -0
- libephemeris/houses.py +1625 -0
- libephemeris/lunar.py +269 -0
- libephemeris/minor_bodies.py +398 -0
- libephemeris/planets.py +1228 -0
- libephemeris/state.py +213 -0
- libephemeris/time_utils.py +136 -0
- libephemeris/utils.py +36 -0
- libephemeris-0.1.6.dist-info/METADATA +376 -0
- libephemeris-0.1.6.dist-info/RECORD +18 -0
- libephemeris-0.1.6.dist-info/WHEEL +5 -0
- libephemeris-0.1.6.dist-info/licenses/LICENSE +13 -0
- libephemeris-0.1.6.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Fixed star position calculations for libephemeris.
|
|
3
|
+
|
|
4
|
+
Computes ecliptic positions for bright fixed stars with:
|
|
5
|
+
- Proper motion correction (linear approximation)
|
|
6
|
+
- IAU 2006 precession from J2000 to date
|
|
7
|
+
- Nutation correction for obliquity
|
|
8
|
+
- Equatorial to ecliptic coordinate transformation
|
|
9
|
+
|
|
10
|
+
Supported stars:
|
|
11
|
+
- Regulus (Alpha Leonis) - Royal Star
|
|
12
|
+
- Spica (Alpha Virginis) - Used for ayanamsha calculations
|
|
13
|
+
|
|
14
|
+
FIXME: Precision - Uses simplified linear proper motion
|
|
15
|
+
Real stars have:
|
|
16
|
+
- Radial velocity (3D motion, not just RA/Dec)
|
|
17
|
+
- Parallax (distance changes apparent position)
|
|
18
|
+
- Acceleration (proper motion not constant)
|
|
19
|
+
Full catalogs like Hipparcos/Gaia provide higher precision.
|
|
20
|
+
|
|
21
|
+
Typical precision: ~1-5 arcseconds over ±100 years from J2000
|
|
22
|
+
For research astronomy, use SIMBAD/Gaia catalogs.
|
|
23
|
+
|
|
24
|
+
References:
|
|
25
|
+
- IAU 2006 Precession: Capitaine et al. A&A 412, 567-586 (2003)
|
|
26
|
+
- Proper motion: Hipparcos/Tycho catalogs
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
import math
|
|
30
|
+
from dataclasses import dataclass
|
|
31
|
+
from typing import Tuple
|
|
32
|
+
from .constants import SE_REGULUS, SE_SPICA_STAR
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass
|
|
36
|
+
class StarData:
|
|
37
|
+
"""
|
|
38
|
+
Fixed star astrometric data (ICRS J2000.0 epoch).
|
|
39
|
+
|
|
40
|
+
Attributes:
|
|
41
|
+
ra_j2000: Right Ascension at J2000.0 in degrees
|
|
42
|
+
dec_j2000: Declination at J2000.0 in degrees
|
|
43
|
+
pm_ra: Proper motion in RA (arcsec/year, includes cos(dec) factor)
|
|
44
|
+
pm_dec: Proper motion in Dec (arcsec/year)
|
|
45
|
+
|
|
46
|
+
Note:
|
|
47
|
+
Proper motions are linearized - good for ±200 years from epoch.
|
|
48
|
+
Does not include parallax or radial velocity effects.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
ra_j2000: float
|
|
52
|
+
dec_j2000: float
|
|
53
|
+
pm_ra: float
|
|
54
|
+
pm_dec: float
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
# Fixed star catalog (J2000.0 ICRS coordinates from Hipparcos)
|
|
58
|
+
FIXED_STARS = {
|
|
59
|
+
SE_REGULUS: StarData(
|
|
60
|
+
ra_j2000=152.092958, # 10h 08m 22.3s (Alpha Leonis)
|
|
61
|
+
dec_j2000=11.967208, # +11° 58' 02"
|
|
62
|
+
pm_ra=-0.00249, # -249 mas/yr (westward)
|
|
63
|
+
pm_dec=0.00152, # +152 mas/yr (northward)
|
|
64
|
+
),
|
|
65
|
+
SE_SPICA_STAR: StarData(
|
|
66
|
+
ra_j2000=201.298247, # 13h 25m 11.6s (Alpha Virginis)
|
|
67
|
+
dec_j2000=-11.161319, # -11° 09' 41"
|
|
68
|
+
pm_ra=-0.04235, # -42.35 mas/yr
|
|
69
|
+
pm_dec=-0.03067, # -30.67 mas/yr
|
|
70
|
+
),
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def calc_fixed_star_position(star_id: int, jd_tt: float) -> Tuple[float, float, float]:
|
|
75
|
+
"""
|
|
76
|
+
Calculate ecliptic position of a fixed star at given date.
|
|
77
|
+
|
|
78
|
+
Applies proper motion and precession to J2000.0 catalog position.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
star_id: Star identifier (SE_REGULUS, SE_SPICA_STAR)
|
|
82
|
+
jd_tt: Julian Day in Terrestrial Time (TT)
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
Tuple[float, float, float]: (longitude, latitude, distance) where:
|
|
86
|
+
- longitude: Ecliptic longitude of date in degrees (0-360)
|
|
87
|
+
- latitude: Ecliptic latitude of date in degrees
|
|
88
|
+
- distance: Arbitrary large value (100000 AU) - stars are effectively infinite
|
|
89
|
+
|
|
90
|
+
Raises:
|
|
91
|
+
ValueError: If star_id not in catalog
|
|
92
|
+
|
|
93
|
+
Algorithm:
|
|
94
|
+
1. Apply linear proper motion from J2000 to date
|
|
95
|
+
2. Precess equatorial coordinates using IAU 2006 formula
|
|
96
|
+
3. Calculate true obliquity (mean + nutation)
|
|
97
|
+
4. Transform to ecliptic coordinates
|
|
98
|
+
|
|
99
|
+
FIXME: Precision - Linear proper motion approximation
|
|
100
|
+
- Ignores radial velocity (parallax effect)
|
|
101
|
+
- Assumes constant proper motion (no acceleration)
|
|
102
|
+
- No annual parallax (star distance not modeled)
|
|
103
|
+
Typical error: 1-5 arcsec over ±100 years
|
|
104
|
+
|
|
105
|
+
References:
|
|
106
|
+
IAU 2006 precession (Capitaine et al.)
|
|
107
|
+
Nutation simplified from IAU 2000B
|
|
108
|
+
"""
|
|
109
|
+
if star_id not in FIXED_STARS:
|
|
110
|
+
raise ValueError(f"Unknown star ID: {star_id}")
|
|
111
|
+
|
|
112
|
+
star = FIXED_STARS[star_id]
|
|
113
|
+
|
|
114
|
+
# Time from J2000.0
|
|
115
|
+
t_years = (jd_tt - 2451545.0) / 365.25
|
|
116
|
+
T = (jd_tt - 2451545.0) / 36525.0 # Julian centuries
|
|
117
|
+
|
|
118
|
+
# FIXME: Precision - Linear proper motion (ignores curvature)
|
|
119
|
+
# Apply proper motion to J2000 coordinates
|
|
120
|
+
ra_pm = star.ra_j2000 + (star.pm_ra * t_years) / 3600.0
|
|
121
|
+
dec_pm = star.dec_j2000 + (star.pm_dec * t_years) / 3600.0
|
|
122
|
+
|
|
123
|
+
# IAU 2006 precession parameters (arcseconds -> degrees)
|
|
124
|
+
zeta = (2306.2181 * T + 0.30188 * T**2 + 0.017998 * T**3) / 3600.0
|
|
125
|
+
z = (2306.2181 * T + 1.09468 * T**2 + 0.018203 * T**3) / 3600.0
|
|
126
|
+
theta = (2004.3109 * T - 0.42665 * T**2 - 0.041833 * T**3) / 3600.0
|
|
127
|
+
|
|
128
|
+
zeta_r = math.radians(zeta)
|
|
129
|
+
z_r = math.radians(z)
|
|
130
|
+
theta_r = math.radians(theta)
|
|
131
|
+
ra_r = math.radians(ra_pm)
|
|
132
|
+
dec_r = math.radians(dec_pm)
|
|
133
|
+
|
|
134
|
+
# Convert equatorial to Cartesian (unit sphere)
|
|
135
|
+
x0 = math.cos(dec_r) * math.cos(ra_r)
|
|
136
|
+
y0 = math.cos(dec_r) * math.sin(ra_r)
|
|
137
|
+
z0 = math.sin(dec_r)
|
|
138
|
+
|
|
139
|
+
# Apply precession rotation: R_z(-z) · R_y(θ) · R_z(-ζ)
|
|
140
|
+
# Step 1: R_z(-ζ) rotation around z-axis
|
|
141
|
+
x1 = x0 * math.cos(-zeta_r) + y0 * math.sin(-zeta_r)
|
|
142
|
+
y1 = -x0 * math.sin(-zeta_r) + y0 * math.cos(-zeta_r)
|
|
143
|
+
z1 = z0
|
|
144
|
+
|
|
145
|
+
# Step 2: R_y(θ) rotation around y-axis
|
|
146
|
+
x2 = x1 * math.cos(theta_r) - z1 * math.sin(theta_r)
|
|
147
|
+
y2 = y1
|
|
148
|
+
z2 = x1 * math.sin(theta_r) + z1 * math.cos(theta_r)
|
|
149
|
+
|
|
150
|
+
# Step 3: R_z(-z) rotation around z-axis
|
|
151
|
+
x3 = x2 * math.cos(-z_r) + y2 * math.sin(-z_r)
|
|
152
|
+
y3 = -x2 * math.sin(-z_r) + y2 * math.cos(-z_r)
|
|
153
|
+
z3 = z2
|
|
154
|
+
|
|
155
|
+
# Convert back to spherical (RA/Dec of date)
|
|
156
|
+
ra_date = math.atan2(y3, x3)
|
|
157
|
+
dec_date = math.asin(z3)
|
|
158
|
+
|
|
159
|
+
# Calculate mean obliquity of date (IAU 2006)
|
|
160
|
+
eps0 = 23.43929111 - (46.8150 + (0.00059 - 0.001813 * T) * T) * T / 3600.0
|
|
161
|
+
|
|
162
|
+
# FIXME: Precision - Simplified nutation (2-term approximation)
|
|
163
|
+
# Full IAU 2000B has 77 terms. This captures ~99% of effect.
|
|
164
|
+
omega = 125.04452 - 1934.136261 * T # Longitude of lunar ascending node
|
|
165
|
+
L = 280.4665 + 36000.7698 * T # Mean longitude of Sun
|
|
166
|
+
|
|
167
|
+
# Nutation in obliquity (arcseconds)
|
|
168
|
+
deps = 9.20 * math.cos(math.radians(omega)) + 0.57 * math.cos(math.radians(2 * L))
|
|
169
|
+
deps_deg = deps / 3600.0
|
|
170
|
+
eps_true = eps0 + deps_deg
|
|
171
|
+
eps_r = math.radians(eps_true)
|
|
172
|
+
|
|
173
|
+
# Transform equatorial (RA, Dec) to ecliptic (lon, lat)
|
|
174
|
+
sin_lat = math.sin(dec_date) * math.cos(eps_r) - math.cos(dec_date) * math.sin(
|
|
175
|
+
eps_r
|
|
176
|
+
) * math.sin(ra_date)
|
|
177
|
+
lat = math.asin(sin_lat)
|
|
178
|
+
|
|
179
|
+
y_lon = math.sin(ra_date) * math.cos(eps_r) + math.tan(dec_date) * math.sin(eps_r)
|
|
180
|
+
x_lon = math.cos(ra_date)
|
|
181
|
+
lon = math.degrees(math.atan2(y_lon, x_lon)) % 360.0
|
|
182
|
+
lat_deg = math.degrees(lat)
|
|
183
|
+
|
|
184
|
+
# Distance is arbitrary for fixed stars (effectively infinite)
|
|
185
|
+
dist = 100000.0 # AU (placeholder)
|
|
186
|
+
|
|
187
|
+
return lon, lat_deg, dist
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def swe_fixstar_ut(
|
|
191
|
+
star_name: str, tjd_ut: float, iflag: int
|
|
192
|
+
) -> Tuple[Tuple[float, float, float, float, float, float], int, str]:
|
|
193
|
+
"""
|
|
194
|
+
Calculate position of a fixed star.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
star_name: Name of star (e.g. "Regulus", "Spica")
|
|
198
|
+
tjd_ut: Julian Day in UT
|
|
199
|
+
iflag: Calculation flags
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
((lon, lat, dist, speed_lon, speed_lat, speed_dist), iflag, error_msg)
|
|
203
|
+
"""
|
|
204
|
+
# Map name to ID
|
|
205
|
+
star_id = -1
|
|
206
|
+
name_upper = star_name.upper().strip()
|
|
207
|
+
if "," in name_upper:
|
|
208
|
+
name_upper = name_upper.split(",")[0].strip()
|
|
209
|
+
|
|
210
|
+
if name_upper == "REGULUS":
|
|
211
|
+
star_id = SE_REGULUS
|
|
212
|
+
elif name_upper == "SPICA":
|
|
213
|
+
star_id = SE_SPICA_STAR
|
|
214
|
+
else:
|
|
215
|
+
return ((0.0, 0.0, 0.0, 0.0, 0.0, 0.0), iflag, f"Star {star_name} not found")
|
|
216
|
+
|
|
217
|
+
# Calculate position (simplified, no speed)
|
|
218
|
+
# We use TT for calculation (approximate UT=TT for stars is fine? No, use deltat)
|
|
219
|
+
from .state import get_timescale
|
|
220
|
+
ts = get_timescale()
|
|
221
|
+
t = ts.ut1_jd(tjd_ut)
|
|
222
|
+
|
|
223
|
+
try:
|
|
224
|
+
lon, lat, dist = calc_fixed_star_position(star_id, t.tt)
|
|
225
|
+
return ((lon, lat, dist, 0.0, 0.0, 0.0), iflag, "")
|
|
226
|
+
except Exception as e:
|
|
227
|
+
return ((0.0, 0.0, 0.0, 0.0, 0.0, 0.0), iflag, str(e))
|
|
228
|
+
|