starplot 0.18.3__py2.py3-none-any.whl → 0.19.0__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 +33 -27
- starplot/data/__init__.py +3 -5
- starplot/data/catalogs.py +23 -11
- starplot/data/db.py +1 -7
- starplot/models/__init__.py +3 -1
- starplot/models/constellation.py +7 -1
- starplot/models/milky_way.py +30 -0
- starplot/models/observer.py +11 -2
- starplot/plots/__init__.py +6 -0
- starplot/{base.py → plots/base.py} +74 -439
- starplot/{horizon.py → plots/horizon.py} +12 -10
- starplot/{map.py → plots/map.py} +10 -7
- starplot/{optic.py → plots/optic.py} +21 -30
- starplot/{zenith.py → plots/zenith.py} +31 -8
- starplot/plotters/__init__.py +9 -7
- starplot/plotters/arrow.py +1 -1
- starplot/plotters/constellations.py +46 -61
- starplot/plotters/dsos.py +33 -16
- starplot/plotters/experimental.py +0 -1
- starplot/plotters/milkyway.py +15 -6
- starplot/plotters/stars.py +19 -36
- starplot/plotters/text.py +464 -0
- starplot/styles/__init__.py +4 -4
- starplot/styles/base.py +1 -13
- {starplot-0.18.3.dist-info → starplot-0.19.0.dist-info}/METADATA +2 -1
- {starplot-0.18.3.dist-info → starplot-0.19.0.dist-info}/RECORD +29 -27
- starplot/data/library/sky.db +0 -0
- {starplot-0.18.3.dist-info → starplot-0.19.0.dist-info}/WHEEL +0 -0
- {starplot-0.18.3.dist-info → starplot-0.19.0.dist-info}/entry_points.txt +0 -0
- {starplot-0.18.3.dist-info → starplot-0.19.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -9,7 +9,7 @@ from matplotlib.ticker import FixedLocator, FuncFormatter
|
|
|
9
9
|
from skyfield.api import wgs84, Star as SkyfieldStar
|
|
10
10
|
from shapely import Point, Polygon, MultiPolygon
|
|
11
11
|
from starplot.coordinates import CoordinateSystem
|
|
12
|
-
from starplot.base import BasePlot, DPI
|
|
12
|
+
from starplot.plots.base import BasePlot, DPI
|
|
13
13
|
from starplot.mixins import ExtentMaskMixin
|
|
14
14
|
from starplot.models.observer import Observer
|
|
15
15
|
from starplot.plotters import (
|
|
@@ -21,6 +21,7 @@ from starplot.plotters import (
|
|
|
21
21
|
LegendPlotterMixin,
|
|
22
22
|
ArrowPlotterMixin,
|
|
23
23
|
)
|
|
24
|
+
from starplot.plotters.text import CollisionHandler
|
|
24
25
|
from starplot.styles import (
|
|
25
26
|
PlotStyle,
|
|
26
27
|
extensions,
|
|
@@ -58,15 +59,14 @@ class HorizonPlot(
|
|
|
58
59
|
"""Creates a new horizon plot.
|
|
59
60
|
|
|
60
61
|
Args:
|
|
61
|
-
|
|
62
|
-
lon: Longitude of observer's location
|
|
62
|
+
|
|
63
63
|
altitude: Tuple of altitude range to plot (min, max)
|
|
64
64
|
azimuth: Tuple of azimuth range to plot (min, max)
|
|
65
|
-
|
|
65
|
+
observer: Observer instance which specifies a time and place. Defaults to `Observer()`
|
|
66
66
|
ephemeris: Ephemeris to use for calculating planet positions (see [Skyfield's documentation](https://rhodesmill.org/skyfield/planets.html) for details)
|
|
67
|
-
style: Styling for the plot (colors, sizes, fonts, etc)
|
|
67
|
+
style: Styling for the plot (colors, sizes, fonts, etc). If `None`, it defaults to `PlotStyle()`
|
|
68
68
|
resolution: Size (in pixels) of largest dimension of the map
|
|
69
|
-
|
|
69
|
+
collision_handler: Default [CollisionHandler][starplot.CollisionHandler] for the plot that describes what to do on label collisions with other labels, markers, etc.
|
|
70
70
|
scale: Scaling factor that will be applied to all relevant sizes in styles (e.g. font size, marker size, line widths, etc). For example, if you want to make everything 2x bigger, then set scale to 2.
|
|
71
71
|
autoscale: If True, then the scale will be automatically set based on resolution
|
|
72
72
|
suppress_warnings: If True (the default), then all warnings will be suppressed
|
|
@@ -85,23 +85,25 @@ class HorizonPlot(
|
|
|
85
85
|
self,
|
|
86
86
|
altitude: tuple[float, float],
|
|
87
87
|
azimuth: tuple[float, float],
|
|
88
|
-
observer: Observer =
|
|
88
|
+
observer: Observer = None,
|
|
89
89
|
ephemeris: str = "de421.bsp",
|
|
90
90
|
style: PlotStyle = DEFAULT_HORIZON_STYLE,
|
|
91
91
|
resolution: int = 4096,
|
|
92
|
-
|
|
92
|
+
collision_handler: CollisionHandler = None,
|
|
93
93
|
scale: float = 1.0,
|
|
94
94
|
autoscale: bool = False,
|
|
95
95
|
suppress_warnings: bool = True,
|
|
96
96
|
*args,
|
|
97
97
|
**kwargs,
|
|
98
98
|
) -> "HorizonPlot":
|
|
99
|
+
observer = observer or Observer()
|
|
100
|
+
|
|
99
101
|
super().__init__(
|
|
100
102
|
observer,
|
|
101
103
|
ephemeris,
|
|
102
104
|
style,
|
|
103
105
|
resolution,
|
|
104
|
-
|
|
106
|
+
collision_handler=collision_handler,
|
|
105
107
|
scale=scale,
|
|
106
108
|
autoscale=autoscale,
|
|
107
109
|
suppress_warnings=suppress_warnings,
|
|
@@ -160,7 +162,7 @@ class HorizonPlot(
|
|
|
160
162
|
# import geopandas as gpd
|
|
161
163
|
|
|
162
164
|
# Skyfield needs these columns
|
|
163
|
-
df["ra_hours"], df["dec_degrees"] = (df.ra / 15, df.dec)
|
|
165
|
+
# df["ra_hours"], df["dec_degrees"] = (df.ra / 15, df.dec)
|
|
164
166
|
|
|
165
167
|
stars_apparent = self.observe(SkyfieldStar.from_dataframe(df)).apparent()
|
|
166
168
|
nearby_stars_alt, nearby_stars_az, _ = stars_apparent.altaz()
|
starplot/{map.py → plots/map.py}
RENAMED
|
@@ -12,7 +12,7 @@ import numpy as np
|
|
|
12
12
|
|
|
13
13
|
from starplot.coordinates import CoordinateSystem
|
|
14
14
|
from starplot import geod
|
|
15
|
-
from starplot.base import BasePlot, DPI
|
|
15
|
+
from starplot.plots.base import BasePlot, DPI
|
|
16
16
|
from starplot.mixins import ExtentMaskMixin
|
|
17
17
|
from starplot.models.observer import Observer
|
|
18
18
|
from starplot.plotters import (
|
|
@@ -24,6 +24,7 @@ from starplot.plotters import (
|
|
|
24
24
|
GradientBackgroundMixin,
|
|
25
25
|
ArrowPlotterMixin,
|
|
26
26
|
)
|
|
27
|
+
from starplot.plotters.text import CollisionHandler
|
|
27
28
|
from starplot.projections import StereoNorth, StereoSouth, ProjectionBase
|
|
28
29
|
from starplot.styles import (
|
|
29
30
|
ObjectStyle,
|
|
@@ -57,11 +58,11 @@ class MapPlot(
|
|
|
57
58
|
ra_max: Maximum right ascension of the map's extent, in degrees (0...360)
|
|
58
59
|
dec_min: Minimum declination of the map's extent, in degrees (-90...90)
|
|
59
60
|
dec_max: Maximum declination of the map's extent, in degrees (-90...90)
|
|
60
|
-
observer: Observer instance which specifies a time and place
|
|
61
|
+
observer: Observer instance which specifies a time and place. Defaults to an observer at epoch J2000
|
|
61
62
|
ephemeris: Ephemeris to use for calculating planet positions (see [Skyfield's documentation](https://rhodesmill.org/skyfield/planets.html) for details)
|
|
62
|
-
style: Styling for the plot (colors, sizes, fonts, etc)
|
|
63
|
+
style: Styling for the plot (colors, sizes, fonts, etc). If `None`, it defaults to `PlotStyle()`
|
|
63
64
|
resolution: Size (in pixels) of largest dimension of the map
|
|
64
|
-
|
|
65
|
+
collision_handler: Default [CollisionHandler][starplot.CollisionHandler] for the plot that describes what to do on label collisions with other labels, markers, etc.
|
|
65
66
|
clip_path: An optional Shapely Polygon that specifies the clip path of the plot -- only objects inside the polygon will be plotted. If `None` (the default), then the clip path will be the extent of the map you specified with the RA/DEC parameters.
|
|
66
67
|
scale: Scaling factor that will be applied to all sizes in styles (e.g. font size, marker size, line widths, etc). For example, if you want to make everything 2x bigger, then set the scale to 2. At `scale=1` and `resolution=4096` (the default), all sizes are optimized visually for a map that covers 1-3 constellations. So, if you're creating a plot of a _larger_ extent, then it'd probably be good to decrease the scale (i.e. make everything smaller) -- and _increase_ the scale if you're plotting a very small area.
|
|
67
68
|
autoscale: If True, then the scale will be set automatically based on resolution.
|
|
@@ -82,11 +83,11 @@ class MapPlot(
|
|
|
82
83
|
ra_max: float = 360,
|
|
83
84
|
dec_min: float = -90,
|
|
84
85
|
dec_max: float = 90,
|
|
85
|
-
observer: Observer =
|
|
86
|
+
observer: Observer = None,
|
|
86
87
|
ephemeris: str = "de421.bsp",
|
|
87
88
|
style: PlotStyle = DEFAULT_MAP_STYLE,
|
|
88
89
|
resolution: int = 4096,
|
|
89
|
-
|
|
90
|
+
collision_handler: CollisionHandler = None,
|
|
90
91
|
clip_path: Polygon = None,
|
|
91
92
|
scale: float = 1.0,
|
|
92
93
|
autoscale: bool = False,
|
|
@@ -94,12 +95,14 @@ class MapPlot(
|
|
|
94
95
|
*args,
|
|
95
96
|
**kwargs,
|
|
96
97
|
) -> "MapPlot":
|
|
98
|
+
observer = observer or Observer.at_epoch(2000)
|
|
99
|
+
|
|
97
100
|
super().__init__(
|
|
98
101
|
observer,
|
|
99
102
|
ephemeris,
|
|
100
103
|
style,
|
|
101
104
|
resolution,
|
|
102
|
-
|
|
105
|
+
collision_handler=collision_handler,
|
|
103
106
|
scale=scale,
|
|
104
107
|
autoscale=autoscale,
|
|
105
108
|
suppress_warnings=suppress_warnings,
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
from typing import Callable
|
|
1
|
+
from typing import Callable
|
|
2
2
|
|
|
3
3
|
from cartopy import crs as ccrs
|
|
4
4
|
from matplotlib import pyplot as plt, patches, path
|
|
5
5
|
from skyfield.api import wgs84, Star as SkyfieldStar
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
from starplot import callables, geod
|
|
9
|
-
from starplot.
|
|
9
|
+
from starplot.coordinates import CoordinateSystem
|
|
10
|
+
from starplot.plots.base import BasePlot, DPI
|
|
10
11
|
from starplot.data.catalogs import Catalog, BIG_SKY_MAG11
|
|
11
12
|
from starplot.mixins import ExtentMaskMixin
|
|
12
13
|
from starplot.models import Star, Optic, Camera
|
|
@@ -27,6 +28,7 @@ from starplot.styles import (
|
|
|
27
28
|
GradientDirection,
|
|
28
29
|
)
|
|
29
30
|
from starplot.utils import azimuth_to_string
|
|
31
|
+
from starplot.plotters.text import CollisionHandler
|
|
30
32
|
|
|
31
33
|
DEFAULT_OPTIC_STYLE = PlotStyle().extend(extensions.OPTIC)
|
|
32
34
|
|
|
@@ -42,16 +44,14 @@ class OpticPlot(
|
|
|
42
44
|
"""Creates a new optic plot.
|
|
43
45
|
|
|
44
46
|
Args:
|
|
45
|
-
optic: Optic instance that defines optical parameters
|
|
46
47
|
ra: Right ascension of target center, in degrees (0...360)
|
|
47
48
|
dec: Declination of target center, in degrees (-90...90)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
dt: Date/time of observation (*must be timezone-aware*). Default = current UTC time.
|
|
49
|
+
optic: Optic instance that defines optical parameters
|
|
50
|
+
observer: Observer instance which specifies a time and place. Defaults to `Observer()`
|
|
51
51
|
ephemeris: Ephemeris to use for calculating planet positions (see [Skyfield's documentation](https://rhodesmill.org/skyfield/planets.html) for details)
|
|
52
|
-
style: Styling for the plot (colors, sizes, fonts, etc)
|
|
52
|
+
style: Styling for the plot (colors, sizes, fonts, etc). If `None`, it defaults to `PlotStyle()`
|
|
53
53
|
resolution: Size (in pixels) of largest dimension of the map
|
|
54
|
-
|
|
54
|
+
collision_handler: Default [CollisionHandler][starplot.CollisionHandler] for the plot that describes what to do on label collisions with other labels, markers, etc.
|
|
55
55
|
raise_on_below_horizon: If True, then a ValueError will be raised if the target is below the horizon at the observing time/location
|
|
56
56
|
scale: Scaling factor that will be applied to all sizes in styles (e.g. font size, marker size, line widths, etc). For example, if you want to make everything 2x bigger, then set the scale to 2. At `scale=1` and `resolution=4096` (the default), all sizes are optimized visually for a map that covers 1-3 constellations. So, if you're creating a plot of a _larger_ extent, then it'd probably be good to decrease the scale (i.e. make everything smaller) -- and _increase_ the scale if you're plotting a very small area.
|
|
57
57
|
autoscale: If True, then the scale will be set automatically based on resolution.
|
|
@@ -72,11 +72,11 @@ class OpticPlot(
|
|
|
72
72
|
ra: float,
|
|
73
73
|
dec: float,
|
|
74
74
|
optic: Optic,
|
|
75
|
-
observer: Observer =
|
|
75
|
+
observer: Observer = None,
|
|
76
76
|
ephemeris: str = "de421.bsp",
|
|
77
77
|
style: PlotStyle = DEFAULT_OPTIC_STYLE,
|
|
78
78
|
resolution: int = 4096,
|
|
79
|
-
|
|
79
|
+
collision_handler: CollisionHandler = None,
|
|
80
80
|
raise_on_below_horizon: bool = True,
|
|
81
81
|
scale: float = 1.0,
|
|
82
82
|
autoscale: bool = False,
|
|
@@ -84,12 +84,13 @@ class OpticPlot(
|
|
|
84
84
|
*args,
|
|
85
85
|
**kwargs,
|
|
86
86
|
) -> "OpticPlot":
|
|
87
|
+
observer = observer or Observer()
|
|
87
88
|
super().__init__(
|
|
88
89
|
observer,
|
|
89
90
|
ephemeris,
|
|
90
91
|
style,
|
|
91
92
|
resolution,
|
|
92
|
-
|
|
93
|
+
collision_handler=collision_handler,
|
|
93
94
|
scale=scale,
|
|
94
95
|
autoscale=autoscale,
|
|
95
96
|
suppress_warnings=suppress_warnings,
|
|
@@ -251,43 +252,35 @@ class OpticPlot(
|
|
|
251
252
|
where_labels: list = None,
|
|
252
253
|
catalog: Catalog = BIG_SKY_MAG11,
|
|
253
254
|
style: ObjectStyle = None,
|
|
254
|
-
rasterize: bool = False,
|
|
255
255
|
size_fn: Callable[[Star], float] = callables.size_by_magnitude_for_optic,
|
|
256
256
|
alpha_fn: Callable[[Star], float] = callables.alpha_by_magnitude,
|
|
257
257
|
color_fn: Callable[[Star], str] = None,
|
|
258
258
|
label_fn: Callable[[Star], str] = Star.get_label,
|
|
259
|
-
labels: Mapping[int, str] = None,
|
|
260
259
|
legend_label: str = "Star",
|
|
261
260
|
bayer_labels: bool = False,
|
|
262
261
|
flamsteed_labels: bool = False,
|
|
263
262
|
sql: str = None,
|
|
264
|
-
|
|
265
|
-
|
|
263
|
+
sql_labels: str = None,
|
|
264
|
+
collision_handler: CollisionHandler = None,
|
|
266
265
|
):
|
|
267
266
|
"""
|
|
268
267
|
Plots stars
|
|
269
268
|
|
|
270
|
-
Labels for stars are determined in this order:
|
|
271
|
-
|
|
272
|
-
1. Return value from `label_fn`
|
|
273
|
-
2. Value for star's HIP id in `labels`
|
|
274
|
-
3. IAU-designated name, as listed in the [data reference](/data/star-designations/)
|
|
275
|
-
|
|
276
269
|
Args:
|
|
277
270
|
where: A list of expressions that determine which stars to plot. See [Selecting Objects](/reference-selecting-objects/) for details.
|
|
278
271
|
where_labels: A list of expressions that determine which stars are labeled on the plot. See [Selecting Objects](/reference-selecting-objects/) for details.
|
|
279
|
-
catalog: The catalog of stars to use
|
|
272
|
+
catalog: The catalog of stars to use -- see [catalogs overview](/data/overview/) for details
|
|
280
273
|
style: If `None`, then the plot's style for stars will be used
|
|
281
|
-
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
|
|
282
274
|
size_fn: Callable for calculating the marker size of each star. If `None`, then the marker style's size will be used.
|
|
283
275
|
alpha_fn: Callable for calculating the alpha value (aka "opacity") of each star. If `None`, then the marker style's alpha will be used.
|
|
284
276
|
color_fn: Callable for calculating the color of each star. If `None`, then the marker style's color will be used.
|
|
285
|
-
label_fn: Callable for determining the label of each star.
|
|
286
|
-
labels: A dictionary that maps a star's HIP id to the label that'll be plotted for that star. If `None`, then the star's IAU-designated name will be used.
|
|
277
|
+
label_fn: Callable for determining the label of each star.
|
|
287
278
|
legend_label: Label for stars in the legend. If `None`, then they will not be in the legend.
|
|
288
279
|
bayer_labels: If True, then Bayer labels for stars will be plotted.
|
|
289
280
|
flamsteed_labels: If True, then Flamsteed number labels for stars will be plotted.
|
|
290
281
|
sql: SQL query for selecting stars (table name is `_`). This query will be applied _after_ any filters in the `where` kwarg.
|
|
282
|
+
sql_labels: SQL query for selecting stars that will be labeled (table name is `_`). Applied _after_ any filters in the `where_labels` kwarg.
|
|
283
|
+
collision_handler: An instance of [CollisionHandler][starplot.CollisionHandler] that describes what to do on collisions with other labels, markers, etc. If `None`, then the collision handler of the plot will be used.
|
|
291
284
|
"""
|
|
292
285
|
optic_star_multiplier = self.FIELD_OF_VIEW_MAX / self.optic.true_fov
|
|
293
286
|
size_fn_mx = None
|
|
@@ -302,18 +295,16 @@ class OpticPlot(
|
|
|
302
295
|
where_labels=where_labels,
|
|
303
296
|
catalog=catalog,
|
|
304
297
|
style=style,
|
|
305
|
-
rasterize=rasterize,
|
|
306
298
|
size_fn=size_fn_mx,
|
|
307
299
|
alpha_fn=alpha_fn,
|
|
308
300
|
color_fn=color_fn,
|
|
309
301
|
label_fn=label_fn,
|
|
310
|
-
labels=labels,
|
|
311
302
|
legend_label=legend_label,
|
|
312
303
|
bayer_labels=bayer_labels,
|
|
313
304
|
flamsteed_labels=flamsteed_labels,
|
|
314
305
|
sql=sql,
|
|
315
|
-
|
|
316
|
-
|
|
306
|
+
sql_labels=sql_labels,
|
|
307
|
+
collision_handler=collision_handler,
|
|
317
308
|
)
|
|
318
309
|
|
|
319
310
|
@use_style(LabelStyle, "info_text")
|
|
@@ -3,12 +3,12 @@ from matplotlib import path, patches
|
|
|
3
3
|
|
|
4
4
|
from starplot.coordinates import CoordinateSystem
|
|
5
5
|
from starplot.data.translations import translate
|
|
6
|
-
from starplot.map import MapPlot
|
|
6
|
+
from starplot.plots.map import MapPlot
|
|
7
7
|
from starplot.models.observer import Observer
|
|
8
8
|
from starplot.projections import Stereographic
|
|
9
9
|
from starplot.styles import LabelStyle, PlotStyle, PathStyle, GradientDirection
|
|
10
10
|
from starplot.styles.helpers import use_style
|
|
11
|
-
|
|
11
|
+
from starplot.plotters.text import CollisionHandler
|
|
12
12
|
|
|
13
13
|
DEFAULT_MAP_STYLE = PlotStyle() # .extend(extensions.MAP)
|
|
14
14
|
|
|
@@ -17,11 +17,11 @@ class ZenithPlot(MapPlot):
|
|
|
17
17
|
"""Creates a new zenith plot.
|
|
18
18
|
|
|
19
19
|
Args:
|
|
20
|
-
observer: Observer instance which specifies a time and place
|
|
20
|
+
observer: Observer instance which specifies a time and place. Defaults to `Observer()`
|
|
21
21
|
ephemeris: Ephemeris to use for calculating planet positions (see [Skyfield's documentation](https://rhodesmill.org/skyfield/planets.html) for details)
|
|
22
|
-
style: Styling for the plot (colors, sizes, fonts, etc)
|
|
22
|
+
style: Styling for the plot (colors, sizes, fonts, etc). If `None`, it defaults to `PlotStyle()`
|
|
23
23
|
resolution: Size (in pixels) of largest dimension of the map
|
|
24
|
-
|
|
24
|
+
collision_handler: Default [CollisionHandler][starplot.CollisionHandler] for the plot that describes what to do on label collisions with other labels, markers, etc.
|
|
25
25
|
scale: Scaling factor that will be applied to all sizes in styles (e.g. font size, marker size, line widths, etc). For example, if you want to make everything 2x bigger, then set the scale to 2. At `scale=1` and `resolution=4096` (the default), all sizes are optimized visually for a map that covers 1-3 constellations. So, if you're creating a plot of a _larger_ extent, then it'd probably be good to decrease the scale (i.e. make everything smaller) -- and _increase_ the scale if you're plotting a very small area.
|
|
26
26
|
autoscale: If True, then the scale will be set automatically based on resolution.
|
|
27
27
|
suppress_warnings: If True (the default), then all warnings will be suppressed
|
|
@@ -36,17 +36,18 @@ class ZenithPlot(MapPlot):
|
|
|
36
36
|
|
|
37
37
|
def __init__(
|
|
38
38
|
self,
|
|
39
|
-
observer: Observer =
|
|
39
|
+
observer: Observer = None,
|
|
40
40
|
ephemeris: str = "de421.bsp",
|
|
41
41
|
style: PlotStyle = DEFAULT_MAP_STYLE,
|
|
42
42
|
resolution: int = 4096,
|
|
43
|
-
|
|
43
|
+
collision_handler: CollisionHandler = None,
|
|
44
44
|
scale: float = 1.0,
|
|
45
45
|
autoscale: bool = False,
|
|
46
46
|
suppress_warnings: bool = True,
|
|
47
47
|
*args,
|
|
48
48
|
**kwargs,
|
|
49
49
|
) -> "ZenithPlot":
|
|
50
|
+
observer = observer or Observer()
|
|
50
51
|
projection = Stereographic(
|
|
51
52
|
center_ra=observer.lst,
|
|
52
53
|
center_dec=observer.lat,
|
|
@@ -62,7 +63,7 @@ class ZenithPlot(MapPlot):
|
|
|
62
63
|
ephemeris,
|
|
63
64
|
style,
|
|
64
65
|
resolution,
|
|
65
|
-
|
|
66
|
+
collision_handler=collision_handler,
|
|
66
67
|
clip_path=None,
|
|
67
68
|
scale=scale,
|
|
68
69
|
autoscale=autoscale,
|
|
@@ -175,3 +176,25 @@ class ZenithPlot(MapPlot):
|
|
|
175
176
|
|
|
176
177
|
self.ax.add_patch(self._background_clip_path)
|
|
177
178
|
self._update_clip_path_polygon()
|
|
179
|
+
|
|
180
|
+
def _prepare_star_coords(self, df, limit_by_altaz=False):
|
|
181
|
+
# TODO : reconcile this commented code
|
|
182
|
+
# self.location = self.earth + wgs84.latlon(
|
|
183
|
+
# self.observer.lat, self.observer.lon
|
|
184
|
+
# )
|
|
185
|
+
# df["ra_hours"], df["dec_degrees"] = (df.ra / 15, df.dec)
|
|
186
|
+
# stars_apparent = (
|
|
187
|
+
# self.location.at(self.observer.timescale)
|
|
188
|
+
# .observe(SkyfieldStar.from_dataframe(df))
|
|
189
|
+
# .apparent()
|
|
190
|
+
# )
|
|
191
|
+
# # we only need altitude
|
|
192
|
+
# stars_alt, _, _ = stars_apparent.altaz()
|
|
193
|
+
# df["alt"] = stars_alt.degrees
|
|
194
|
+
# df = df[df["alt"] > 0]
|
|
195
|
+
|
|
196
|
+
df["x"], df["y"] = (
|
|
197
|
+
df["ra"],
|
|
198
|
+
df["dec"],
|
|
199
|
+
)
|
|
200
|
+
return df
|
starplot/plotters/__init__.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
from .
|
|
4
|
-
from .
|
|
5
|
-
from .
|
|
6
|
-
from .
|
|
7
|
-
from .
|
|
1
|
+
# ruff: noqa: F401,F403
|
|
2
|
+
|
|
3
|
+
from .constellations import ConstellationPlotterMixin
|
|
4
|
+
from .stars import StarPlotterMixin
|
|
5
|
+
from .dsos import DsoPlotterMixin
|
|
6
|
+
from .milkyway import MilkyWayPlotterMixin
|
|
7
|
+
from .legend import LegendPlotterMixin
|
|
8
|
+
from .gradients import GradientBackgroundMixin
|
|
9
|
+
from .arrow import ArrowPlotterMixin
|
starplot/plotters/arrow.py
CHANGED
|
@@ -52,7 +52,7 @@ class ArrowPlotterMixin:
|
|
|
52
52
|
max_attempts: int = 100,
|
|
53
53
|
):
|
|
54
54
|
"""
|
|
55
|
-
Plots an arrow from one point to another.
|
|
55
|
+
Plots an arrow from one point to another if you specify both `origin` and `target`. If you only specify a `target`, then the arrow will serve as a "pointer" to that target.
|
|
56
56
|
|
|
57
57
|
Args:
|
|
58
58
|
origin: Starting point (ra, dec)
|
|
@@ -10,8 +10,13 @@ from matplotlib.collections import LineCollection
|
|
|
10
10
|
from ibis import _
|
|
11
11
|
|
|
12
12
|
from starplot.coordinates import CoordinateSystem
|
|
13
|
-
from starplot.data import constellations as condata
|
|
14
|
-
from starplot.data.catalogs import
|
|
13
|
+
from starplot.data import db, constellations as condata
|
|
14
|
+
from starplot.data.catalogs import (
|
|
15
|
+
Catalog,
|
|
16
|
+
CONSTELLATIONS_IAU,
|
|
17
|
+
CONSTELLATION_BORDERS,
|
|
18
|
+
BIG_SKY_MAG11,
|
|
19
|
+
)
|
|
15
20
|
from starplot.data.stars import load as load_stars
|
|
16
21
|
from starplot.models import Star, Constellation
|
|
17
22
|
from starplot.models.constellation import from_tuple
|
|
@@ -27,17 +32,7 @@ from starplot.styles import LineStyle, LabelStyle
|
|
|
27
32
|
from starplot.styles.helpers import use_style
|
|
28
33
|
from starplot.utils import points_on_line
|
|
29
34
|
from starplot.geometry import is_wrapped_polygon
|
|
30
|
-
|
|
31
|
-
DEFAULT_AUTO_ADJUST_SETTINGS = {
|
|
32
|
-
"avoid_constellation_lines": False,
|
|
33
|
-
"point_generation_max_iterations": 10,
|
|
34
|
-
"distance_step_size": 2,
|
|
35
|
-
"max_distance": 3_000,
|
|
36
|
-
"label_padding": 6,
|
|
37
|
-
"buffer": 0.3,
|
|
38
|
-
"seed": None,
|
|
39
|
-
}
|
|
40
|
-
"""Default settings for auto-adjusting constellation labels"""
|
|
35
|
+
from starplot.plotters.text import CollisionHandler
|
|
41
36
|
|
|
42
37
|
GEODETIC_PROJECTIONS = (
|
|
43
38
|
Equidistant,
|
|
@@ -74,6 +69,7 @@ class ConstellationPlotterMixin:
|
|
|
74
69
|
filters=[_.hip.isin(hips)],
|
|
75
70
|
)
|
|
76
71
|
df = results.to_pandas()
|
|
72
|
+
df["ra_hours"], df["dec_degrees"] = (df.ra / 15, df.dec)
|
|
77
73
|
df = self._prepare_star_coords(df, limit_by_altaz=False)
|
|
78
74
|
|
|
79
75
|
return {star.hip: (star.x, star.y) for star in df.itertuples()}
|
|
@@ -95,6 +91,7 @@ class ConstellationPlotterMixin:
|
|
|
95
91
|
style: Styling of the constellations. If None, then the plot's style (specified when creating the plot) will be used
|
|
96
92
|
where: A list of expressions that determine which constellations to plot. See [Selecting Objects](/reference-selecting-objects/) for details.
|
|
97
93
|
sql: SQL query for selecting constellations (table name is `_`). This query will be applied _after_ any filters in the `where` kwarg.
|
|
94
|
+
catalog: The catalog of constellations to use -- see [catalogs overview](/data/overview/) for details
|
|
98
95
|
"""
|
|
99
96
|
self.logger.debug("Plotting constellation lines...")
|
|
100
97
|
|
|
@@ -126,7 +123,7 @@ class ConstellationPlotterMixin:
|
|
|
126
123
|
inbounds = False
|
|
127
124
|
|
|
128
125
|
for s1_hip, s2_hip in hiplines:
|
|
129
|
-
if not constars.get(s2_hip):
|
|
126
|
+
if not constars.get(s1_hip) or not constars.get(s2_hip):
|
|
130
127
|
continue
|
|
131
128
|
s1_ra, s1_dec = constars.get(s1_hip)
|
|
132
129
|
s2_ra, s2_dec = constars.get(s2_hip)
|
|
@@ -206,15 +203,23 @@ class ConstellationPlotterMixin:
|
|
|
206
203
|
|
|
207
204
|
@profile
|
|
208
205
|
@use_style(LineStyle, "constellation_borders")
|
|
209
|
-
def constellation_borders(
|
|
206
|
+
def constellation_borders(
|
|
207
|
+
self, style: LineStyle = None, catalog: Catalog = CONSTELLATION_BORDERS
|
|
208
|
+
):
|
|
210
209
|
"""Plots the constellation borders
|
|
211
210
|
|
|
212
211
|
Args:
|
|
213
212
|
style: Styling of the constellation borders. If None, then the plot's style (specified when creating the plot) will be used
|
|
213
|
+
catalog: Catalog to use for constellation borders
|
|
214
214
|
"""
|
|
215
|
+
con = db.connect()
|
|
216
|
+
borders = catalog._load(connection=con, table_name="constellation_borders")
|
|
217
|
+
borders = borders.mutate(
|
|
218
|
+
geometry=_.geometry.cast("geometry"), # cast WKB to geometry type
|
|
219
|
+
)
|
|
220
|
+
|
|
215
221
|
extent = self._extent_mask()
|
|
216
|
-
|
|
217
|
-
borders_df = results.to_pandas()
|
|
222
|
+
borders_df = borders.filter(_.geometry.intersects(extent)).to_pandas()
|
|
218
223
|
|
|
219
224
|
if borders_df.empty:
|
|
220
225
|
return
|
|
@@ -248,7 +253,29 @@ class ConstellationPlotterMixin:
|
|
|
248
253
|
)
|
|
249
254
|
self.ax.add_collection(line_collection)
|
|
250
255
|
|
|
251
|
-
|
|
256
|
+
@profile
|
|
257
|
+
@use_style(LabelStyle, "constellation_labels")
|
|
258
|
+
def constellation_labels(
|
|
259
|
+
self,
|
|
260
|
+
style: LabelStyle = None,
|
|
261
|
+
label_fn: Callable[[Constellation], str] = Constellation.get_label,
|
|
262
|
+
collision_handler: CollisionHandler = None,
|
|
263
|
+
):
|
|
264
|
+
"""
|
|
265
|
+
Plots constellation labels for all constellations that have been plotted. This means you must plot the constellations before plotting their labels.
|
|
266
|
+
|
|
267
|
+
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.
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
style: Styling of the constellation labels. If None, then the plot's style (specified when creating the plot) will be used
|
|
271
|
+
label_fn: Callable for determining the label for each constellation. The default function returns the constellation's name in uppercase.
|
|
272
|
+
collision_handler: An instance of [CollisionHandler][starplot.CollisionHandler] that describes what to do on collisions with other labels, markers, etc. If `None`, then `CollisionHandler(allow_constellation_line_collisions=True)` will be used (**Important: this function does NOT default to the plot's collision handler, since it's the only area-based label function and collisions should be handled differently**).
|
|
273
|
+
"""
|
|
274
|
+
|
|
275
|
+
collision_handler = collision_handler or CollisionHandler(
|
|
276
|
+
allow_constellation_line_collisions=True
|
|
277
|
+
)
|
|
278
|
+
|
|
252
279
|
hips = []
|
|
253
280
|
for c in self.objects.constellations:
|
|
254
281
|
hips.extend(c.star_hip_ids)
|
|
@@ -283,49 +310,7 @@ class ConstellationPlotterMixin:
|
|
|
283
310
|
centroid.x,
|
|
284
311
|
centroid.y,
|
|
285
312
|
style,
|
|
286
|
-
hide_on_collision=self.hide_colliding_labels,
|
|
287
313
|
area=constellation.boundary, # TODO : make this intersection with clip path
|
|
288
|
-
|
|
314
|
+
collision_handler=collision_handler,
|
|
289
315
|
gid="constellations-label-name",
|
|
290
316
|
)
|
|
291
|
-
|
|
292
|
-
def _constellation_labels_static(self, style, label_fn):
|
|
293
|
-
for constellation in self.objects.constellations:
|
|
294
|
-
text = label_fn(constellation)
|
|
295
|
-
self.text(
|
|
296
|
-
text,
|
|
297
|
-
constellation.ra,
|
|
298
|
-
constellation.dec,
|
|
299
|
-
style,
|
|
300
|
-
hide_on_collision=self.hide_colliding_labels,
|
|
301
|
-
remove_on_constellation_collision=False,
|
|
302
|
-
gid="constellations-label-name",
|
|
303
|
-
)
|
|
304
|
-
|
|
305
|
-
@profile
|
|
306
|
-
@use_style(LabelStyle, "constellation_labels")
|
|
307
|
-
def constellation_labels(
|
|
308
|
-
self,
|
|
309
|
-
style: LabelStyle = None,
|
|
310
|
-
label_fn: Callable[[Constellation], str] = Constellation.get_label,
|
|
311
|
-
auto_adjust: bool = True,
|
|
312
|
-
auto_adjust_settings: dict = DEFAULT_AUTO_ADJUST_SETTINGS,
|
|
313
|
-
):
|
|
314
|
-
"""
|
|
315
|
-
Plots constellation labels for all constellations that have been plotted. This means you must plot the constellations before plotting their labels.
|
|
316
|
-
|
|
317
|
-
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.
|
|
318
|
-
|
|
319
|
-
Args:
|
|
320
|
-
style: Styling of the constellation labels. If None, then the plot's style (specified when creating the plot) will be used
|
|
321
|
-
label_fn: Callable for determining the label for each constellation. The default function returns the constellation's name in uppercase.
|
|
322
|
-
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.
|
|
323
|
-
auto_adjust_settings: Optional settings for the auto adjustment algorithm.
|
|
324
|
-
"""
|
|
325
|
-
|
|
326
|
-
if auto_adjust:
|
|
327
|
-
settings = DEFAULT_AUTO_ADJUST_SETTINGS
|
|
328
|
-
settings.update(auto_adjust_settings)
|
|
329
|
-
self._constellation_labels_auto(style, label_fn, settings=settings)
|
|
330
|
-
else:
|
|
331
|
-
self._constellation_labels_static(style, label_fn)
|