starplot 0.15.5__py2.py3-none-any.whl → 0.15.7__py2.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 +1 -1
- starplot/base.py +12 -3
- starplot/data/constellations.py +19 -5
- starplot/data/dsos.py +17 -4
- starplot/data/library/sky.db +0 -0
- starplot/data/stars.py +15 -4
- starplot/models/base.py +60 -14
- starplot/models/constellation.py +14 -26
- starplot/models/dso.py +54 -41
- starplot/models/moon.py +6 -28
- starplot/models/planet.py +2 -18
- starplot/models/star.py +25 -36
- starplot/models/sun.py +2 -18
- starplot/optic.py +3 -1
- starplot/optics.py +81 -40
- starplot/plotters/constellations.py +15 -10
- starplot/plotters/dsos.py +26 -11
- starplot/plotters/stars.py +18 -3
- {starplot-0.15.5.dist-info → starplot-0.15.7.dist-info}/METADATA +3 -2
- {starplot-0.15.5.dist-info → starplot-0.15.7.dist-info}/RECORD +23 -23
- {starplot-0.15.5.dist-info → starplot-0.15.7.dist-info}/WHEEL +1 -1
- {starplot-0.15.5.dist-info → starplot-0.15.7.dist-info}/entry_points.txt +0 -0
- {starplot-0.15.5.dist-info → starplot-0.15.7.dist-info/licenses}/LICENSE +0 -0
starplot/models/star.py
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import math
|
|
2
|
-
from typing import Optional, Union, Iterator
|
|
2
|
+
from typing import Optional, Union, Iterator, Any
|
|
3
3
|
|
|
4
4
|
import numpy as np
|
|
5
|
-
from shapely import Point
|
|
6
5
|
from ibis import _
|
|
6
|
+
from pydantic import field_validator
|
|
7
7
|
|
|
8
|
-
from starplot.models.base import SkyObject
|
|
8
|
+
from starplot.models.base import SkyObject, ShapelyPoint
|
|
9
9
|
from starplot.data.stars import StarCatalog, load as _load_stars
|
|
10
10
|
|
|
11
11
|
|
|
@@ -38,38 +38,20 @@ class Star(SkyObject):
|
|
|
38
38
|
flamsteed: Optional[int] = None
|
|
39
39
|
"""Flamsteed number, if available"""
|
|
40
40
|
|
|
41
|
-
geometry:
|
|
41
|
+
geometry: ShapelyPoint = None
|
|
42
42
|
"""Shapely Point of the star's position. Right ascension coordinates are in degrees (0...360)."""
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
constellation_id: str = None,
|
|
56
|
-
bayer: str = None,
|
|
57
|
-
flamsteed: int = None,
|
|
58
|
-
) -> None:
|
|
59
|
-
super().__init__(ra, dec, constellation_id)
|
|
60
|
-
self.magnitude = magnitude
|
|
61
|
-
self.bv = bv
|
|
62
|
-
self.hip = hip if hip is not None and np.isfinite(hip) else None
|
|
63
|
-
self.name = name
|
|
64
|
-
self.tyc = tyc
|
|
65
|
-
self.ccdm = ccdm
|
|
66
|
-
self.geometry = geometry
|
|
67
|
-
|
|
68
|
-
if bayer:
|
|
69
|
-
self.bayer = bayer
|
|
70
|
-
|
|
71
|
-
if flamsteed and not math.isnan(flamsteed):
|
|
72
|
-
self.flamsteed = int(flamsteed)
|
|
44
|
+
@field_validator("flamsteed", "hip", mode="before")
|
|
45
|
+
@classmethod
|
|
46
|
+
def nan(cls, value: int) -> int:
|
|
47
|
+
if not value or math.isnan(value):
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
return int(value)
|
|
51
|
+
|
|
52
|
+
def model_post_init(self, context: Any) -> None:
|
|
53
|
+
self.bayer = self.bayer or None
|
|
54
|
+
self.hip = self.hip if self.hip is not None and np.isfinite(self.hip) else None
|
|
73
55
|
|
|
74
56
|
def __repr__(self) -> str:
|
|
75
57
|
return f"Star(hip={self.hip}, tyc={self.tyc}, magnitude={self.magnitude}, ra={self.ra}, dec={self.dec})"
|
|
@@ -83,7 +65,7 @@ class Star(SkyObject):
|
|
|
83
65
|
|
|
84
66
|
@classmethod
|
|
85
67
|
def get(
|
|
86
|
-
cls, catalog: StarCatalog = StarCatalog.BIG_SKY_MAG11, **kwargs
|
|
68
|
+
cls, catalog: StarCatalog = StarCatalog.BIG_SKY_MAG11, sql: str = None, **kwargs
|
|
87
69
|
) -> Union["Star", None]:
|
|
88
70
|
"""
|
|
89
71
|
Get a Star, by matching its attributes as specified in `**kwargs`
|
|
@@ -94,6 +76,7 @@ class Star(SkyObject):
|
|
|
94
76
|
|
|
95
77
|
Args:
|
|
96
78
|
catalog: The catalog of stars to use: "big-sky-mag11", or "big-sky" -- see [`StarCatalog`](/reference-data/#starplot.data.stars.StarCatalog) for details
|
|
79
|
+
sql: SQL query for selecting star (table name is "_")
|
|
97
80
|
**kwargs: Attributes on the star you want to match
|
|
98
81
|
|
|
99
82
|
Raises: `ValueError` if more than one star is matched
|
|
@@ -109,6 +92,7 @@ class Star(SkyObject):
|
|
|
109
92
|
df = _load_stars(
|
|
110
93
|
catalog=catalog,
|
|
111
94
|
filters=filters,
|
|
95
|
+
sql=sql,
|
|
112
96
|
).to_pandas()
|
|
113
97
|
|
|
114
98
|
results = [from_tuple(s) for s in df.itertuples()]
|
|
@@ -125,13 +109,17 @@ class Star(SkyObject):
|
|
|
125
109
|
|
|
126
110
|
@classmethod
|
|
127
111
|
def find(
|
|
128
|
-
cls,
|
|
112
|
+
cls,
|
|
113
|
+
where: list = None,
|
|
114
|
+
sql: str = None,
|
|
115
|
+
catalog: StarCatalog = StarCatalog.BIG_SKY_MAG11,
|
|
129
116
|
) -> list["Star"]:
|
|
130
117
|
"""
|
|
131
118
|
Find Stars
|
|
132
119
|
|
|
133
120
|
Args:
|
|
134
121
|
where: A list of expressions that determine which stars to find. See [Selecting Objects](/reference-selecting-objects/) for details.
|
|
122
|
+
sql: SQL query for selecting stars (table name is "_")
|
|
135
123
|
catalog: The catalog of stars to use: "big-sky-mag11", or "big-sky" -- see [`StarCatalog`](/reference-data/#starplot.data.stars.StarCatalog) for details
|
|
136
124
|
|
|
137
125
|
Returns:
|
|
@@ -141,6 +129,7 @@ class Star(SkyObject):
|
|
|
141
129
|
df = _load_stars(
|
|
142
130
|
catalog=catalog,
|
|
143
131
|
filters=where,
|
|
132
|
+
sql=sql,
|
|
144
133
|
).to_pandas()
|
|
145
134
|
|
|
146
135
|
return [from_tuple(s) for s in df.itertuples()]
|
|
@@ -157,10 +146,10 @@ def from_tuple(star: tuple) -> Star:
|
|
|
157
146
|
ccdm=getattr(star, "ccdm", None),
|
|
158
147
|
name=getattr(star, "name", None),
|
|
159
148
|
geometry=star.geometry,
|
|
160
|
-
constellation_id=getattr(star, "constellation", None),
|
|
161
149
|
bayer=getattr(star, "bayer", None),
|
|
162
150
|
flamsteed=getattr(star, "flamsteed", None),
|
|
163
151
|
)
|
|
152
|
+
s._constellation_id = getattr(star, "constellation", None)
|
|
164
153
|
s._row_id = getattr(star, "rowid", None)
|
|
165
154
|
|
|
166
155
|
return s
|
starplot/models/sun.py
CHANGED
|
@@ -2,10 +2,9 @@ from datetime import datetime
|
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
from skyfield.api import Angle, wgs84
|
|
5
|
-
from shapely import Polygon
|
|
6
5
|
|
|
7
6
|
from starplot.data import load
|
|
8
|
-
from starplot.models.base import SkyObject
|
|
7
|
+
from starplot.models.base import SkyObject, ShapelyPolygon
|
|
9
8
|
from starplot.geometry import circle
|
|
10
9
|
from starplot.utils import dt_or_now
|
|
11
10
|
|
|
@@ -22,24 +21,9 @@ class Sun(SkyObject):
|
|
|
22
21
|
apparent_size: float
|
|
23
22
|
"""Apparent size (degrees)"""
|
|
24
23
|
|
|
25
|
-
geometry:
|
|
24
|
+
geometry: ShapelyPolygon = None
|
|
26
25
|
"""Shapely Polygon of the Sun's extent. Right ascension coordinates are in degrees (0...360)."""
|
|
27
26
|
|
|
28
|
-
def __init__(
|
|
29
|
-
self,
|
|
30
|
-
ra: float,
|
|
31
|
-
dec: float,
|
|
32
|
-
name: str,
|
|
33
|
-
dt: datetime,
|
|
34
|
-
apparent_size: float,
|
|
35
|
-
geometry: Polygon = None,
|
|
36
|
-
) -> None:
|
|
37
|
-
super().__init__(ra, dec)
|
|
38
|
-
self.name = name
|
|
39
|
-
self.dt = dt
|
|
40
|
-
self.apparent_size = apparent_size
|
|
41
|
-
self.geometry = geometry
|
|
42
|
-
|
|
43
27
|
@classmethod
|
|
44
28
|
def get(
|
|
45
29
|
cls,
|
starplot/optic.py
CHANGED
|
@@ -220,6 +220,7 @@ class OpticPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
220
220
|
legend_label: str = "Star",
|
|
221
221
|
bayer_labels: bool = False,
|
|
222
222
|
flamsteed_labels: bool = False,
|
|
223
|
+
sql: str = None,
|
|
223
224
|
*args,
|
|
224
225
|
**kwargs,
|
|
225
226
|
):
|
|
@@ -229,7 +230,7 @@ class OpticPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
229
230
|
Args:
|
|
230
231
|
where: A list of expressions that determine which stars to plot. See [Selecting Objects](/reference-selecting-objects/) for details.
|
|
231
232
|
where_labels: A list of expressions that determine which stars are labeled on the plot. See [Selecting Objects](/reference-selecting-objects/) for details.
|
|
232
|
-
catalog: The catalog of stars to use
|
|
233
|
+
catalog: The catalog of stars to use: "big-sky-mag11", or "big-sky" -- see [star catalogs](/data/star-catalogs/) for details
|
|
233
234
|
style: If `None`, then the plot's style for stars will be used
|
|
234
235
|
rasterize: If True, then the stars will be rasterized when plotted, which can speed up exporting to SVG and reduce the file size but with a loss of image quality
|
|
235
236
|
size_fn: Callable for calculating the marker size of each star. If `None`, then the marker style's size will be used.
|
|
@@ -239,6 +240,7 @@ class OpticPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
239
240
|
legend_label: Label for stars in the legend. If `None`, then they will not be in the legend.
|
|
240
241
|
bayer_labels: If True, then Bayer labels for stars will be plotted.
|
|
241
242
|
flamsteed_labels: If True, then Flamsteed number labels for stars will be plotted.
|
|
243
|
+
sql: SQL query for selecting stars (table name is `_`). This query will be applied _after_ any filters in the `where` kwarg.
|
|
242
244
|
"""
|
|
243
245
|
optic_star_multiplier = self.FIELD_OF_VIEW_MAX / self.optic.true_fov
|
|
244
246
|
size_fn_mx = None
|
starplot/optics.py
CHANGED
|
@@ -3,18 +3,15 @@ import math
|
|
|
3
3
|
from abc import ABC, abstractmethod
|
|
4
4
|
|
|
5
5
|
import pyproj
|
|
6
|
-
|
|
7
6
|
from matplotlib import patches
|
|
7
|
+
from pydantic import BaseModel, computed_field
|
|
8
8
|
|
|
9
9
|
from starplot.utils import in_circle
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class Optic(ABC):
|
|
12
|
+
class Optic(BaseModel, ABC):
|
|
13
13
|
"""Abstract class for defining Optics."""
|
|
14
14
|
|
|
15
|
-
def __init__(self) -> "Optic":
|
|
16
|
-
pass
|
|
17
|
-
|
|
18
15
|
def __str__(self):
|
|
19
16
|
return "Optic"
|
|
20
17
|
|
|
@@ -70,18 +67,34 @@ class Scope(Optic):
|
|
|
70
67
|
Scope: A new instance of a Scope optic
|
|
71
68
|
"""
|
|
72
69
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
70
|
+
focal_length: float
|
|
71
|
+
"""Focal length (mm) of the telescope"""
|
|
72
|
+
|
|
73
|
+
eyepiece_focal_length: float
|
|
74
|
+
"""Focal length (mm) of the eyepiece"""
|
|
75
|
+
|
|
76
|
+
eyepiece_fov: float
|
|
77
|
+
"""Field of view (degrees) of the eyepiece"""
|
|
78
|
+
|
|
79
|
+
@computed_field
|
|
80
|
+
@property
|
|
81
|
+
def magnification(self) -> float:
|
|
82
|
+
"""Magnification calculated from the telescope's focal length and eyepiece focal length"""
|
|
83
|
+
return self.focal_length / self.eyepiece_focal_length
|
|
84
|
+
|
|
85
|
+
@computed_field
|
|
86
|
+
@property
|
|
87
|
+
def true_fov(self) -> float:
|
|
88
|
+
"""True field of view of telescope"""
|
|
89
|
+
return self.eyepiece_fov / self.magnification
|
|
90
|
+
|
|
91
|
+
@computed_field
|
|
92
|
+
@property
|
|
93
|
+
def radius(self) -> float:
|
|
94
|
+
return self._compute_radius(self.true_fov / 2)
|
|
82
95
|
|
|
83
96
|
def __str__(self):
|
|
84
|
-
return f"{self.focal_length}mm w/ {self.eyepiece_focal_length}mm ({self.magnification:.0f}x) @ {self.eyepiece_fov:.0f}\N{DEGREE SIGN} = {self.true_fov:.2f}\N{DEGREE SIGN} TFOV"
|
|
97
|
+
return f"{self.focal_length:.0f}mm w/ {self.eyepiece_focal_length:.0f}mm ({self.magnification:.0f}x) @ {self.eyepiece_fov:.0f}\N{DEGREE SIGN} = {self.true_fov:.2f}\N{DEGREE SIGN} TFOV"
|
|
85
98
|
|
|
86
99
|
@property
|
|
87
100
|
def xlim(self):
|
|
@@ -172,14 +185,25 @@ class Binoculars(Optic):
|
|
|
172
185
|
|
|
173
186
|
"""
|
|
174
187
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
188
|
+
magnification: float
|
|
189
|
+
"""Magnification of the binoculars"""
|
|
190
|
+
|
|
191
|
+
fov: float
|
|
192
|
+
"""Apparent field of view of the binoculars"""
|
|
193
|
+
|
|
194
|
+
@computed_field
|
|
195
|
+
@property
|
|
196
|
+
def true_fov(self) -> float:
|
|
197
|
+
"""True field of view of binoculars"""
|
|
198
|
+
return self.fov / self.magnification
|
|
199
|
+
|
|
200
|
+
@computed_field
|
|
201
|
+
@property
|
|
202
|
+
def radius(self) -> float:
|
|
203
|
+
return self._compute_radius(self.true_fov / 2)
|
|
180
204
|
|
|
181
205
|
def __str__(self):
|
|
182
|
-
return f"{self.magnification}x @ {self.
|
|
206
|
+
return f"{self.magnification:.0f}x @ {self.fov:.0f}\N{DEGREE SIGN} = {self.true_fov}\N{DEGREE SIGN}"
|
|
183
207
|
|
|
184
208
|
@property
|
|
185
209
|
def xlim(self):
|
|
@@ -225,39 +249,56 @@ class Camera(Optic):
|
|
|
225
249
|
sensor_height: Height of camera sensor (mm)
|
|
226
250
|
sensor_width: Width of camera sensor (mm)
|
|
227
251
|
lens_focal_length: Focal length of camera lens (mm)
|
|
228
|
-
rotation: Angle (degrees) to rotate camera
|
|
252
|
+
rotation: Angle (degrees) to rotate camera, defaults to 0
|
|
229
253
|
|
|
230
254
|
Returns:
|
|
231
255
|
Camera: A new instance of a Camera optic
|
|
232
256
|
|
|
233
257
|
"""
|
|
234
258
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
259
|
+
sensor_height: float
|
|
260
|
+
"""Height (mm) of camera's sensor"""
|
|
261
|
+
|
|
262
|
+
sensor_width: float
|
|
263
|
+
"""Width (mm) of camera's sensor"""
|
|
264
|
+
|
|
265
|
+
lens_focal_length: float
|
|
266
|
+
"""Focal length (mm) of the camera's lens"""
|
|
267
|
+
|
|
268
|
+
rotation: float = 0
|
|
269
|
+
"""Angle (degrees) to rotate the camera"""
|
|
270
|
+
|
|
271
|
+
@computed_field
|
|
272
|
+
@property
|
|
273
|
+
def true_fov_x(self) -> float:
|
|
274
|
+
return 2 * math.degrees(
|
|
247
275
|
math.atan(self.sensor_width / (2 * self.lens_focal_length))
|
|
248
276
|
)
|
|
249
|
-
|
|
277
|
+
|
|
278
|
+
@computed_field
|
|
279
|
+
@property
|
|
280
|
+
def true_fov_y(self) -> float:
|
|
281
|
+
return 2 * math.degrees(
|
|
250
282
|
math.atan(self.sensor_height / (2 * self.lens_focal_length))
|
|
251
283
|
)
|
|
252
|
-
self.true_fov = max(self.true_fov_x, self.true_fov_y)
|
|
253
284
|
|
|
254
|
-
|
|
255
|
-
|
|
285
|
+
@computed_field
|
|
286
|
+
@property
|
|
287
|
+
def true_fov(self) -> float:
|
|
288
|
+
return max(self.true_fov_x, self.true_fov_y)
|
|
289
|
+
|
|
290
|
+
@computed_field
|
|
291
|
+
@property
|
|
292
|
+
def radius_x(self) -> float:
|
|
293
|
+
return self._compute_radius(self.true_fov_x / 2)
|
|
256
294
|
|
|
257
|
-
|
|
295
|
+
@computed_field
|
|
296
|
+
@property
|
|
297
|
+
def radius_y(self) -> float:
|
|
298
|
+
return self._compute_radius(self.true_fov_y / 2)
|
|
258
299
|
|
|
259
300
|
def __str__(self):
|
|
260
|
-
return f"{self.sensor_width}x{self.sensor_height} w/ {self.lens_focal_length}mm lens = {self.true_fov_x:.2f}\N{DEGREE SIGN} x {self.true_fov_y:.2f}\N{DEGREE SIGN}"
|
|
301
|
+
return f"{self.sensor_width}x{self.sensor_height} w/ {self.lens_focal_length:.0f}mm lens = {self.true_fov_x:.2f}\N{DEGREE SIGN} x {self.true_fov_y:.2f}\N{DEGREE SIGN}"
|
|
261
302
|
|
|
262
303
|
@property
|
|
263
304
|
def xlim(self):
|
|
@@ -12,9 +12,9 @@ from starplot.data import constellations as condata, constellation_lines as conl
|
|
|
12
12
|
from starplot.data.stars import load as load_stars, StarCatalog
|
|
13
13
|
from starplot.data.constellations import (
|
|
14
14
|
CONSTELLATIONS_FULL_NAMES,
|
|
15
|
-
CONSTELLATION_HIP_IDS,
|
|
16
15
|
)
|
|
17
16
|
from starplot.data.constellation_stars import CONSTELLATION_HIPS
|
|
17
|
+
from starplot.models import Star
|
|
18
18
|
from starplot.models.constellation import from_tuple as constellation_from_tuple
|
|
19
19
|
from starplot.projections import Projection
|
|
20
20
|
from starplot.profile import profile
|
|
@@ -65,6 +65,7 @@ class ConstellationPlotterMixin:
|
|
|
65
65
|
self,
|
|
66
66
|
style: LineStyle = None,
|
|
67
67
|
where: list = None,
|
|
68
|
+
sql: str = None,
|
|
68
69
|
):
|
|
69
70
|
"""Plots the constellation lines **only**. To plot constellation borders and/or labels, see separate functions for them.
|
|
70
71
|
|
|
@@ -73,6 +74,7 @@ class ConstellationPlotterMixin:
|
|
|
73
74
|
Args:
|
|
74
75
|
style: Styling of the constellations. If None, then the plot's style (specified when creating the plot) will be used
|
|
75
76
|
where: A list of expressions that determine which constellations to plot. See [Selecting Objects](/reference-selecting-objects/) for details.
|
|
77
|
+
sql: SQL query for selecting constellations (table name is `_`). This query will be applied _after_ any filters in the `where` kwarg.
|
|
76
78
|
"""
|
|
77
79
|
self.logger.debug("Plotting constellation lines...")
|
|
78
80
|
|
|
@@ -80,7 +82,7 @@ class ConstellationPlotterMixin:
|
|
|
80
82
|
ctr = 0
|
|
81
83
|
|
|
82
84
|
extent = self._extent_mask()
|
|
83
|
-
results = condata.load(extent=extent, filters=where)
|
|
85
|
+
results = condata.load(extent=extent, filters=where, sql=sql)
|
|
84
86
|
constellations_df = results.to_pandas()
|
|
85
87
|
|
|
86
88
|
if constellations_df.empty:
|
|
@@ -262,11 +264,17 @@ class ConstellationPlotterMixin:
|
|
|
262
264
|
self.ax.add_collection(line_collection)
|
|
263
265
|
|
|
264
266
|
def _constellation_labels_auto(self, style, labels, settings):
|
|
267
|
+
hips = []
|
|
268
|
+
for c in self.objects.constellations:
|
|
269
|
+
hips.extend(c.star_hip_ids)
|
|
270
|
+
|
|
271
|
+
all_constellation_stars = Star.find(where=[_.hip.isin(hips)])
|
|
272
|
+
|
|
265
273
|
for constellation in self.objects.constellations:
|
|
266
274
|
constellation_line_stars = [
|
|
267
275
|
s
|
|
268
|
-
for s in
|
|
269
|
-
if s.hip in
|
|
276
|
+
for s in all_constellation_stars
|
|
277
|
+
if s.hip in constellation.star_hip_ids
|
|
270
278
|
]
|
|
271
279
|
if not constellation_line_stars:
|
|
272
280
|
continue
|
|
@@ -302,10 +310,11 @@ class ConstellationPlotterMixin:
|
|
|
302
310
|
text = labels.get(con.lower())
|
|
303
311
|
self.text(
|
|
304
312
|
text,
|
|
305
|
-
ra,
|
|
313
|
+
ra * 15,
|
|
306
314
|
dec,
|
|
307
315
|
style,
|
|
308
316
|
hide_on_collision=self.hide_colliding_labels,
|
|
317
|
+
remove_on_constellation_collision=False,
|
|
309
318
|
gid="constellations-label-name",
|
|
310
319
|
)
|
|
311
320
|
|
|
@@ -319,7 +328,7 @@ class ConstellationPlotterMixin:
|
|
|
319
328
|
auto_adjust_settings: dict = DEFAULT_AUTO_ADJUST_SETTINGS,
|
|
320
329
|
):
|
|
321
330
|
"""
|
|
322
|
-
Plots constellation labels.
|
|
331
|
+
Plots constellation labels for all constellations that have been plotted. This means you must plot the constellations before plotting their labels.
|
|
323
332
|
|
|
324
333
|
It's good to plot these last because they're area-based labels (vs point-based, like for star names), and area-based labels have more freedom to move around. If you plot area-based labels first, then it would limit the available space for point-based labels.
|
|
325
334
|
|
|
@@ -328,10 +337,6 @@ class ConstellationPlotterMixin:
|
|
|
328
337
|
labels: A dictionary where the keys are each constellation's 3-letter IAU abbreviation, and the values are how the constellation will be labeled on the plot.
|
|
329
338
|
auto_adjust: If True (the default), then labels will be automatically adjusted to avoid collisions with other labels and stars **Important: you must plot stars and constellations first for this to work**. This uses a fairly simple method: for each constellation it finds the centroid of all plotted constellation stars with lines and then generates random points in the constellation boundary starting at the centroid and then progressively increasing the distance from the centroid.
|
|
330
339
|
auto_adjust_settings: Optional settings for the auto adjustment algorithm.
|
|
331
|
-
|
|
332
|
-
TODO:
|
|
333
|
-
make this work without plotting constellations first
|
|
334
|
-
|
|
335
340
|
"""
|
|
336
341
|
|
|
337
342
|
if auto_adjust:
|
starplot/plotters/dsos.py
CHANGED
|
@@ -44,7 +44,7 @@ class DsoPlotterMixin:
|
|
|
44
44
|
This is just a small wrapper around the `dsos()` function, so any `kwargs` will be passed through.
|
|
45
45
|
"""
|
|
46
46
|
where = kwargs.pop("where", [])
|
|
47
|
-
where.append(_.type == DsoType.OPEN_CLUSTER)
|
|
47
|
+
where.append(_.type == DsoType.OPEN_CLUSTER.value)
|
|
48
48
|
self.dsos(where=where, **kwargs)
|
|
49
49
|
|
|
50
50
|
def globular_clusters(self, **kwargs):
|
|
@@ -54,7 +54,7 @@ class DsoPlotterMixin:
|
|
|
54
54
|
This is just a small wrapper around the `dsos()` function, so any `kwargs` will be passed through.
|
|
55
55
|
"""
|
|
56
56
|
where = kwargs.pop("where", [])
|
|
57
|
-
where.append(_.type == DsoType.GLOBULAR_CLUSTER)
|
|
57
|
+
where.append(_.type == DsoType.GLOBULAR_CLUSTER.value)
|
|
58
58
|
self.dsos(where=where, **kwargs)
|
|
59
59
|
|
|
60
60
|
def galaxies(self, **kwargs):
|
|
@@ -68,9 +68,9 @@ class DsoPlotterMixin:
|
|
|
68
68
|
This is just a small wrapper around the `dsos()` function, so any `kwargs` will be passed through.
|
|
69
69
|
"""
|
|
70
70
|
galaxy_types = [
|
|
71
|
-
DsoType.GALAXY,
|
|
72
|
-
DsoType.GALAXY_PAIR,
|
|
73
|
-
DsoType.GALAXY_TRIPLET,
|
|
71
|
+
DsoType.GALAXY.value,
|
|
72
|
+
DsoType.GALAXY_PAIR.value,
|
|
73
|
+
DsoType.GALAXY_TRIPLET.value,
|
|
74
74
|
]
|
|
75
75
|
where = kwargs.pop("where", [])
|
|
76
76
|
where.append(_.type.isin(galaxy_types))
|
|
@@ -85,15 +85,19 @@ class DsoPlotterMixin:
|
|
|
85
85
|
- Emission Nebula
|
|
86
86
|
- Star Cluster Nebula
|
|
87
87
|
- Reflection Nebula
|
|
88
|
+
- HII Ionized Regions
|
|
89
|
+
|
|
90
|
+
* Note that this does NOT plot dark nebulae
|
|
88
91
|
|
|
89
92
|
This is just a small wrapper around the `dsos()` function, so any `kwargs` will be passed through.
|
|
90
93
|
"""
|
|
91
94
|
nebula_types = [
|
|
92
|
-
DsoType.NEBULA,
|
|
93
|
-
DsoType.PLANETARY_NEBULA,
|
|
94
|
-
DsoType.EMISSION_NEBULA,
|
|
95
|
-
DsoType.STAR_CLUSTER_NEBULA,
|
|
96
|
-
DsoType.REFLECTION_NEBULA,
|
|
95
|
+
DsoType.NEBULA.value,
|
|
96
|
+
DsoType.PLANETARY_NEBULA.value,
|
|
97
|
+
DsoType.EMISSION_NEBULA.value,
|
|
98
|
+
DsoType.STAR_CLUSTER_NEBULA.value,
|
|
99
|
+
DsoType.REFLECTION_NEBULA.value,
|
|
100
|
+
DsoType.HII_IONIZED_REGION.value,
|
|
97
101
|
]
|
|
98
102
|
where = kwargs.pop("where", [])
|
|
99
103
|
where.append(_.type.isin(nebula_types))
|
|
@@ -109,6 +113,8 @@ class DsoPlotterMixin:
|
|
|
109
113
|
legend_labels: Mapping[DsoType, str] = DSO_LEGEND_LABELS,
|
|
110
114
|
alpha_fn: Callable[[DSO], float] = None,
|
|
111
115
|
label_fn: Callable[[DSO], str] = None,
|
|
116
|
+
sql: str = None,
|
|
117
|
+
sql_labels: str = None,
|
|
112
118
|
):
|
|
113
119
|
"""
|
|
114
120
|
Plots Deep Sky Objects (DSOs), from OpenNGC
|
|
@@ -121,6 +127,8 @@ class DsoPlotterMixin:
|
|
|
121
127
|
legend_labels: A dictionary that maps a `DsoType` to the legend label that'll be plotted for that type of DSO. If you want to hide all DSO legend labels, then set this arg to `None`.
|
|
122
128
|
alpha_fn: Callable for calculating the alpha value (aka "opacity") of each DSO. If `None`, then the marker style's alpha will be used.
|
|
123
129
|
label_fn: Callable for determining the label of each DSO. If `None`, then the names in the `labels` kwarg will be used.
|
|
130
|
+
sql: SQL query for selecting DSOs (table name is `_`). This query will be applied _after_ any filters in the `where` kwarg.
|
|
131
|
+
sql_labels: SQL query for selecting DSOs that will be labeled (table name is `_`). Applied _after_ any filters in the `where_labels` kwarg.
|
|
124
132
|
"""
|
|
125
133
|
|
|
126
134
|
# TODO: add kwarg styles
|
|
@@ -139,12 +147,19 @@ class DsoPlotterMixin:
|
|
|
139
147
|
legend_labels = {**DSO_LEGEND_LABELS, **legend_labels}
|
|
140
148
|
|
|
141
149
|
extent = self._extent_mask()
|
|
142
|
-
dso_results = load(extent=extent, filters=where)
|
|
150
|
+
dso_results = load(extent=extent, filters=where, sql=sql)
|
|
143
151
|
|
|
144
152
|
dso_results_labeled = dso_results
|
|
145
153
|
for f in where_labels:
|
|
146
154
|
dso_results_labeled = dso_results_labeled.filter(f)
|
|
147
155
|
|
|
156
|
+
if sql_labels:
|
|
157
|
+
result = (
|
|
158
|
+
dso_results_labeled.alias("_").sql(sql_labels).select("sk").execute()
|
|
159
|
+
)
|
|
160
|
+
skids = result["sk"].to_list()
|
|
161
|
+
dso_results_labeled = dso_results_labeled.filter(_.sk.isin(skids))
|
|
162
|
+
|
|
148
163
|
label_row_ids = dso_results_labeled.to_pandas()["rowid"].tolist()
|
|
149
164
|
|
|
150
165
|
results_df = dso_results.to_pandas()
|
starplot/plotters/stars.py
CHANGED
|
@@ -2,6 +2,7 @@ from typing import Callable, Mapping
|
|
|
2
2
|
|
|
3
3
|
import rtree
|
|
4
4
|
import numpy as np
|
|
5
|
+
from ibis import _ as ibis_table
|
|
5
6
|
from skyfield.api import Star as SkyfieldStar, wgs84
|
|
6
7
|
|
|
7
8
|
from starplot import callables
|
|
@@ -13,13 +14,14 @@ from starplot.profile import profile
|
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
class StarPlotterMixin:
|
|
16
|
-
def _load_stars(self, catalog, filters=None):
|
|
17
|
+
def _load_stars(self, catalog, filters=None, sql=None):
|
|
17
18
|
extent = self._extent_mask()
|
|
18
19
|
|
|
19
20
|
return stars.load(
|
|
20
21
|
extent=extent,
|
|
21
22
|
catalog=catalog,
|
|
22
23
|
filters=filters,
|
|
24
|
+
sql=sql,
|
|
23
25
|
)
|
|
24
26
|
|
|
25
27
|
def _scatter_stars(self, ras, decs, sizes, alphas, colors, style=None, **kwargs):
|
|
@@ -165,6 +167,8 @@ class StarPlotterMixin:
|
|
|
165
167
|
legend_label: str = "Star",
|
|
166
168
|
bayer_labels: bool = False,
|
|
167
169
|
flamsteed_labels: bool = False,
|
|
170
|
+
sql: str = None,
|
|
171
|
+
sql_labels: str = None,
|
|
168
172
|
*args,
|
|
169
173
|
**kwargs,
|
|
170
174
|
):
|
|
@@ -180,7 +184,7 @@ class StarPlotterMixin:
|
|
|
180
184
|
Args:
|
|
181
185
|
where: A list of expressions that determine which stars to plot. See [Selecting Objects](/reference-selecting-objects/) for details.
|
|
182
186
|
where_labels: A list of expressions that determine which stars are labeled on the plot (this includes all labels: name, Bayer, and Flamsteed). If you want to hide **all** labels, then set this arg to `[False]`. See [Selecting Objects](/reference-selecting-objects/) for details.
|
|
183
|
-
catalog: The catalog of stars to use: "big-sky-mag11", or "big-sky" -- see [
|
|
187
|
+
catalog: The catalog of stars to use: "big-sky-mag11", or "big-sky" -- see [star catalogs](/data/star-catalogs/) for details
|
|
184
188
|
style: If `None`, then the plot's style for stars will be used
|
|
185
189
|
size_fn: Callable for calculating the marker size of each star. If `None`, then the marker style's size will be used.
|
|
186
190
|
alpha_fn: Callable for calculating the alpha value (aka "opacity") of each star. If `None`, then the marker style's alpha will be used.
|
|
@@ -190,6 +194,8 @@ class StarPlotterMixin:
|
|
|
190
194
|
legend_label: Label for stars in the legend. If `None`, then they will not be in the legend.
|
|
191
195
|
bayer_labels: If True, then Bayer labels for stars will be plotted.
|
|
192
196
|
flamsteed_labels: If True, then Flamsteed number labels for stars will be plotted.
|
|
197
|
+
sql: SQL query for selecting stars (table name is `_`). This query will be applied _after_ any filters in the `where` kwarg.
|
|
198
|
+
sql_labels: SQL query for selecting stars that will be labeled (table name is `_`). Applied _after_ any filters in the `where_labels` kwarg.
|
|
193
199
|
"""
|
|
194
200
|
|
|
195
201
|
# fallback to style if callables are None
|
|
@@ -205,12 +211,21 @@ class StarPlotterMixin:
|
|
|
205
211
|
stars_to_index = []
|
|
206
212
|
labels = labels or {}
|
|
207
213
|
|
|
208
|
-
star_results = self._load_stars(catalog, filters=where)
|
|
214
|
+
star_results = self._load_stars(catalog, filters=where, sql=sql)
|
|
209
215
|
|
|
210
216
|
star_results_labeled = star_results
|
|
211
217
|
for f in where_labels:
|
|
212
218
|
star_results_labeled = star_results_labeled.filter(f)
|
|
213
219
|
|
|
220
|
+
if sql_labels:
|
|
221
|
+
result = (
|
|
222
|
+
star_results_labeled.alias("_").sql(sql_labels).select("sk").execute()
|
|
223
|
+
)
|
|
224
|
+
skids = result["sk"].to_list()
|
|
225
|
+
star_results_labeled = star_results_labeled.filter(
|
|
226
|
+
ibis_table.sk.isin(skids)
|
|
227
|
+
)
|
|
228
|
+
|
|
214
229
|
label_row_ids = star_results_labeled.to_pandas()["rowid"].tolist()
|
|
215
230
|
|
|
216
231
|
stars_df = star_results.to_pandas()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: starplot
|
|
3
|
-
Version: 0.15.
|
|
3
|
+
Version: 0.15.7
|
|
4
4
|
Summary: Star charts and maps of the sky
|
|
5
5
|
Keywords: astronomy,stars,charts,maps,constellations,sky,plotting
|
|
6
6
|
Author-email: Steve Berardi <hello@steveberardi.com>
|
|
@@ -10,6 +10,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
10
10
|
Classifier: Programming Language :: Python :: 3.10
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.11
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
License-File: LICENSE
|
|
13
14
|
Requires-Dist: matplotlib >= 3.8.0
|
|
14
15
|
Requires-Dist: numpy >= 1.26.2
|
|
15
16
|
Requires-Dist: pandas >= 1.4.0
|