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.
Files changed (98) hide show
  1. starplot/__init__.py +59 -0
  2. starplot/callables.py +176 -0
  3. starplot/cli.py +29 -0
  4. starplot/config.py +80 -0
  5. starplot/coordinates.py +7 -0
  6. starplot/data/__init__.py +22 -0
  7. starplot/data/catalogs.py +356 -0
  8. starplot/data/constellations.py +71 -0
  9. starplot/data/db.py +33 -0
  10. starplot/data/dsos.py +85 -0
  11. starplot/data/ecliptic.py +201 -0
  12. starplot/data/library/constellation_names.parquet +0 -0
  13. starplot/data/library/dso_names.parquet +0 -0
  14. starplot/data/library/readme.md +1 -0
  15. starplot/data/library/star_designations.parquet +0 -0
  16. starplot/data/stars.py +79 -0
  17. starplot/data/translations.py +408 -0
  18. starplot/data/utils.py +35 -0
  19. starplot/geometry.py +319 -0
  20. starplot/mixins.py +360 -0
  21. starplot/models/__init__.py +21 -0
  22. starplot/models/base.py +77 -0
  23. starplot/models/comet.py +302 -0
  24. starplot/models/constellation.py +151 -0
  25. starplot/models/dso.py +317 -0
  26. starplot/models/milky_way.py +30 -0
  27. starplot/models/moon.py +130 -0
  28. starplot/models/objects.py +29 -0
  29. starplot/models/observer.py +125 -0
  30. starplot/models/optics.py +342 -0
  31. starplot/models/planet.py +137 -0
  32. starplot/models/satellite.py +138 -0
  33. starplot/models/star.py +253 -0
  34. starplot/models/sun.py +62 -0
  35. starplot/plots/__init__.py +7 -0
  36. starplot/plots/base.py +1023 -0
  37. starplot/plots/galaxy.py +372 -0
  38. starplot/plots/horizon.py +543 -0
  39. starplot/plots/map.py +515 -0
  40. starplot/plots/optic.py +469 -0
  41. starplot/plots/zenith.py +217 -0
  42. starplot/plotters/__init__.py +9 -0
  43. starplot/plotters/arrow.py +174 -0
  44. starplot/plotters/constellations.py +298 -0
  45. starplot/plotters/debug.py +21 -0
  46. starplot/plotters/dsos.py +294 -0
  47. starplot/plotters/experimental.py +722 -0
  48. starplot/plotters/gradients.py +153 -0
  49. starplot/plotters/legend.py +253 -0
  50. starplot/plotters/milkyway.py +51 -0
  51. starplot/plotters/stars.py +319 -0
  52. starplot/plotters/text.py +802 -0
  53. starplot/profile.py +16 -0
  54. starplot/projections.py +184 -0
  55. starplot/styles/__init__.py +6 -0
  56. starplot/styles/base.py +1344 -0
  57. starplot/styles/ext/antique.yml +175 -0
  58. starplot/styles/ext/blue_dark.yml +163 -0
  59. starplot/styles/ext/blue_gold.yml +147 -0
  60. starplot/styles/ext/blue_light.yml +123 -0
  61. starplot/styles/ext/blue_medium.yml +142 -0
  62. starplot/styles/ext/blue_night.yml +185 -0
  63. starplot/styles/ext/cb_wong.yml +124 -0
  64. starplot/styles/ext/color_print.yml +111 -0
  65. starplot/styles/ext/gradient_presets.yml +158 -0
  66. starplot/styles/ext/grayscale.yml +94 -0
  67. starplot/styles/ext/grayscale_dark.yml +136 -0
  68. starplot/styles/ext/map.yml +12 -0
  69. starplot/styles/ext/nord.yml +158 -0
  70. starplot/styles/ext/optic.yml +20 -0
  71. starplot/styles/ext/publication.yml +8 -0
  72. starplot/styles/extensions.py +129 -0
  73. starplot/styles/fonts-library/gfs-didot/DESCRIPTION.en_us.html +9 -0
  74. starplot/styles/fonts-library/gfs-didot/GFSDidot-Regular.ttf +0 -0
  75. starplot/styles/fonts-library/gfs-didot/METADATA.pb +16 -0
  76. starplot/styles/fonts-library/gfs-didot/OFL.txt +94 -0
  77. starplot/styles/fonts-library/inter/Inter-Bold.ttf +0 -0
  78. starplot/styles/fonts-library/inter/Inter-BoldItalic.ttf +0 -0
  79. starplot/styles/fonts-library/inter/Inter-ExtraBold.ttf +0 -0
  80. starplot/styles/fonts-library/inter/Inter-ExtraLight.ttf +0 -0
  81. starplot/styles/fonts-library/inter/Inter-ExtraLightItalic.ttf +0 -0
  82. starplot/styles/fonts-library/inter/Inter-Italic.ttf +0 -0
  83. starplot/styles/fonts-library/inter/Inter-Light.ttf +0 -0
  84. starplot/styles/fonts-library/inter/Inter-LightItalic.ttf +0 -0
  85. starplot/styles/fonts-library/inter/Inter-Regular.ttf +0 -0
  86. starplot/styles/fonts-library/inter/Inter-SemiBold.ttf +0 -0
  87. starplot/styles/fonts-library/inter/Inter-SemiBoldItalic.ttf +0 -0
  88. starplot/styles/fonts-library/inter/LICENSE.txt +92 -0
  89. starplot/styles/fonts.py +15 -0
  90. starplot/styles/helpers.py +93 -0
  91. starplot/styles/markers.py +308 -0
  92. starplot/utils.py +169 -0
  93. starplot/warnings.py +21 -0
  94. starplot-0.20.5.dist-info/METADATA +146 -0
  95. starplot-0.20.5.dist-info/RECORD +98 -0
  96. starplot-0.20.5.dist-info/WHEEL +4 -0
  97. starplot-0.20.5.dist-info/entry_points.txt +3 -0
  98. starplot-0.20.5.dist-info/licenses/LICENSE +21 -0
@@ -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
+ )
@@ -0,0 +1,7 @@
1
+ # ruff: noqa: F401,F403
2
+
3
+ from .map import MapPlot
4
+ from .horizon import HorizonPlot
5
+ from .zenith import ZenithPlot
6
+ from .optic import OpticPlot
7
+ from .galaxy import GalaxyPlot