starplot 0.12.4__py2.py3-none-any.whl → 0.13.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.
Potentially problematic release.
This version of starplot might be problematic. Click here for more details.
- starplot/__init__.py +1 -1
- starplot/base.py +371 -60
- starplot/callables.py +61 -7
- starplot/data/bayer.py +1532 -3
- starplot/data/flamsteed.py +2682 -0
- starplot/data/library/constellation_borders_inv.gpkg +0 -0
- starplot/data/library/constellation_lines_hips.json +3 -1
- starplot/data/stars.py +408 -87
- starplot/horizon.py +398 -0
- starplot/map.py +149 -24
- starplot/models/constellation.py +1 -0
- starplot/optic.py +26 -14
- starplot/plotters/dsos.py +6 -2
- starplot/plotters/stars.py +114 -13
- starplot/styles/base.py +263 -156
- starplot/styles/ext/antique.yml +45 -39
- starplot/styles/ext/blue_dark.yml +32 -36
- starplot/styles/ext/blue_light.yml +43 -25
- starplot/styles/ext/blue_medium.yml +48 -44
- starplot/styles/ext/cb_wong.yml +7 -0
- starplot/styles/ext/grayscale.yml +13 -7
- starplot/styles/ext/grayscale_dark.yml +12 -4
- starplot/styles/ext/map.yml +4 -4
- starplot/styles/ext/nord.yml +32 -32
- starplot/styles/ext/optic.yml +7 -5
- 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/hind/DESCRIPTION.en_us.html +28 -0
- starplot/styles/fonts-library/hind/Hind-Bold.ttf +0 -0
- starplot/styles/fonts-library/hind/Hind-Light.ttf +0 -0
- starplot/styles/fonts-library/hind/Hind-Medium.ttf +0 -0
- starplot/styles/fonts-library/hind/Hind-Regular.ttf +0 -0
- starplot/styles/fonts-library/hind/Hind-SemiBold.ttf +0 -0
- starplot/styles/fonts-library/hind/METADATA.pb +58 -0
- starplot/styles/fonts-library/hind/OFL.txt +93 -0
- starplot/styles/fonts-library/inter/Inter-Black.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-BlackItalic.ttf +0 -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-ExtraBoldItalic.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-Medium.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-MediumItalic.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/Inter-Thin.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-ThinItalic.ttf +0 -0
- starplot/styles/fonts-library/inter/LICENSE.txt +92 -0
- starplot/styles/fonts.py +15 -0
- starplot/styles/markers.py +207 -6
- {starplot-0.12.4.dist-info → starplot-0.13.0.dist-info}/METADATA +9 -10
- starplot-0.13.0.dist-info/RECORD +101 -0
- starplot-0.12.4.dist-info/RECORD +0 -67
- {starplot-0.12.4.dist-info → starplot-0.13.0.dist-info}/LICENSE +0 -0
- {starplot-0.12.4.dist-info → starplot-0.13.0.dist-info}/WHEEL +0 -0
starplot/map.py
CHANGED
|
@@ -14,7 +14,7 @@ import geopandas as gpd
|
|
|
14
14
|
import numpy as np
|
|
15
15
|
|
|
16
16
|
from starplot import geod
|
|
17
|
-
from starplot.base import BasePlot
|
|
17
|
+
from starplot.base import BasePlot, DPI
|
|
18
18
|
from starplot.data import DataFiles, constellations as condata, stars
|
|
19
19
|
from starplot.data.constellations import CONSTELLATIONS_FULL_NAMES
|
|
20
20
|
from starplot.mixins import ExtentMaskMixin
|
|
@@ -28,7 +28,6 @@ from starplot.styles import (
|
|
|
28
28
|
PlotStyle,
|
|
29
29
|
PolygonStyle,
|
|
30
30
|
PathStyle,
|
|
31
|
-
extensions,
|
|
32
31
|
)
|
|
33
32
|
from starplot.styles.helpers import use_style
|
|
34
33
|
from starplot.utils import lon_to_ra, ra_to_lon
|
|
@@ -37,7 +36,25 @@ from starplot.utils import lon_to_ra, ra_to_lon
|
|
|
37
36
|
warnings.filterwarnings("ignore", module="cartopy")
|
|
38
37
|
warnings.filterwarnings("ignore", module="shapely")
|
|
39
38
|
|
|
40
|
-
DEFAULT_MAP_STYLE = PlotStyle().extend(extensions.MAP)
|
|
39
|
+
DEFAULT_MAP_STYLE = PlotStyle() # .extend(extensions.MAP)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def points(start, end, num_points=100):
|
|
43
|
+
"""Generates points along a line segment.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
start (tuple): (x, y) coordinates of the starting point.
|
|
47
|
+
end (tuple): (x, y) coordinates of the ending point.
|
|
48
|
+
num_points (int): Number of points to generate.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
list: List of (x, y) coordinates of the generated points.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
x_coords = np.linspace(start[0], end[0], num_points)
|
|
55
|
+
y_coords = np.linspace(start[1], end[1], num_points)
|
|
56
|
+
|
|
57
|
+
return list(zip(x_coords, y_coords))
|
|
41
58
|
|
|
42
59
|
|
|
43
60
|
class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
@@ -60,6 +77,8 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
60
77
|
resolution: Size (in pixels) of largest dimension of the map
|
|
61
78
|
hide_colliding_labels: If True, then labels will not be plotted if they collide with another existing label
|
|
62
79
|
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.
|
|
80
|
+
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.
|
|
81
|
+
autoscale: If True, then the scale will be set automatically based on resolution.
|
|
63
82
|
|
|
64
83
|
Returns:
|
|
65
84
|
MapPlot: A new instance of a MapPlot
|
|
@@ -78,9 +97,11 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
78
97
|
dt: datetime = None,
|
|
79
98
|
ephemeris: str = "de421_2001.bsp",
|
|
80
99
|
style: PlotStyle = DEFAULT_MAP_STYLE,
|
|
81
|
-
resolution: int =
|
|
100
|
+
resolution: int = 4096,
|
|
82
101
|
hide_colliding_labels: bool = True,
|
|
83
102
|
clip_path: Polygon = None,
|
|
103
|
+
scale: float = 1.0,
|
|
104
|
+
autoscale: bool = False,
|
|
84
105
|
*args,
|
|
85
106
|
**kwargs,
|
|
86
107
|
) -> "MapPlot":
|
|
@@ -90,6 +111,8 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
90
111
|
style,
|
|
91
112
|
resolution,
|
|
92
113
|
hide_colliding_labels,
|
|
114
|
+
scale=scale,
|
|
115
|
+
autoscale=autoscale,
|
|
93
116
|
*args,
|
|
94
117
|
**kwargs,
|
|
95
118
|
)
|
|
@@ -249,7 +272,7 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
249
272
|
if constellation_borders.empty:
|
|
250
273
|
return
|
|
251
274
|
|
|
252
|
-
style_kwargs = style.matplot_kwargs(self.
|
|
275
|
+
style_kwargs = style.matplot_kwargs(self.scale)
|
|
253
276
|
|
|
254
277
|
geometries = []
|
|
255
278
|
|
|
@@ -265,6 +288,7 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
265
288
|
transform=self._plate_carree,
|
|
266
289
|
clip_on=True,
|
|
267
290
|
clip_path=self._background_clip_path,
|
|
291
|
+
gid="constellations-border",
|
|
268
292
|
**style_kwargs,
|
|
269
293
|
)
|
|
270
294
|
|
|
@@ -325,9 +349,7 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
325
349
|
mls = MultiLineString(geometries)
|
|
326
350
|
geometries = unary_union(mls)
|
|
327
351
|
|
|
328
|
-
style_kwargs = self.style.constellation_borders.matplot_kwargs(
|
|
329
|
-
size_multiplier=self._size_multiplier
|
|
330
|
-
)
|
|
352
|
+
style_kwargs = self.style.constellation_borders.matplot_kwargs(self.scale)
|
|
331
353
|
|
|
332
354
|
for ls in list(geometries.geoms):
|
|
333
355
|
# print(ls)
|
|
@@ -350,7 +372,9 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
350
372
|
labels: dict[str, str] = CONSTELLATIONS_FULL_NAMES,
|
|
351
373
|
where: list = None,
|
|
352
374
|
):
|
|
353
|
-
"""Plots the constellation lines and/or labels
|
|
375
|
+
"""Plots the constellation lines and/or labels.
|
|
376
|
+
|
|
377
|
+
**Important:** If you're plotting the constellation lines, then it's good to plot them _first_, because Starplot will use the constellation lines to determine where to place labels that are plotted afterwards (labels will look better if they're not crossing a constellation line).
|
|
354
378
|
|
|
355
379
|
Args:
|
|
356
380
|
style: Styling of the constellations. If None, then the plot's style (specified when creating the plot) will be used
|
|
@@ -379,7 +403,7 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
379
403
|
transform = self._geodetic
|
|
380
404
|
|
|
381
405
|
conline_hips = condata.lines()
|
|
382
|
-
style_kwargs = style.line.matplot_kwargs(
|
|
406
|
+
style_kwargs = style.line.matplot_kwargs(self.scale)
|
|
383
407
|
|
|
384
408
|
for c in constellations_gdf.itertuples():
|
|
385
409
|
obj = constellation_from_tuple(c)
|
|
@@ -416,19 +440,45 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
416
440
|
# s1_ra, s1_dec = self._proj.transform_point(s1_ra, s1.dec_degrees, self._geodetic)
|
|
417
441
|
# s2_ra, s2_dec = self._proj.transform_point(s2_ra, s2.dec_degrees, self._geodetic)
|
|
418
442
|
|
|
419
|
-
self.ax.plot(
|
|
443
|
+
constellation_line = self.ax.plot(
|
|
420
444
|
[s1_ra, s2_ra],
|
|
421
445
|
[s1_dec, s2_dec],
|
|
422
446
|
transform=transform,
|
|
423
447
|
**style_kwargs,
|
|
424
448
|
clip_on=True,
|
|
425
449
|
clip_path=self._background_clip_path,
|
|
450
|
+
gid="constellations-line",
|
|
451
|
+
)[0]
|
|
452
|
+
|
|
453
|
+
extent = constellation_line.get_window_extent(
|
|
454
|
+
renderer=self.fig.canvas.get_renderer()
|
|
426
455
|
)
|
|
427
456
|
|
|
457
|
+
if extent.xmin < 0:
|
|
458
|
+
continue
|
|
459
|
+
|
|
460
|
+
start = self._proj.transform_point(s1_ra, s1_dec, self._geodetic)
|
|
461
|
+
end = self._proj.transform_point(s2_ra, s2_dec, self._geodetic)
|
|
462
|
+
radius = style_kwargs.get("linewidth") or 1
|
|
463
|
+
|
|
464
|
+
if any([np.isnan(n) for n in start + end]):
|
|
465
|
+
continue
|
|
466
|
+
|
|
467
|
+
for x, y in points(start, end, 25):
|
|
468
|
+
x0, y0 = self.ax.transData.transform((x, y))
|
|
469
|
+
if x0 < 0 or y0 < 0:
|
|
470
|
+
continue
|
|
471
|
+
self._constellations_rtree.insert(
|
|
472
|
+
0,
|
|
473
|
+
np.array((x0 - radius, y0 - radius, x0 + radius, y0 + radius)),
|
|
474
|
+
obj=obj.name,
|
|
475
|
+
)
|
|
476
|
+
|
|
428
477
|
if inbounds:
|
|
429
478
|
self._objects.constellations.append(obj)
|
|
430
479
|
|
|
431
480
|
self._plot_constellation_labels(style.label, labels)
|
|
481
|
+
# self._plot_constellation_labels_experimental(style.label, labels)
|
|
432
482
|
|
|
433
483
|
def _plot_constellation_labels(
|
|
434
484
|
self,
|
|
@@ -440,6 +490,75 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
440
490
|
for con in condata.iterator():
|
|
441
491
|
_, ra, dec = condata.get(con)
|
|
442
492
|
text = labels.get(con.lower())
|
|
493
|
+
self.text(
|
|
494
|
+
text,
|
|
495
|
+
ra,
|
|
496
|
+
dec,
|
|
497
|
+
style,
|
|
498
|
+
hide_on_collision=False,
|
|
499
|
+
gid="constellations-label-name",
|
|
500
|
+
)
|
|
501
|
+
|
|
502
|
+
def _plot_constellation_labels_experimental(
|
|
503
|
+
self,
|
|
504
|
+
style: PathStyle = None,
|
|
505
|
+
labels: dict[str, str] = CONSTELLATIONS_FULL_NAMES,
|
|
506
|
+
):
|
|
507
|
+
from shapely import (
|
|
508
|
+
MultiPoint,
|
|
509
|
+
intersection,
|
|
510
|
+
delaunay_triangles,
|
|
511
|
+
distance,
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
def sorter(g):
|
|
515
|
+
d = distance(g.centroid, points.centroid)
|
|
516
|
+
# d = distance(g.centroid, constellation.boundary.centroid)
|
|
517
|
+
extent = abs(g.bounds[2] - g.bounds[0])
|
|
518
|
+
area = g.area / constellation.boundary.area
|
|
519
|
+
return (extent**2 + area) - (d**2)
|
|
520
|
+
|
|
521
|
+
for constellation in self.objects.constellations:
|
|
522
|
+
constellation_stars = [
|
|
523
|
+
s
|
|
524
|
+
for s in self.objects.stars
|
|
525
|
+
if s.constellation_id == constellation.iau_id
|
|
526
|
+
]
|
|
527
|
+
points = MultiPoint([(s.ra, s.dec) for s in constellation_stars])
|
|
528
|
+
|
|
529
|
+
triangles = delaunay_triangles(
|
|
530
|
+
geometry=points,
|
|
531
|
+
# tolerance=2,
|
|
532
|
+
)
|
|
533
|
+
|
|
534
|
+
polygons = []
|
|
535
|
+
for t in triangles.geoms:
|
|
536
|
+
try:
|
|
537
|
+
inter = intersection(t, constellation.boundary)
|
|
538
|
+
except Exception:
|
|
539
|
+
continue
|
|
540
|
+
if (
|
|
541
|
+
inter.geom_type == "Polygon"
|
|
542
|
+
and len(list(zip(*inter.exterior.coords.xy))) > 2
|
|
543
|
+
):
|
|
544
|
+
polygons.append(inter)
|
|
545
|
+
|
|
546
|
+
p_by_area = {pg.area: pg for pg in polygons}
|
|
547
|
+
polygons_sorted = [
|
|
548
|
+
p_by_area[k] for k in sorted(p_by_area.keys(), reverse=True)
|
|
549
|
+
]
|
|
550
|
+
|
|
551
|
+
# sort by combination of horizontal extent and area
|
|
552
|
+
polygons_sorted = sorted(polygons_sorted, key=sorter, reverse=True)
|
|
553
|
+
|
|
554
|
+
if len(polygons_sorted) > 0:
|
|
555
|
+
i = 0
|
|
556
|
+
ra, dec = polygons_sorted[i].centroid.x, polygons_sorted[i].centroid.y
|
|
557
|
+
else:
|
|
558
|
+
ra, dec = constellation.ra, constellation.dec
|
|
559
|
+
|
|
560
|
+
text = labels.get(constellation.iau_id)
|
|
561
|
+
style = style or self.style.constellation.label
|
|
443
562
|
self.text(text, ra, dec, style)
|
|
444
563
|
|
|
445
564
|
@use_style(PolygonStyle, "milky_way")
|
|
@@ -499,11 +618,11 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
499
618
|
ra, dec, _ = zenith.radec()
|
|
500
619
|
|
|
501
620
|
self.marker(
|
|
502
|
-
ra.hours,
|
|
503
|
-
dec.degrees,
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
legend_label,
|
|
621
|
+
ra=ra.hours,
|
|
622
|
+
dec=dec.degrees,
|
|
623
|
+
style=style,
|
|
624
|
+
label=label,
|
|
625
|
+
legend_label=legend_label,
|
|
507
626
|
)
|
|
508
627
|
|
|
509
628
|
@use_style(PathStyle, "horizon")
|
|
@@ -554,7 +673,7 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
554
673
|
|
|
555
674
|
TODO : investigate why line is extra thick on bottom when plotting line
|
|
556
675
|
"""
|
|
557
|
-
style_kwargs = style.line.matplot_kwargs(self.
|
|
676
|
+
style_kwargs = style.line.matplot_kwargs(self.scale)
|
|
558
677
|
style_kwargs["clip_on"] = False
|
|
559
678
|
style_kwargs["edgecolor"] = style_kwargs.pop("color")
|
|
560
679
|
|
|
@@ -574,7 +693,7 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
574
693
|
x,
|
|
575
694
|
y,
|
|
576
695
|
dash_capstyle=style.line.dash_capstyle,
|
|
577
|
-
**style.line.matplot_kwargs(self.
|
|
696
|
+
**style.line.matplot_kwargs(self.scale),
|
|
578
697
|
**style_kwargs,
|
|
579
698
|
**self._plot_kwargs(),
|
|
580
699
|
)
|
|
@@ -597,10 +716,13 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
597
716
|
cardinal_directions = [north, east, south, west]
|
|
598
717
|
|
|
599
718
|
text_kwargs = dict(
|
|
600
|
-
**style.label.matplot_kwargs(self.
|
|
719
|
+
**style.label.matplot_kwargs(self.scale),
|
|
601
720
|
hide_on_collision=False,
|
|
602
|
-
xytext=(
|
|
603
|
-
|
|
721
|
+
xytext=(
|
|
722
|
+
style.label.offset_x * self.scale,
|
|
723
|
+
style.label.offset_y * self.scale,
|
|
724
|
+
),
|
|
725
|
+
textcoords="offset points",
|
|
604
726
|
path_effects=[],
|
|
605
727
|
)
|
|
606
728
|
|
|
@@ -609,7 +731,7 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
609
731
|
|
|
610
732
|
for i, position in enumerate(cardinal_directions):
|
|
611
733
|
ra, dec, _ = position.radec()
|
|
612
|
-
self._text(ra.hours, dec.degrees, labels[i], **text_kwargs)
|
|
734
|
+
self._text(ra.hours, dec.degrees, labels[i], force=True, **text_kwargs)
|
|
613
735
|
|
|
614
736
|
@use_style(PathStyle, "gridlines")
|
|
615
737
|
def gridlines(
|
|
@@ -664,6 +786,7 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
664
786
|
ypadding=12,
|
|
665
787
|
clip_on=True,
|
|
666
788
|
clip_path=self._background_clip_path,
|
|
789
|
+
gid="gridlines",
|
|
667
790
|
**line_style_kwargs,
|
|
668
791
|
)
|
|
669
792
|
|
|
@@ -681,6 +804,7 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
681
804
|
self.ax.plot(
|
|
682
805
|
(ra * 15, ra * 15),
|
|
683
806
|
(-90, 90),
|
|
807
|
+
gid="gridlines",
|
|
684
808
|
**line_style_kwargs,
|
|
685
809
|
**self._plot_kwargs(),
|
|
686
810
|
)
|
|
@@ -732,6 +856,7 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
732
856
|
figsize=(self.figure_size, self.figure_size),
|
|
733
857
|
facecolor=self.style.figure_background_color.as_hex(),
|
|
734
858
|
layout="constrained",
|
|
859
|
+
dpi=DPI,
|
|
735
860
|
)
|
|
736
861
|
bounds = self._latlon_bounds()
|
|
737
862
|
center_lat = (bounds[2] + bounds[3]) / 2
|
|
@@ -800,7 +925,7 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
800
925
|
0.05,
|
|
801
926
|
info,
|
|
802
927
|
transform=self.ax.transAxes,
|
|
803
|
-
**style.matplot_kwargs(self.
|
|
928
|
+
**style.matplot_kwargs(self.scale),
|
|
804
929
|
)
|
|
805
930
|
|
|
806
931
|
def _plot_background_clip_path(self):
|
|
@@ -830,7 +955,7 @@ class MapPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
830
955
|
fill=True,
|
|
831
956
|
facecolor=self.style.background_color.as_hex(),
|
|
832
957
|
# edgecolor=self.style.border_line_color.as_hex(),
|
|
833
|
-
linewidth=0,
|
|
958
|
+
linewidth=0,
|
|
834
959
|
zorder=-2_000,
|
|
835
960
|
transform=self.ax.transAxes,
|
|
836
961
|
)
|
starplot/models/constellation.py
CHANGED
starplot/optic.py
CHANGED
|
@@ -8,7 +8,7 @@ from matplotlib import pyplot as plt, patches, path
|
|
|
8
8
|
from skyfield.api import wgs84, Star as SkyfieldStar
|
|
9
9
|
|
|
10
10
|
from starplot import callables
|
|
11
|
-
from starplot.base import BasePlot
|
|
11
|
+
from starplot.base import BasePlot, DPI
|
|
12
12
|
from starplot.data.stars import StarCatalog, STAR_NAMES
|
|
13
13
|
from starplot.mixins import ExtentMaskMixin
|
|
14
14
|
from starplot.models import Star
|
|
@@ -44,6 +44,8 @@ class OpticPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
44
44
|
resolution: Size (in pixels) of largest dimension of the map
|
|
45
45
|
hide_colliding_labels: If True, then labels will not be plotted if they collide with another existing label
|
|
46
46
|
raise_on_below_horizon: If True, then a ValueError will be raised if the target is below the horizon at the observing time/location
|
|
47
|
+
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.
|
|
48
|
+
autoscale: If True, then the scale will be set automatically based on resolution.
|
|
47
49
|
|
|
48
50
|
Returns:
|
|
49
51
|
OpticPlot: A new instance of an OpticPlot
|
|
@@ -62,9 +64,11 @@ class OpticPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
62
64
|
dt: datetime = None,
|
|
63
65
|
ephemeris: str = "de421_2001.bsp",
|
|
64
66
|
style: PlotStyle = DEFAULT_OPTIC_STYLE,
|
|
65
|
-
resolution: int =
|
|
67
|
+
resolution: int = 4096,
|
|
66
68
|
hide_colliding_labels: bool = True,
|
|
67
69
|
raise_on_below_horizon: bool = True,
|
|
70
|
+
scale: float = 1.0,
|
|
71
|
+
autoscale: bool = False,
|
|
68
72
|
*args,
|
|
69
73
|
**kwargs,
|
|
70
74
|
) -> "OpticPlot":
|
|
@@ -74,6 +78,8 @@ class OpticPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
74
78
|
style,
|
|
75
79
|
resolution,
|
|
76
80
|
hide_colliding_labels,
|
|
81
|
+
scale=scale,
|
|
82
|
+
autoscale=autoscale,
|
|
77
83
|
*args,
|
|
78
84
|
**kwargs,
|
|
79
85
|
)
|
|
@@ -193,6 +199,7 @@ class OpticPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
193
199
|
else:
|
|
194
200
|
plotted.set_clip_path(self._background_clip_path)
|
|
195
201
|
|
|
202
|
+
@use_style(ObjectStyle, "star")
|
|
196
203
|
def stars(
|
|
197
204
|
self,
|
|
198
205
|
mag: float = 6.0,
|
|
@@ -207,6 +214,7 @@ class OpticPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
207
214
|
labels: Mapping[int, str] = STAR_NAMES,
|
|
208
215
|
legend_label: str = "Star",
|
|
209
216
|
bayer_labels: bool = False,
|
|
217
|
+
flamsteed_labels: bool = False,
|
|
210
218
|
*args,
|
|
211
219
|
**kwargs,
|
|
212
220
|
):
|
|
@@ -225,12 +233,16 @@ class OpticPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
225
233
|
where_labels: A list of expressions that determine which stars are labeled on the plot. See [Selecting Objects](/reference-selecting-objects/) for details.
|
|
226
234
|
labels: A dictionary that maps a star's HIP id to the label that'll be plotted for that star. If you want to hide name labels, then set this arg to `None`.
|
|
227
235
|
legend_label: Label for stars in the legend. If `None`, then they will not be in the legend.
|
|
228
|
-
bayer_labels: If True, then Bayer labels for stars will be plotted.
|
|
236
|
+
bayer_labels: If True, then Bayer labels for stars will be plotted.
|
|
237
|
+
flamsteed_labels: If True, then Flamsteed number labels for stars will be plotted.
|
|
229
238
|
"""
|
|
230
|
-
optic_star_multiplier =
|
|
239
|
+
optic_star_multiplier = self.FIELD_OF_VIEW_MAX / self.optic.true_fov
|
|
240
|
+
size_fn_mx = None
|
|
231
241
|
|
|
232
|
-
|
|
233
|
-
|
|
242
|
+
if size_fn is not None:
|
|
243
|
+
|
|
244
|
+
def size_fn_mx(s):
|
|
245
|
+
return size_fn(s) * optic_star_multiplier
|
|
234
246
|
|
|
235
247
|
super().stars(
|
|
236
248
|
mag=mag,
|
|
@@ -245,6 +257,7 @@ class OpticPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
245
257
|
labels=labels,
|
|
246
258
|
legend_label=legend_label,
|
|
247
259
|
bayer_labels=bayer_labels,
|
|
260
|
+
flamsteed_labels=flamsteed_labels,
|
|
248
261
|
*args,
|
|
249
262
|
**kwargs,
|
|
250
263
|
)
|
|
@@ -268,7 +281,7 @@ class OpticPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
268
281
|
) # apply transform again because new xy limits will undo the transform
|
|
269
282
|
|
|
270
283
|
dt_str = self.dt.strftime("%m/%d/%Y @ %H:%M:%S") + " " + self.dt.tzname()
|
|
271
|
-
font_size = style.font_size * self.
|
|
284
|
+
font_size = style.font_size * self.scale
|
|
272
285
|
|
|
273
286
|
column_labels = [
|
|
274
287
|
"Target (Alt/Az)",
|
|
@@ -296,19 +309,17 @@ class OpticPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
296
309
|
edges="vertical",
|
|
297
310
|
)
|
|
298
311
|
table.auto_set_font_size(False)
|
|
299
|
-
table.set_fontsize(font_size)
|
|
312
|
+
table.set_fontsize(style.font_size)
|
|
300
313
|
table.scale(1, 3.1)
|
|
301
314
|
|
|
302
315
|
# Apply style to all cells
|
|
303
316
|
for row in [0, 1]:
|
|
304
317
|
for col in range(len(values)):
|
|
305
|
-
table[row, col].set_text_props(
|
|
306
|
-
**style.matplot_kwargs(self._size_multiplier)
|
|
307
|
-
)
|
|
318
|
+
table[row, col].set_text_props(**style.matplot_kwargs(self.scale))
|
|
308
319
|
|
|
309
320
|
# Apply some styles only to the header row
|
|
310
321
|
for col in range(len(values)):
|
|
311
|
-
table[0, col].set_text_props(fontweight="heavy", fontsize=font_size * 1.
|
|
322
|
+
table[0, col].set_text_props(fontweight="heavy", fontsize=font_size * 1.2)
|
|
312
323
|
|
|
313
324
|
def _plot_border(self):
|
|
314
325
|
# since we're using AzimuthalEquidistant projection, the center will always be (0, 0)
|
|
@@ -330,7 +341,7 @@ class OpticPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
330
341
|
inner_border = self.optic.patch(
|
|
331
342
|
x,
|
|
332
343
|
y,
|
|
333
|
-
linewidth=2 * self.
|
|
344
|
+
linewidth=2 * self.scale,
|
|
334
345
|
edgecolor=self.style.border_line_color.as_hex(),
|
|
335
346
|
fill=False,
|
|
336
347
|
zorder=ZOrderEnum.LAYER_5 + 100,
|
|
@@ -342,7 +353,7 @@ class OpticPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
342
353
|
x,
|
|
343
354
|
y,
|
|
344
355
|
padding=0.05,
|
|
345
|
-
linewidth=20 * self.
|
|
356
|
+
linewidth=20 * self.scale,
|
|
346
357
|
edgecolor=self.style.border_bg_color.as_hex(),
|
|
347
358
|
fill=False,
|
|
348
359
|
zorder=ZOrderEnum.LAYER_5,
|
|
@@ -366,6 +377,7 @@ class OpticPlot(BasePlot, ExtentMaskMixin, StarPlotterMixin, DsoPlotterMixin):
|
|
|
366
377
|
figsize=(self.figure_size, self.figure_size),
|
|
367
378
|
facecolor=self.style.figure_background_color.as_hex(),
|
|
368
379
|
layout="constrained",
|
|
380
|
+
dpi=DPI,
|
|
369
381
|
)
|
|
370
382
|
self.ax = plt.axes(projection=self._proj)
|
|
371
383
|
self.ax.xaxis.set_visible(False)
|
starplot/plotters/dsos.py
CHANGED
|
@@ -222,16 +222,20 @@ class DsoPlotterMixin:
|
|
|
222
222
|
)
|
|
223
223
|
|
|
224
224
|
if label:
|
|
225
|
-
self.text(
|
|
225
|
+
self.text(
|
|
226
|
+
label, ra / 15, dec, style.label, gid=f"dso-{d.type}-label"
|
|
227
|
+
)
|
|
226
228
|
|
|
227
229
|
else:
|
|
228
230
|
# if no major axis, then just plot as a marker
|
|
229
231
|
self.marker(
|
|
230
232
|
ra=ra / 15,
|
|
231
233
|
dec=dec,
|
|
232
|
-
label=label,
|
|
233
234
|
style=style,
|
|
235
|
+
label=label,
|
|
234
236
|
skip_bounds_check=True,
|
|
237
|
+
gid_marker=f"dso-{d.type}-marker",
|
|
238
|
+
gid_label=f"dso-{d.type}-label",
|
|
235
239
|
)
|
|
236
240
|
|
|
237
241
|
self._objects.dsos.append(_dso)
|