aetherfield 0.2.6__tar.gz → 0.2.7__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aetherfield
3
- Version: 0.2.6
3
+ Version: 0.2.7
4
4
  Summary: AetherField runtime ephemeris
5
5
  Author: WitchMithras
6
6
  License: Other/Proprietary License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "aetherfield"
7
- version = "0.2.6"
7
+ version = "0.2.7"
8
8
  description = "AetherField runtime ephemeris"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -32,9 +32,4 @@ package-dir = {"" = "src"}
32
32
  [tool.setuptools.packages.find]
33
33
  where = ["src"]
34
34
  include = ["aetherfield*"]
35
- exclude = ["tests*"]
36
-
37
- [project.scripts]
38
- aetherfield-compare = "aetherfield.cli.compare:main"
39
- aetherfield-benchmark = "aetherfield.cli.benchmark:main"
40
- aetherfield-calibrate-all = "aetherfield.cli.calibrate_all:main"
35
+ exclude = ["tests*"]
@@ -40,6 +40,8 @@ AGE_LENGTH = 2147.67
40
40
  ANCHOR_YEAR = 1
41
41
  ANCHOR_SIGN = "Pisces"
42
42
 
43
+ load_dotenv()
44
+
43
45
  def _wrap_deg(x: float) -> float:
44
46
  return x % 360.0
45
47
 
@@ -156,7 +158,6 @@ def _lst_deg(dt, lon_deg):
156
158
  return (_gmst_deg(dt) + lon_deg) % 360.0
157
159
 
158
160
 
159
- load_dotenv()
160
161
 
161
162
  try:
162
163
  import pytz
@@ -219,8 +220,8 @@ except Exception:
219
220
 
220
221
  DE421_START = datetime(1951, 1, 1, tzinfo=UTC)
221
222
  DE421_END = datetime(2050, 12, 31, 23, 59, 59, tzinfo=UTC)
222
- DE400_START = datetime(1550, 1, 1, tzinfo=UTC)
223
- DE400_END = datetime(2650, 12, 31, 23, 59, 59, tzinfo=UTC)
223
+ DE440_START = datetime(1550, 1, 1, tzinfo=UTC)
224
+ DE440_END = datetime(2650, 12, 31, 23, 59, 59, tzinfo=UTC)
224
225
  # DE441 spans beyond Python's datetime range; clamp to supported bounds.
225
226
  DE441_START = datetime(1, 1, 1, tzinfo=UTC)
226
227
  DE441_END = datetime(9999, 12, 31, 23, 59, 59, tzinfo=UTC)
@@ -235,16 +236,6 @@ class EphemerisSpec:
235
236
  true_start_year: int
236
237
  true_end_year: int
237
238
 
