starplot 0.20.5__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.
- starplot/__init__.py +59 -0
- starplot/callables.py +176 -0
- starplot/cli.py +29 -0
- starplot/config.py +80 -0
- starplot/coordinates.py +7 -0
- starplot/data/__init__.py +22 -0
- starplot/data/catalogs.py +356 -0
- starplot/data/constellations.py +71 -0
- starplot/data/db.py +33 -0
- starplot/data/dsos.py +85 -0
- starplot/data/ecliptic.py +201 -0
- starplot/data/library/constellation_names.parquet +0 -0
- starplot/data/library/dso_names.parquet +0 -0
- starplot/data/library/readme.md +1 -0
- starplot/data/library/star_designations.parquet +0 -0
- starplot/data/stars.py +79 -0
- starplot/data/translations.py +408 -0
- starplot/data/utils.py +35 -0
- starplot/geometry.py +319 -0
- starplot/mixins.py +360 -0
- starplot/models/__init__.py +21 -0
- starplot/models/base.py +77 -0
- starplot/models/comet.py +302 -0
- starplot/models/constellation.py +151 -0
- starplot/models/dso.py +317 -0
- starplot/models/milky_way.py +30 -0
- starplot/models/moon.py +130 -0
- starplot/models/objects.py +29 -0
- starplot/models/observer.py +125 -0
- starplot/models/optics.py +342 -0
- starplot/models/planet.py +137 -0
- starplot/models/satellite.py +138 -0
- starplot/models/star.py +253 -0
- starplot/models/sun.py +62 -0
- starplot/plots/__init__.py +7 -0
- starplot/plots/base.py +1023 -0
- starplot/plots/galaxy.py +372 -0
- starplot/plots/horizon.py +543 -0
- starplot/plots/map.py +515 -0
- starplot/plots/optic.py +469 -0
- starplot/plots/zenith.py +217 -0
- starplot/plotters/__init__.py +9 -0
- starplot/plotters/arrow.py +174 -0
- starplot/plotters/constellations.py +298 -0
- starplot/plotters/debug.py +21 -0
- starplot/plotters/dsos.py +294 -0
- starplot/plotters/experimental.py +722 -0
- starplot/plotters/gradients.py +153 -0
- starplot/plotters/legend.py +253 -0
- starplot/plotters/milkyway.py +51 -0
- starplot/plotters/stars.py +319 -0
- starplot/plotters/text.py +802 -0
- starplot/profile.py +16 -0
- starplot/projections.py +184 -0
- starplot/styles/__init__.py +6 -0
- starplot/styles/base.py +1344 -0
- starplot/styles/ext/antique.yml +175 -0
- starplot/styles/ext/blue_dark.yml +163 -0
- starplot/styles/ext/blue_gold.yml +147 -0
- starplot/styles/ext/blue_light.yml +123 -0
- starplot/styles/ext/blue_medium.yml +142 -0
- starplot/styles/ext/blue_night.yml +185 -0
- starplot/styles/ext/cb_wong.yml +124 -0
- starplot/styles/ext/color_print.yml +111 -0
- starplot/styles/ext/gradient_presets.yml +158 -0
- starplot/styles/ext/grayscale.yml +94 -0
- starplot/styles/ext/grayscale_dark.yml +136 -0
- starplot/styles/ext/map.yml +12 -0
- starplot/styles/ext/nord.yml +158 -0
- starplot/styles/ext/optic.yml +20 -0
- starplot/styles/ext/publication.yml +8 -0
- starplot/styles/extensions.py +129 -0
- starplot/styles/fonts-library/gfs-didot/DESCRIPTION.en_us.html +9 -0
- starplot/styles/fonts-library/gfs-didot/GFSDidot-Regular.ttf +0 -0
- starplot/styles/fonts-library/gfs-didot/METADATA.pb +16 -0
- starplot/styles/fonts-library/gfs-didot/OFL.txt +94 -0
- starplot/styles/fonts-library/inter/Inter-Bold.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-BoldItalic.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-ExtraBold.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-ExtraLight.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-ExtraLightItalic.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-Italic.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-Light.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-LightItalic.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-Regular.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-SemiBold.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-SemiBoldItalic.ttf +0 -0
- starplot/styles/fonts-library/inter/LICENSE.txt +92 -0
- starplot/styles/fonts.py +15 -0
- starplot/styles/helpers.py +93 -0
- starplot/styles/markers.py +308 -0
- starplot/utils.py +169 -0
- starplot/warnings.py +21 -0
- starplot-0.20.5.dist-info/METADATA +146 -0
- starplot-0.20.5.dist-info/RECORD +98 -0
- starplot-0.20.5.dist-info/WHEEL +4 -0
- starplot-0.20.5.dist-info/entry_points.txt +3 -0
- starplot-0.20.5.dist-info/licenses/LICENSE +21 -0
starplot/models/star.py
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Optional, Union, Iterator
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pyarrow as pa
|
|
6
|
+
from ibis import _
|
|
7
|
+
from shapely import from_wkb, Point, Geometry
|
|
8
|
+
|
|
9
|
+
from starplot.models.base import SkyObject, CatalogObject
|
|
10
|
+
from starplot.data.catalogs import Catalog, BIG_SKY_MAG11
|
|
11
|
+
from starplot.data.stars import load as _load_stars
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(slots=True, kw_only=True)
|
|
15
|
+
class Star(CatalogObject, SkyObject):
|
|
16
|
+
"""
|
|
17
|
+
Star model.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
magnitude: float
|
|
21
|
+
"""Magnitude"""
|
|
22
|
+
|
|
23
|
+
geometry: Point
|
|
24
|
+
"""Shapely Point of the star's position. Right ascension coordinates are in degrees (0...360)."""
|
|
25
|
+
|
|
26
|
+
epoch_year: float = None
|
|
27
|
+
"""Epoch of position"""
|
|
28
|
+
|
|
29
|
+
bv: Optional[float] = None
|
|
30
|
+
"""B-V Color Index, if available"""
|
|
31
|
+
|
|
32
|
+
hip: Optional[int] = None
|
|
33
|
+
"""Hipparcos Catalog ID, if available"""
|
|
34
|
+
|
|
35
|
+
tyc: Optional[str] = None
|
|
36
|
+
"""Tycho ID, if available"""
|
|
37
|
+
|
|
38
|
+
ccdm: Optional[str] = None
|
|
39
|
+
"""CCDM Component Identifier (if applicable)"""
|
|
40
|
+
|
|
41
|
+
parallax_mas: float = None
|
|
42
|
+
"""Trigonometric parallax in milliarcseconds"""
|
|
43
|
+
|
|
44
|
+
ra_mas_per_year: float = None
|
|
45
|
+
"""Right ascension proper motion in milliarcseconds per Julian year"""
|
|
46
|
+
|
|
47
|
+
dec_mas_per_year: float = None
|
|
48
|
+
"""Declination proper motion in milliarcseconds per Julian year"""
|
|
49
|
+
|
|
50
|
+
name: Optional[str] = None
|
|
51
|
+
"""Name, if available"""
|
|
52
|
+
|
|
53
|
+
bayer: Optional[str] = None
|
|
54
|
+
"""Bayer designation, if available"""
|
|
55
|
+
|
|
56
|
+
flamsteed: Optional[int] = None
|
|
57
|
+
"""Flamsteed number, if available"""
|
|
58
|
+
|
|
59
|
+
@classmethod
|
|
60
|
+
def _pyarrow_schema(cls):
|
|
61
|
+
base_schema = super(Star, cls)._pyarrow_schema()
|
|
62
|
+
star_fields = [
|
|
63
|
+
pa.field("pk", pa.int64(), nullable=False),
|
|
64
|
+
pa.field("geometry", pa.binary(), nullable=False),
|
|
65
|
+
pa.field("magnitude", pa.float64(), nullable=False),
|
|
66
|
+
pa.field("epoch_year", pa.float64()),
|
|
67
|
+
pa.field("bv", pa.float64()),
|
|
68
|
+
pa.field("hip", pa.int64()),
|
|
69
|
+
pa.field("tyc", pa.string()),
|
|
70
|
+
pa.field("ccdm", pa.string()),
|
|
71
|
+
pa.field("parallax_mas", pa.float64()),
|
|
72
|
+
pa.field("ra_mas_per_year", pa.float64()),
|
|
73
|
+
pa.field("dec_mas_per_year", pa.float64()),
|
|
74
|
+
pa.field("name", pa.string()),
|
|
75
|
+
pa.field("bayer", pa.string()),
|
|
76
|
+
pa.field("flamsteed", pa.int64()),
|
|
77
|
+
]
|
|
78
|
+
return pa.schema(list(base_schema) + star_fields)
|
|
79
|
+
|
|
80
|
+
def __post_init__(self):
|
|
81
|
+
self.bayer = self.bayer or None
|
|
82
|
+
self.hip = (
|
|
83
|
+
int(self.hip) if self.hip is not None and np.isfinite(self.hip) else None
|
|
84
|
+
)
|
|
85
|
+
self.flamsteed = (
|
|
86
|
+
int(self.flamsteed)
|
|
87
|
+
if self.flamsteed is not None and np.isfinite(self.flamsteed)
|
|
88
|
+
else None
|
|
89
|
+
)
|
|
90
|
+
self.ccdm = self.ccdm if isinstance(self.ccdm, str) else None
|
|
91
|
+
|
|
92
|
+
def __repr__(self) -> str:
|
|
93
|
+
return f"Star(hip={self.hip}, tyc={self.tyc}, magnitude={self.magnitude}, ra={self.ra}, dec={self.dec})"
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def is_primary(self) -> bool:
|
|
97
|
+
return self.ccdm is None or self.ccdm.startswith("A")
|
|
98
|
+
|
|
99
|
+
@classmethod
|
|
100
|
+
def all(cls, catalog: Catalog = BIG_SKY_MAG11) -> Iterator["Star"]:
|
|
101
|
+
"""
|
|
102
|
+
Get all stars from a catalog
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
catalog: Catalog you want to get star objects from
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
Iterator of Star instances
|
|
109
|
+
"""
|
|
110
|
+
df = _load_stars(catalog=catalog).to_pandas()
|
|
111
|
+
|
|
112
|
+
for s in df.itertuples():
|
|
113
|
+
yield from_tuple(s)
|
|
114
|
+
|
|
115
|
+
@classmethod
|
|
116
|
+
def get(
|
|
117
|
+
cls, catalog: Catalog = BIG_SKY_MAG11, sql: str = None, **kwargs
|
|
118
|
+
) -> Union["Star", None]:
|
|
119
|
+
"""
|
|
120
|
+
Get a Star, by matching its attributes as specified in `**kwargs`
|
|
121
|
+
|
|
122
|
+
If there are multiple matches, then the first match (sorted by CCDM) will be returned.
|
|
123
|
+
|
|
124
|
+
Example:
|
|
125
|
+
|
|
126
|
+
sirius = Star.get(name="Sirius")
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
catalog: The catalog of stars to use
|
|
130
|
+
sql: SQL query for selecting star (table name is "_")
|
|
131
|
+
**kwargs: Attributes on the star you want to match
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
First star that matches specified attributes, when sorted by CCDM -- or `None` if no star matches
|
|
135
|
+
"""
|
|
136
|
+
filters = []
|
|
137
|
+
|
|
138
|
+
for k, v in kwargs.items():
|
|
139
|
+
filters.append(getattr(_, k) == v)
|
|
140
|
+
|
|
141
|
+
table = _load_stars(
|
|
142
|
+
catalog=catalog,
|
|
143
|
+
filters=filters,
|
|
144
|
+
sql=sql,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
if "ccdm" in table.columns:
|
|
148
|
+
table = table.order_by(table.ccdm)
|
|
149
|
+
|
|
150
|
+
df = table.to_pandas()
|
|
151
|
+
results = [from_tuple(s) for s in df.itertuples()]
|
|
152
|
+
|
|
153
|
+
if results:
|
|
154
|
+
return results[0]
|
|
155
|
+
|
|
156
|
+
return None
|
|
157
|
+
|
|
158
|
+
@classmethod
|
|
159
|
+
def find(
|
|
160
|
+
cls,
|
|
161
|
+
catalog: Catalog = BIG_SKY_MAG11,
|
|
162
|
+
where: list = None,
|
|
163
|
+
sql: str = None,
|
|
164
|
+
) -> list["Star"]:
|
|
165
|
+
"""
|
|
166
|
+
Find Stars
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
catalog: The catalog of stars to use
|
|
170
|
+
where: A list of expressions that determine which stars to find. See [Selecting Objects](/reference-selecting-objects/) for details.
|
|
171
|
+
sql: SQL query for selecting stars (table name is "_")
|
|
172
|
+
|
|
173
|
+
Returns:
|
|
174
|
+
List of Stars that match all `where` expressions
|
|
175
|
+
|
|
176
|
+
"""
|
|
177
|
+
|
|
178
|
+
# from ibis import to_sql
|
|
179
|
+
|
|
180
|
+
# from starplot.data import db
|
|
181
|
+
|
|
182
|
+
# con = db.connect()
|
|
183
|
+
|
|
184
|
+
# exp = _load_stars(
|
|
185
|
+
# catalog=catalog,
|
|
186
|
+
# filters=where,
|
|
187
|
+
# sql=sql,
|
|
188
|
+
# ).select(Star._fields())
|
|
189
|
+
|
|
190
|
+
# result = con.raw_sql(to_sql(exp))
|
|
191
|
+
# columns = [desc[0] for desc in result.description]
|
|
192
|
+
|
|
193
|
+
# rows =[]
|
|
194
|
+
# while True:
|
|
195
|
+
# batch = result.fetchmany(5_000)
|
|
196
|
+
# if not batch:
|
|
197
|
+
# break # No more rows to fetch
|
|
198
|
+
# for row in batch:
|
|
199
|
+
# row_dict = dict(zip(columns, row))
|
|
200
|
+
# # breakpoint()
|
|
201
|
+
# s = from_dict(row_dict)
|
|
202
|
+
# rows.append(s)
|
|
203
|
+
|
|
204
|
+
# return rows
|
|
205
|
+
|
|
206
|
+
df = _load_stars(
|
|
207
|
+
catalog=catalog,
|
|
208
|
+
filters=where,
|
|
209
|
+
sql=sql,
|
|
210
|
+
).to_pandas()
|
|
211
|
+
|
|
212
|
+
return [from_tuple(s) for s in df.itertuples()]
|
|
213
|
+
|
|
214
|
+
@classmethod
|
|
215
|
+
def get_label(cls, star) -> str:
|
|
216
|
+
"""
|
|
217
|
+
Default function for determining the plotted label for a Star.
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
The star's name
|
|
221
|
+
"""
|
|
222
|
+
return star.name
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def from_dict(star: dict) -> Star:
|
|
226
|
+
if not isinstance(star["geometry"], Geometry):
|
|
227
|
+
star["geometry"] = from_wkb(star["geometry"])
|
|
228
|
+
|
|
229
|
+
return Star(**star)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def from_tuple(star: tuple) -> Star:
|
|
233
|
+
kwargs = {f: getattr(star, f) for f in Star._fields() if hasattr(star, f)}
|
|
234
|
+
if not isinstance(kwargs["geometry"], Geometry):
|
|
235
|
+
kwargs["geometry"] = from_wkb(kwargs["geometry"])
|
|
236
|
+
s = Star(**kwargs)
|
|
237
|
+
|
|
238
|
+
# print(set(star._fields) )
|
|
239
|
+
# populate extra fields
|
|
240
|
+
# fields = Star._dir() + [
|
|
241
|
+
# 'Index',
|
|
242
|
+
# 'constellation',
|
|
243
|
+
# 'constellation_id',
|
|
244
|
+
# ]
|
|
245
|
+
# extra_fields = set(star._fields) - set(fields)
|
|
246
|
+
# extra = {}
|
|
247
|
+
# for f in extra_fields:
|
|
248
|
+
# # setattr(s, f, getattr(star, f))
|
|
249
|
+
# extra[f] = getattr(star, f)
|
|
250
|
+
|
|
251
|
+
# s.extra = extra
|
|
252
|
+
|
|
253
|
+
return s
|
starplot/models/sun.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
from shapely import Polygon
|
|
6
|
+
from skyfield.api import Angle
|
|
7
|
+
|
|
8
|
+
from starplot.data import load
|
|
9
|
+
from starplot.models.base import SkyObject
|
|
10
|
+
from starplot.models.observer import Observer
|
|
11
|
+
from starplot.geometry import circle
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(slots=True)
|
|
15
|
+
class Sun(SkyObject):
|
|
16
|
+
"""Sun model."""
|
|
17
|
+
|
|
18
|
+
name: str = "Sun"
|
|
19
|
+
"""Name of the Sun"""
|
|
20
|
+
|
|
21
|
+
dt: datetime = None
|
|
22
|
+
"""Date/time of Sun's position"""
|
|
23
|
+
|
|
24
|
+
apparent_size: float = 0
|
|
25
|
+
"""Apparent diameter (degrees)"""
|
|
26
|
+
|
|
27
|
+
geometry: Polygon = None
|
|
28
|
+
"""Shapely Polygon of the Sun's extent. Right ascension coordinates are in degrees (0...360)."""
|
|
29
|
+
|
|
30
|
+
@classmethod
|
|
31
|
+
def get(
|
|
32
|
+
cls,
|
|
33
|
+
observer: Observer = None,
|
|
34
|
+
ephemeris: str = "de421.bsp",
|
|
35
|
+
) -> "Sun":
|
|
36
|
+
"""
|
|
37
|
+
Get the Sun for a specific date/time and observing location.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
observer: Observer instance that specifies a time and location
|
|
41
|
+
ephemeris: Ephemeris to use for calculating Sun/moon/planet positions (see [Skyfield's documentation](https://rhodesmill.org/skyfield/planets.html) for details)
|
|
42
|
+
"""
|
|
43
|
+
RADIUS_KM = 695_700
|
|
44
|
+
|
|
45
|
+
observer = observer or Observer(lat=None, lon=None)
|
|
46
|
+
eph = load(ephemeris)
|
|
47
|
+
sun = eph["sun"]
|
|
48
|
+
|
|
49
|
+
ra, dec, distance = observer._astrometric(sun, ephemeris=ephemeris)
|
|
50
|
+
|
|
51
|
+
apparent_diameter_degrees = Angle(
|
|
52
|
+
radians=np.arcsin(RADIUS_KM / distance.km) * 2.0
|
|
53
|
+
).degrees
|
|
54
|
+
|
|
55
|
+
return Sun(
|
|
56
|
+
ra=ra.hours * 15,
|
|
57
|
+
dec=dec.degrees,
|
|
58
|
+
name="Sun",
|
|
59
|
+
dt=observer.dt,
|
|
60
|
+
apparent_size=apparent_diameter_degrees,
|
|
61
|
+
geometry=circle((ra.hours * 15, dec.degrees), apparent_diameter_degrees),
|
|
62
|
+
)
|