238
-
239
- _DE440_SPEC = EphemerisSpec(
240
- name="de440",
241
- filename="de440.bsp",
242
- start=DE400_START,
243
- end=DE400_END,
244
- true_start_year=1550,
245
- true_end_year=2650,
246
- )
247
-
248
239
  EPHEMERIS_SPECS: Dict[str, EphemerisSpec] = {
249
240
  "de421": EphemerisSpec(
250
241
  name="de421",
@@ -254,8 +245,14 @@ EPHEMERIS_SPECS: Dict[str, EphemerisSpec] = {
254
245
  true_start_year=1951,
255
246
  true_end_year=2050,
256
247
  ),
257
- "de440": _DE440_SPEC,
258
- "de400": _DE440_SPEC, # alias for de440
248
+ "de440": EphemerisSpec(
249
+ name="de440",
250
+ filename="de440.bsp",
251
+ start=DE440_START,
252
+ end=DE440_END,
253
+ true_start_year=1550,
254
+ true_end_year=2650,
255
+ ),
259
256
  "de441": EphemerisSpec(
260
257
  name="de441",
261
258
  filename="de441.bsp",
@@ -318,6 +315,13 @@ def _select_calibration_ephemeris() -> Tuple[EphemerisSpec, Optional[Path]]:
318
315
  return spec, path
319
316
  return EPHEMERIS_SPECS["de421"], _resolve_ephemeris_path("de421.bsp")
320
317
 
318
+ def resolve_ephemeris(year: int):
319
+ if 1950 <= year <= 2050:
320
+ return "de421"
321
+ elif 1550 <= year <= 2650:
322
+ return "de440"
323
+ else:
324
+ return "de441"
321
325
 
322
326
  _CAL_EPHEMERIS_SPEC, _CAL_EPHEMERIS_PATH = _select_calibration_ephemeris()
323
327
  EPHEMERIS_NAME = _CAL_EPHEMERIS_SPEC.name
@@ -943,14 +947,14 @@ class AetherField:
943
947
  'rates_deg_per_day': self.rates_deg_per_day,
944
948
  'anchors_min': self.anchors_min,
945
949
  'anchors_max': self.anchors_max,
946
- 'ephemeris_name': ephemeris_name,
947
- 'ephemeris_path': ephemeris_path,
950
+ #'ephemeris_name': ephemeris_name,
951
+ #'ephemeris_path': ephemeris_path,
948
952
  'ephemeris_start': self.window_start.isoformat(),
949
953
  'ephemeris_end': self.window_end.isoformat(),
950
954
  'ephemeris_true_start_year': spec.true_start_year if spec else None,
951
955
  'ephemeris_true_end_year': spec.true_end_year if spec else None,
952
- 'de421_start': self.window_start.isoformat(),
953
- 'de421_end': self.window_end.isoformat(),
956
+ #'de421_start': self.window_start.isoformat(),
957
+ #'de421_end': self.window_end.isoformat(),
954
958
  'piecewise': pw,
955
959
  }
956
960
  with open(path, 'w', encoding='utf-8') as f:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aetherfield
3
- Version: 0.2.6
3
+ Version: 0.2.7
4
4
  Summary: AetherField runtime ephemeris
5
5
  Author: WitchMithras
6
6
  License: Other/Proprietary License
@@ -7,9 +7,5 @@ src/aetherfield/iplocal.py
7
7
  src/aetherfield.egg-info/PKG-INFO
8
8
  src/aetherfield.egg-info/SOURCES.txt
9
9
  src/aetherfield.egg-info/dependency_links.txt
10
- src/aetherfield.egg-info/entry_points.txt
11
10
  src/aetherfield.egg-info/requires.txt
12
- src/aetherfield.egg-info/top_level.txt
13
- src/aetherfield/cli/benchmark.py
14
- src/aetherfield/cli/calibrate_all.py
15
- src/aetherfield/cli/compare.py
11
+ src/aetherfield.egg-info/top_level.txt
@@ -1,195 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import argparse
4
- from dataclasses import dataclass
5
- from datetime import datetime, timedelta
6
- from statistics import mean, median
7
- from typing import Dict, List, Optional, Sequence
8
-
9
- import pytz
10
- import aetherfield as af
11
-
12
-
13
- UTC = pytz.utc
14
- DE421_START = af.DE421_START
15
- DE421_END = af.DE421_END
16
-
17
-
18
- def parse_dt(s: str) -> datetime:
19
- s = s.strip()
20
- if s.endswith('Z'):
21
- s = s[:-1]
22
- dt = datetime.fromisoformat(s)
23
- return dt.replace(tzinfo=UTC)
24
- dt = datetime.fromisoformat(s)
25
- if dt.tzinfo is None:
26
- dt = dt.replace(tzinfo=UTC)
27
- return dt.astimezone(UTC)
28
-
29
-
30
- def wrap_delta_deg(a: float, b: float) -> float:
31
- return (a - b + 540.0) % 360.0 - 180.0
32
-
33
-
34
- def _drift_longitude(a: af.AetherField, dt: datetime, body: str, anchor_mode: str = 'nearest') -> float:
35
- a._ensure_anchor(body) # type: ignore[attr-defined]
36
- rate = a.rates_deg_per_day.get(body)
37
- if rate is None:
38
- raise KeyError(f"No drift rate for body: {body}")
39
- dt = dt if dt.tzinfo else dt.replace(tzinfo=UTC)
40
- dt = dt.astimezone(UTC)
41
- if anchor_mode == 'nearest':
42
- d_start = abs((dt - DE421_START).total_seconds())
43
- d_end = abs((DE421_END - dt).total_seconds())
44
- anchor_mode = 'start' if d_start < d_end else 'end'
45
- if anchor_mode == 'start':
46
- days = (dt - DE421_START).total_seconds() / 86400.0
47
- return (a.anchors_min[body] + rate * days) % 360.0 # type: ignore[attr-defined]
48
- else:
49
- days = (dt - DE421_END).total_seconds() / 86400.0
50
- return (a.anchors_max[body] + rate * days) % 360.0 # type: ignore[attr-defined]
51
-
52
-
53
- def skyfield_longitudes(ts: Sequence[datetime], body: str) -> List[float]:
54
- from skyfield.api import load
55
- from skyfield.framelib import ecliptic_frame
56
-
57
- eph = load('de421.bsp')
58
- earth = eph['earth']
59
- key = af._body_key(eph, body) # type: ignore[attr-defined]
60
- tscale = load.timescale()
61
- out: List[float] = []
62
- for dt in ts:
63
- t = tscale.from_datetime(dt.astimezone(UTC))
64
- app = earth.at(t).observe(key).apparent()
65
- lon, lat, dist = app.frame_latlon(ecliptic_frame)
66
- out.append(float(lon.degrees) % 360.0)
67
- return out
68
-
69
-
70
- @dataclass
71
- class BodyStats:
72
- n: int
73
- mae_mean: float
74
- mae_piece: float
75
- med_mean: float
76
- med_piece: float
77
- max_mean: float
78
- max_piece: float
79
-
80
-
81
- def benchmark(
82
- bodies: Sequence[str],
83
- start: datetime,
84
- end: datetime,
85
- step_days: int,
86
- piecewise_step: int,
87
- build_piecewise: bool,
88
- fit_rates: bool,
89
- drift_anchor: str,
90
- load_cal: Optional[str],
91
- save_cal: Optional[str],
92
- ) -> Dict[str, BodyStats]:
93
- r0 = max(start, DE421_START)
94
- r1 = min(end, DE421_END)
95
- if r1 < r0:
96
- return {}
97
- tlist: List[datetime] = []
98
- step_days = max(1, int(step_days))
99
- t = r0
100
- while t <= r1:
101
- tlist.append(t)
102
- t = t + timedelta(days=step_days)
103
-
104
- if load_cal:
105
- a = af.AetherField.load_calibration(load_cal)
106
- else:
107
- a = af.AetherField()
108
- if fit_rates:
109
- try:
110
- a.fit_rates()
111
- except Exception:
112
- pass
113
- if build_piecewise:
114
- try:
115
- a.fit_piecewise(step_days=piecewise_step, bodies=tuple(bodies))
116
- except Exception:
117
- pass
118
- if save_cal:
119
- try:
120
- a.save_calibration(save_cal)
121
- except Exception:
122
- pass
123
-
124
- results: Dict[str, BodyStats] = {}
125
- for body in bodies:
126
- sky = skyfield_longitudes(tlist, body)
127
- mean_preds = [_drift_longitude(a, dt, body, anchor_mode=drift_anchor) for dt in tlist]
128
- if build_piecewise and (body in getattr(a, 'piecewise', {})):
129
- piece_preds = [a.longitude_piecewise(dt, body, anchor_mode=drift_anchor) for dt in tlist]
130
- else:
131
- piece_preds = [a.longitude(dt, body) for dt in tlist]
132
-
133
- mean_err = [abs(wrap_delta_deg(p, s)) for p, s in zip(mean_preds, sky)]
134
- piece_err = [abs(wrap_delta_deg(p, s)) for p, s in zip(piece_preds, sky)]
135
-
136
- stats = BodyStats(
137
- n=len(sky),
138
- mae_mean=mean(mean_err) if mean_err else float('nan'),
139
- mae_piece=mean(piece_err) if piece_err else float('nan'),
140
- med_mean=median(mean_err) if mean_err else float('nan'),
141
- med_piece=median(piece_err) if piece_err else float('nan'),
142
- max_mean=max(mean_err) if mean_err else float('nan'),
143
- max_piece=max(piece_err) if piece_err else float('nan'),
144
- )
145
- results[body] = stats
146
-
147
- return results
148
-
149
-
150
- def main(argv=None) -> int:
151
- parser = argparse.ArgumentParser(description="Benchmark AetherField mean drift vs piecewise against Skyfield/de421.")
152
- parser.add_argument('--bodies', default='sun,moon,mercury,venus,mars,jupiter,saturn,uranus,neptune,pluto', help='Comma-separated list of bodies to evaluate.')
153
- parser.add_argument('--start', required=True, help='Start datetime ISO8601 (e.g., 2001-01-01T00:00:00Z).')
154
- parser.add_argument('--end', required=True, help='End datetime ISO8601 (inclusive).')
155
- parser.add_argument('--step-days', type=int, default=5, help='Sampling step in days.')
156
- parser.add_argument('--drift-anchor', choices=['start', 'end', 'nearest'], default='nearest', help='Anchor used for mean-drift and extrapolation.')
157
- parser.add_argument('--piecewise', action='store_true', help='Build and use piecewise segments for evaluation.')
158
- parser.add_argument('--piecewise-step', type=int, default=10, help='Step in days for fitting piecewise segments.')
159
- parser.add_argument('--fit-rates', action='store_true', help='Fit mean drift rates from in-range samples before benchmarking.')
160
- parser.add_argument('--load-calibration', default=None, help='Path to load saved calibration (rates/anchors/piecewise).')
161
- parser.add_argument('--save-calibration', default=None, help='Path to save calibration after building.')
162
- parser.add_argument('--json', action='store_true', help='Emit JSON summary instead of text table.')
163
-
164
- args = parser.parse_args(argv)
165
- bodies = [b.strip().lower() for b in args.bodies.split(',') if b.strip()]
166
-
167
- start = parse_dt(args.start)
168
- end = parse_dt(args.end)
169
- stats = benchmark(
170
- bodies=bodies,
171
- start=start,
172
- end=end,
173
- step_days=args.step_days,
174
- piecewise_step=args.piecewise_step,
175
- build_piecewise=args.piecewise,
176
- fit_rates=args.fit_rates,
177
- drift_anchor=args.drift_anchor,
178
- load_cal=args.load_calibration,
179
- save_cal=args.save_calibration,
180
- )
181
-
182
- if args.json:
183
- import json
184
- print(json.dumps({k: vars(v) for k, v in stats.items()}, indent=2))
185
- else:
186
- for b, st in stats.items():
187
- print(f"{b:9s} N={st.n:4d} MAE(mean)={st.mae_mean:6.3f}° MAE(piece)={st.mae_piece:6.3f}° "
188
- f"MED(mean)={st.med_mean:6.3f}° MED(piece)={st.med_piece:6.3f}° "
189
- f"MAX(mean)={st.max_mean:6.3f}° MAX(piece)={st.max_piece:6.3f}°")
190
- return 0
191
-
192
-
193
- if __name__ == '__main__':
194
- raise SystemExit(main())
195
-
@@ -1,61 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import argparse
4
-
5
- import aetherfield as af
6
-
7
-
8
- DEFAULT_OUT = 'aetherfield_calibration.json'
9
-
10
-
11
- def main(argv=None) -> int:
12
- parser = argparse.ArgumentParser(description='Calibrate AetherField and save piecewise segments for all bodies.')
13
- parser.add_argument('--out', default=DEFAULT_OUT, help='Output JSON path for calibration data.')
14
- args = parser.parse_args(argv)
15
-
16
- a = af.AetherField()
17
-
18
- bodies_all = ('sun','moon','mercury','venus','mars','jupiter','saturn','uranus','neptune','pluto')
19
- # Ensure anchors
20
- for b in bodies_all:
21
- a._ensure_anchor(b) # type: ignore[attr-defined]
22
-
23
- # Fit mean drift from in-range samples (coarse global refinement)
24
- try:
25
- a.fit_rates()
26
- except Exception:
27
- pass
28
-
29
- # Piecewise segments with tuned steps per group
30
- groups = [
31
- (('moon',), 1),
32
- (('sun','mercury','venus'), 5),
33
- (('mars',), 10),
34
- (('jupiter','saturn'), 15),
35
- (('uranus','neptune','pluto'), 30),
36
- ]
37
-
38
- summary = {}
39
- for bodies, step in groups:
40
- try:
41
- created = a.fit_piecewise(step_days=step, bodies=bodies)
42
- summary.update(created)
43
- except Exception:
44
- for b in bodies:
45
- summary[b] = summary.get(b, 0)
46
-
47
- # Persist
48
- a.save_calibration(args.out)
49
-
50
- # Print a compact summary
51
- print(f"Saved calibration -> {args.out}")
52
- for b in bodies_all:
53
- n = summary.get(b, 0)
54
- print(f" {b:9s} segments: {n}")
55
-
56
- return 0
57
-
58
-
59
- if __name__ == '__main__':
60
- raise SystemExit(main())
61
-
@@ -1,194 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import argparse
4
- from dataclasses import dataclass
5
- from datetime import datetime, timezone
6
- from typing import Optional
7
-
8
- import pytz
9
-
10
- import aetherfield as af # reuse host implementation during staging
11
-
12
-
13
- UTC = pytz.utc
14
- DE421_START = af.DE421_START
15
- DE421_END = af.DE421_END
16
-
17
- planet_eph = {
18
- 'jupiter': 5,
19
- 'saturn': 6,
20
- 'uranus': 7,
21
- 'neptune': 8,
22
- 'pluto': 9
23
- }
24
-
25
-
26
- def parse_dt(dt_str: Optional[str]) -> datetime:
27
- if not dt_str:
28
- return datetime.now(UTC)
29
- s = dt_str.strip()
30
- if s.endswith('Z'):
31
- s = s[:-1]
32
- dt = datetime.fromisoformat(s)
33
- return dt.replace(tzinfo=UTC)
34
- dt = datetime.fromisoformat(s)
35
- if dt.tzinfo is None:
36
- dt = dt.replace(tzinfo=UTC)
37
- return dt.astimezone(UTC)
38
-
39
-
40
- def parse_moontime(mt_str: Optional[str]) -> Optional[datetime]:
41
- if not mt_str:
42
- return None
43
- try:
44
- from moontime import MoonTime
45
- mt = MoonTime.fromisoformat(mt_str)
46
- return mt.to_datetime().astimezone(UTC)
47
- except Exception:
48
- return None
49
-
50
-
51
- def wrap_delta_deg(a: float, b: float) -> float:
52
- d = (a - b + 540.0) % 360.0 - 180.0
53
- return d
54
-
55
-
56
- def sf_ecliptic_longitude(dt: datetime, body: str) -> float:
57
- from skyfield.api import load
58
- from skyfield.framelib import ecliptic_frame
59
-
60
- if dt.tzinfo is None:
61
- dt = dt.replace(tzinfo=UTC)
62
- dt = dt.astimezone(UTC)
63
-
64
- eph = load('de421.bsp')
65
- ts = load.timescale()
66
- t = ts.from_datetime(dt)
67
- earth = eph['earth']
68
- b = af._body_key(eph, body) # type: ignore[attr-defined]
69
- app = earth.at(t).observe(b).apparent()
70
- lon, lat, dist = app.frame_latlon(ecliptic_frame)
71
- return float(lon.degrees) % 360.0
72
-
73
-
74
- @dataclass
75
- class CompareResult:
76
- body: str
77
- dt: datetime
78
- aether_lon: float
79
- skyfield_lon: Optional[float]
80
- delta_deg: Optional[float]
81
- aether_sign: str
82
- skyfield_sign: Optional[str]
83
-
84
-
85
- def _drift_longitude(a: af.AetherField, dt: datetime, body: str, anchor_mode: str = 'end') -> float:
86
- a._ensure_anchor(body) # type: ignore[attr-defined]
87
- rate = a.rates_deg_per_day.get(body)
88
- if rate is None:
89
- raise KeyError(f"No drift rate for body: {body}")
90
- dt = dt if dt.tzinfo else dt.replace(tzinfo=UTC)
91
- dt = dt.astimezone(UTC)
92
- if anchor_mode == 'nearest':
93
- d_start = abs((dt - DE421_START).total_seconds())
94
- d_end = abs((DE421_END - dt).total_seconds())
95
- anchor_mode = 'start' if d_start < d_end else 'end'
96
- if anchor_mode == 'start':
97
- days = (dt - DE421_START).total_seconds() / 86400.0
98
- return (a.anchors_min[body] + rate * days) % 360.0 # type: ignore[attr-defined]
99
- else:
100
- days = (dt - DE421_END).total_seconds() / 86400.0
101
- return (a.anchors_max[body] + rate * days) % 360.0 # type: ignore[attr-defined]
102
-
103
-
104
- def compare_once(body: str, dt: datetime, force_aether: bool = False, fit_rates: bool = False) -> CompareResult:
105
- a = af.AetherField()
106
- if fit_rates:
107
- try:
108
- a.fit_rates()
109
- except Exception:
110
- pass
111
- if force_aether:
112
- aether_lon = _drift_longitude(a, dt, body)
113
- aether_sign = af.get_zodiac_by_longitude(aether_lon)
114
- else:
115
- aether_lon = a.longitude(dt, body)
116
- aether_sign = a.sign(dt, body)
117
- sky_lon: Optional[float] = None
118
- sky_sign: Optional[str] = None
119
- if DE421_START <= dt <= DE421_END:
120
- try:
121
- sky_lon = sf_ecliptic_longitude(dt, body)
122
- sky_sign = af.get_zodiac_by_longitude(sky_lon)
123
- except Exception:
124
- pass
125
- delta = wrap_delta_deg(aether_lon, sky_lon) if sky_lon is not None else None
126
- return CompareResult(body, dt, aether_lon, sky_lon, delta, aether_sign, sky_sign)
127
-
128
-
129
- def main(argv=None) -> int:
130
- p = argparse.ArgumentParser(description="Compare AetherField with Skyfield for a single timestamp.")
131
- p.add_argument('--body', required=True, help='Body (sun, moon, mercury, ... pluto)')
132
- p.add_argument('--dt', default=None, help='ISO8601 datetime (UTC).')
133
- p.add_argument('--moontime', default=None, help='MoonTime string (mt:...)')
134
- p.add_argument('--force-aether', action='store_true', help='Use AetherField-only (drift).')
135
- p.add_argument('--fit-rates', action='store_true', help='Fit mean drift from in-range samples.')
136
- p.add_argument('--calibrate', action='store_true', help='Ensure anchors and piecewise segments (no-ops if present).')
137
- p.add_argument('--save-calibration', default=None, help='Save calibration JSON path.')
138
- p.add_argument('--load-calibration', default=None, help='Load calibration JSON path.')
139
- p.add_argument('--drift-anchor', choices=['start','end','nearest'], default='end', help='Anchor for drift only mode.')
140
- p.add_argument('--piecewise', action='store_true', help='Use piecewise segments when forcing aether.')
141
- p.add_argument('--piecewise-step', type=int, default=30, help='Step in days for piecewise building.')
142
- p.add_argument('--json', action='store_true', help='Emit JSON instead of text.')
143
- args = p.parse_args(argv)
144
-
145
- body = args.body.strip().lower()
146
- dt = parse_moontime(args.moontime) or parse_dt(args.dt)
147
-
148
- if args.load_calibration:
149
- try:
150
- a = af.AetherField.load_calibration(args.load_calibration)
151
- except Exception:
152
- a = af.AetherField()
153
- else:
154
- a = af.AetherField()
155
- if args.fit_rates:
156
- try:
157
- a.fit_rates()
158
- except Exception:
159
- pass
160
- if args.calibrate:
161
- try:
162
- if args.piecewise:
163
- a.fit_piecewise(step_days=int(args.piecewise_step), bodies=(body,))
164
- except Exception:
165
- pass
166
- if args.save_calibration:
167
- try:
168
- a.save_calibration(args.save_calibration)
169
- except Exception:
170
- pass
171
-
172
- res = compare_once(body, dt, force_aether=args.force_aether, fit_rates=args.fit_rates)
173
-
174
- if args.json:
175
- import json
176
- print(json.dumps({
177
- 'body': res.body,
178
- 'dt': res.dt.isoformat(),
179
- 'aether_lon': res.aether_lon,
180
- 'skyfield_lon': res.skyfield_lon,
181
- 'delta_deg': res.delta_deg,
182
- 'aether_sign': res.aether_sign,
183
- 'skyfield_sign': res.skyfield_sign,
184
- }, indent=2))
185
- else:
186
- print(f"{res.body} @ {res.dt.isoformat()}\n"
187
- f" Aether: {res.aether_lon:8.3f} deg ({res.aether_sign})\n"
188
- f" Skyfield: {'n/a' if res.skyfield_lon is None else f'{res.skyfield_lon:8.3f} deg ('+str(res.skyfield_sign)+')'}\n"
189
- f" Delta: {'n/a' if res.delta_deg is None else f'{res.delta_deg:+.3f} deg'}")
190
- return 0
191
-
192
-
193
- if __name__ == '__main__':
194
- raise SystemExit(main())
@@ -1,4 +0,0 @@
1
- [console_scripts]
2
- aetherfield-benchmark = aetherfield.cli.benchmark:main
3
- aetherfield-calibrate-all = aetherfield.cli.calibrate_all:main
4
- aetherfield-compare = aetherfield.cli.compare:main
File without changes
File without changes
File without changes