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.

Files changed (63) hide show
  1. starplot/__init__.py +1 -1
  2. starplot/base.py +371 -60
  3. starplot/callables.py +61 -7
  4. starplot/data/bayer.py +1532 -3
  5. starplot/data/flamsteed.py +2682 -0
  6. starplot/data/library/constellation_borders_inv.gpkg +0 -0
  7. starplot/data/library/constellation_lines_hips.json +3 -1
  8. starplot/data/stars.py +408 -87
  9. starplot/horizon.py +398 -0
  10. starplot/map.py +149 -24
  11. starplot/models/constellation.py +1 -0
  12. starplot/optic.py +26 -14
  13. starplot/plotters/dsos.py +6 -2
  14. starplot/plotters/stars.py +114 -13
  15. starplot/styles/base.py +263 -156
  16. starplot/styles/ext/antique.yml +45 -39
  17. starplot/styles/ext/blue_dark.yml +32 -36
  18. starplot/styles/ext/blue_light.yml +43 -25
  19. starplot/styles/ext/blue_medium.yml +48 -44
  20. starplot/styles/ext/cb_wong.yml +7 -0
  21. starplot/styles/ext/grayscale.yml +13 -7
  22. starplot/styles/ext/grayscale_dark.yml +12 -4
  23. starplot/styles/ext/map.yml +4 -4
  24. starplot/styles/ext/nord.yml +32 -32
  25. starplot/styles/ext/optic.yml +7 -5
  26. starplot/styles/fonts-library/gfs-didot/DESCRIPTION.en_us.html +9 -0
  27. starplot/styles/fonts-library/gfs-didot/GFSDidot-Regular.ttf +0 -0
  28. starplot/styles/fonts-library/gfs-didot/METADATA.pb +16 -0
  29. starplot/styles/fonts-library/gfs-didot/OFL.txt +94 -0
  30. starplot/styles/fonts-library/hind/DESCRIPTION.en_us.html +28 -0
  31. starplot/styles/fonts-library/hind/Hind-Bold.ttf +0 -0
  32. starplot/styles/fonts-library/hind/Hind-Light.ttf +0 -0
  33. starplot/styles/fonts-library/hind/Hind-Medium.ttf +0 -0
  34. starplot/styles/fonts-library/hind/Hind-Regular.ttf +0 -0
  35. starplot/styles/fonts-library/hind/Hind-SemiBold.ttf +0 -0
  36. starplot/styles/fonts-library/hind/METADATA.pb +58 -0
  37. starplot/styles/fonts-library/hind/OFL.txt +93 -0
  38. starplot/styles/fonts-library/inter/Inter-Black.ttf +0 -0
  39. starplot/styles/fonts-library/inter/Inter-BlackItalic.ttf +0 -0
  40. starplot/styles/fonts-library/inter/Inter-Bold.ttf +0 -0
  41. starplot/styles/fonts-library/inter/Inter-BoldItalic.ttf +0 -0
  42. starplot/styles/fonts-library/inter/Inter-ExtraBold.ttf +0 -0
  43. starplot/styles/fonts-library/inter/Inter-ExtraBoldItalic.ttf +0 -0
  44. starplot/styles/fonts-library/inter/Inter-ExtraLight.ttf +0 -0
  45. starplot/styles/fonts-library/inter/Inter-ExtraLightItalic.ttf +0 -0
  46. starplot/styles/fonts-library/inter/Inter-Italic.ttf +0 -0
  47. starplot/styles/fonts-library/inter/Inter-Light.ttf +0 -0
  48. starplot/styles/fonts-library/inter/Inter-LightItalic.ttf +0 -0
  49. starplot/styles/fonts-library/inter/Inter-Medium.ttf +0 -0
  50. starplot/styles/fonts-library/inter/Inter-MediumItalic.ttf +0 -0
  51. starplot/styles/fonts-library/inter/Inter-Regular.ttf +0 -0
  52. starplot/styles/fonts-library/inter/Inter-SemiBold.ttf +0 -0
  53. starplot/styles/fonts-library/inter/Inter-SemiBoldItalic.ttf +0 -0
  54. starplot/styles/fonts-library/inter/Inter-Thin.ttf +0 -0
  55. starplot/styles/fonts-library/inter/Inter-ThinItalic.ttf +0 -0
  56. starplot/styles/fonts-library/inter/LICENSE.txt +92 -0
  57. starplot/styles/fonts.py +15 -0
  58. starplot/styles/markers.py +207 -6
  59. {starplot-0.12.4.dist-info → starplot-0.13.0.dist-info}/METADATA +9 -10
  60. starplot-0.13.0.dist-info/RECORD +101 -0
  61. starplot-0.12.4.dist-info/RECORD +0 -67
  62. {starplot-0.12.4.dist-info → starplot-0.13.0.dist-info}/LICENSE +0 -0
  63. {starplot-0.12.4.dist-info → starplot-0.13.0.dist-info}/WHEEL +0 -0
starplot/styles/base.py CHANGED
@@ -1,8 +1,8 @@
1
1
  import json
2
+
2
3
  from enum import Enum
3
4
  from pathlib import Path
4
- from typing import Optional, Union
5
- from functools import cache
5
+ from typing import Optional, Union, List
6
6
 
7
7
  import yaml
8
8
 
@@ -14,7 +14,14 @@ from typing_extensions import Annotated
14
14
 
15
15
  from starplot.data.dsos import DsoType
16
16
  from starplot.styles.helpers import merge_dict
17
- from starplot.styles.markers import ellipse, circle_cross, circle_line
17
+ from starplot.styles.markers import (
18
+ ellipse,
19
+ circle_cross,
20
+ circle_crosshair,
21
+ circle_line,
22
+ circle_dot,
23
+ circle_dotted_rings,
24
+ )
18
25
 
19
26
 
20
27
  ColorStr = Annotated[
@@ -26,10 +33,11 @@ ColorStr = Annotated[
26
33
  ]
27
34
 
28
35
 
29
- FONT_SCALE = 2
30
-
31
36
  HERE = Path(__file__).resolve().parent
32
37
 
38
+ PI = 3.141592653589793
39
+ SQR_2 = 1.41421356237
40
+
33
41
 
34
42
  class BaseStyle(BaseModel):
35
43
  __hash__ = object.__hash__
@@ -97,9 +105,6 @@ class MarkerSymbolEnum(str, Enum):
97
105
  SQUARE_STRIPES_DIAGONAL = "square_stripes_diagonal"
98
106
  """\u25A8"""
99
107
 
100
- # SQUARE_CROSSHAIR = "square_crosshair"
101
- # """\u2BD0"""
102
-
103
108
  STAR = "star"
104
109
  """\u2605"""
105
110
 
@@ -118,9 +123,17 @@ class MarkerSymbolEnum(str, Enum):
118
123
  CIRCLE_CROSS = "circle_cross"
119
124
  """\u1AA0"""
120
125
 
126
+ CIRCLE_CROSSHAIR = "circle_crosshair"
127
+ """No preview available, but this is the standard symbol for planetary nebulae"""
128
+
129
+ CIRCLE_DOT = "circle_dot"
130
+ """\u29BF"""
131
+
121
132
  CIRCLE_DOTTED_EDGE = "circle_dotted_edge"
122
133
  """\u25CC"""
123
134
 
135
+ CIRCLE_DOTTED_RINGS = "circle_dotted_rings"
136
+
124
137
  CIRCLE_LINE = "circle_line"
125
138
  """\u29B5"""
126
139
 
@@ -150,7 +163,10 @@ class MarkerSymbolEnum(str, Enum):
150
163
  MarkerSymbolEnum.TRIANGLE: "^",
151
164
  MarkerSymbolEnum.CIRCLE_PLUS: "$\u2295$",
152
165
  MarkerSymbolEnum.CIRCLE_CROSS: circle_cross(),
166
+ MarkerSymbolEnum.CIRCLE_CROSSHAIR: circle_crosshair(),
167
+ MarkerSymbolEnum.CIRCLE_DOT: circle_dot(),
153
168
  MarkerSymbolEnum.CIRCLE_DOTTED_EDGE: "$\u25CC$",
169
+ MarkerSymbolEnum.CIRCLE_DOTTED_RINGS: circle_dotted_rings(),
154
170
  MarkerSymbolEnum.CIRCLE_LINE: circle_line(),
155
171
  MarkerSymbolEnum.COMET: "$\u2604$",
156
172
  MarkerSymbolEnum.STAR_8: "$\u2734$",
@@ -222,6 +238,11 @@ class AnchorPointEnum(str, Enum):
222
238
 
223
239
  return style
224
240
 
241
+ @staticmethod
242
+ def from_str(value: str) -> "AnchorPointEnum":
243
+ options = {ap.value: ap for ap in AnchorPointEnum}
244
+ return options.get(value)
245
+
225
246
 
226
247
  class ZOrderEnum(int, Enum):
227
248
  """
@@ -245,19 +266,6 @@ class ZOrderEnum(int, Enum):
245
266
  class MarkerStyle(BaseStyle):
246
267
  """
247
268
  Styling properties for markers.
248
-
249
- ???- tip "Example Usage"
250
- Creates a style for a red triangle marker:
251
- ```python
252
- m = MarkerStyle(
253
- color="#b13737",
254
- symbol="triangle",
255
- size=8,
256
- fill="full",
257
- alpha=1.0,
258
- zorder=100,
259
- )
260
- ```
261
269
  """
262
270
 
263
271
  color: Optional[ColorStr] = ColorStr("#000")
@@ -266,14 +274,20 @@ class MarkerStyle(BaseStyle):
266
274
  edge_color: Optional[ColorStr] = ColorStr("#000")
267
275
  """Edge color of marker. Can be a hex, rgb, hsl, or word string."""
268
276
 
269
- edge_width: int = 1
270
- """Edge width of marker. Not available for all marker symbols."""
277
+ edge_width: float = 1
278
+ """Edge width of marker, in points. Not available for all marker symbols."""
279
+
280
+ line_style: Union[LineStyleEnum, tuple] = LineStyleEnum.SOLID
281
+ """Edge line style. Can be a predefined value in `LineStyleEnum` or a [Matplotlib linestyle tuple](https://matplotlib.org/stable/gallery/lines_bars_and_markers/linestyles.html)."""
282
+
283
+ dash_capstyle: DashCapStyleEnum = DashCapStyleEnum.PROJECTING
284
+ """Style of dash endpoints"""
271
285
 
272
286
  symbol: MarkerSymbolEnum = MarkerSymbolEnum.POINT
273
287
  """Symbol for marker"""
274
288
 
275
- size: int = 4
276
- """Relative size of marker"""
289
+ size: float = 22
290
+ """Size of marker in points"""
277
291
 
278
292
  fill: FillStyleEnum = FillStyleEnum.NONE
279
293
  """Fill style of marker"""
@@ -281,53 +295,59 @@ class MarkerStyle(BaseStyle):
281
295
  alpha: float = 1.0
282
296
  """Alpha value (controls transparency)"""
283
297
 
284
- zorder: int = -1
298
+ zorder: int = ZOrderEnum.LAYER_2
285
299
  """Zorder of marker"""
286
300
 
287
301
  @property
288
302
  def symbol_matplot(self) -> str:
289
303
  return MarkerSymbolEnum(self.symbol).as_matplot()
290
304
 
291
- @cache
292
- def matplot_kwargs(self, size_multiplier: float = 1.0) -> dict:
305
+ def matplot_kwargs(self, scale: float = 1.0) -> dict:
293
306
  return dict(
294
307
  color=self.color.as_hex() if self.color else "none",
295
308
  markeredgecolor=self.edge_color.as_hex() if self.edge_color else "none",
296
309
  marker=MarkerSymbolEnum(self.symbol).as_matplot(),
297
- markersize=self.size * size_multiplier * FONT_SCALE,
310
+ markersize=self.size * scale,
298
311
  fillstyle=self.fill,
299
312
  alpha=self.alpha,
300
313
  zorder=self.zorder,
301
314
  )
302
315
 
316
+ def matplot_scatter_kwargs(self, scale: float = 1.0) -> dict:
317
+ plot_kwargs = self.matplot_kwargs(scale)
318
+ plot_kwargs["edgecolors"] = plot_kwargs.pop("markeredgecolor")
319
+
320
+ # matplotlib's plot() function takes the marker size in points diameter
321
+ # and the scatter() function takes it in points squared
322
+ plot_kwargs["s"] = ((plot_kwargs.pop("markersize") / scale) ** 2) * (scale**2)
323
+
324
+ plot_kwargs["c"] = plot_kwargs.pop("color")
325
+ plot_kwargs["linewidths"] = self.edge_width * scale
326
+ plot_kwargs["linestyle"] = self.line_style
327
+ plot_kwargs["capstyle"] = self.dash_capstyle
328
+
329
+ plot_kwargs.pop("fillstyle")
330
+
331
+ return plot_kwargs
332
+
303
333
  def to_polygon_style(self):
304
334
  return PolygonStyle(
305
335
  fill_color=self.color.as_hex() if self.color else None,
306
336
  edge_color=self.edge_color.as_hex() if self.edge_color else None,
337
+ edge_width=self.edge_width,
307
338
  alpha=self.alpha,
308
339
  zorder=self.zorder,
340
+ line_style=self.line_style,
309
341
  )
310
342
 
311
343
 
312
344
  class LineStyle(BaseStyle):
313
345
  """
314
346
  Styling properties for lines.
315
-
316
- ???- tip "Example Usage"
317
- Creates a style for a dashed green line:
318
- ```python
319
- ls = LineStyle(
320
- width=2,
321
- color="#6ba832",
322
- style="dashed",
323
- alpha=0.2,
324
- zorder=-10,
325
- )
326
- ```
327
347
  """
328
348
 
329
- width: float = 2
330
- """Width of line"""
349
+ width: float = 4
350
+ """Width of line in points"""
331
351
 
332
352
  color: ColorStr = ColorStr("#000")
333
353
  """Color of the line. Can be a hex, rgb, hsl, or word string."""
@@ -341,17 +361,17 @@ class LineStyle(BaseStyle):
341
361
  alpha: float = 1.0
342
362
  """Alpha value (controls transparency)"""
343
363
 
344
- zorder: int = -1
364
+ zorder: int = ZOrderEnum.LAYER_2
345
365
  """Zorder of the line"""
346
366
 
347
367
  edge_width: int = 0
348
- """Width of the line's edge. _If the width or color is falsey then the line will NOT be drawn with an edge._"""
368
+ """Width of the line's edge in points. _If the width or color is falsey then the line will NOT be drawn with an edge._"""
349
369
 
350
370
  edge_color: Optional[ColorStr] = None
351
371
  """Edge color of the line. _If the width or color is falsey then the line will NOT be drawn with an edge._"""
352
372
 
353
- def matplot_kwargs(self, size_multiplier: float = 1.0) -> dict:
354
- line_width = self.width * size_multiplier
373
+ def matplot_kwargs(self, scale: float = 1.0) -> dict:
374
+ line_width = self.width * scale
355
375
 
356
376
  result = dict(
357
377
  color=self.color.as_hex(),
@@ -365,7 +385,7 @@ class LineStyle(BaseStyle):
365
385
  if self.edge_width and self.edge_color:
366
386
  result["path_effects"] = [
367
387
  patheffects.withStroke(
368
- linewidth=line_width + 2 * self.edge_width * size_multiplier,
388
+ linewidth=line_width + 2 * self.edge_width * scale,
369
389
  foreground=self.edge_color.as_hex(),
370
390
  )
371
391
  ]
@@ -376,21 +396,10 @@ class LineStyle(BaseStyle):
376
396
  class PolygonStyle(BaseStyle):
377
397
  """
378
398
  Styling properties for polygons.
379
-
380
- ???- tip "Example Usage"
381
- Creates a style for a partially transparent blue polygon:
382
- ```python
383
- ps = PolygonStyle(
384
- color="#d9d9d9",
385
- alpha=0.36,
386
- edge_width=0,
387
- zorder=-10000,
388
- )
389
- ```
390
399
  """
391
400
 
392
- edge_width: int = 1
393
- """Width of the polygon's edge"""
401
+ edge_width: float = 1
402
+ """Width of the polygon's edge in points"""
394
403
 
395
404
  color: Optional[ColorStr] = None
396
405
  """If specified, this will be the fill color AND edge color of the polygon"""
@@ -410,12 +419,12 @@ class PolygonStyle(BaseStyle):
410
419
  zorder: int = -1
411
420
  """Zorder of the polygon"""
412
421
 
413
- def matplot_kwargs(self, size_multiplier: float = 1.0) -> dict:
422
+ def matplot_kwargs(self, scale: float = 1.0) -> dict:
414
423
  styles = dict(
415
424
  edgecolor=self.edge_color.as_hex() if self.edge_color else "none",
416
425
  facecolor=self.fill_color.as_hex() if self.fill_color else "none",
417
426
  fill=True if self.fill_color else False,
418
- linewidth=self.edge_width * size_multiplier,
427
+ linewidth=self.edge_width * scale,
419
428
  linestyle=self.line_style,
420
429
  alpha=self.alpha,
421
430
  zorder=self.zorder,
@@ -430,23 +439,10 @@ class PolygonStyle(BaseStyle):
430
439
  class LabelStyle(BaseStyle):
431
440
  """
432
441
  Styling properties for a label.
433
-
434
- ???- tip "Example Usage"
435
- Creates a style for a bold blue label:
436
- ```python
437
- ls = LabelStyle(
438
- font_color="blue",
439
- font_weight="bold",
440
- zorder=1,
441
- )
442
- ```
443
442
  """
444
443
 
445
- anchor_point: AnchorPointEnum = AnchorPointEnum.BOTTOM_RIGHT
446
- """Anchor point of label"""
447
-
448
- font_size: int = 8
449
- """Relative font size of the label"""
444
+ font_size: float = 15
445
+ """Font size of the label, in points"""
450
446
 
451
447
  font_weight: FontWeightEnum = FontWeightEnum.NORMAL
452
448
  """Font weight (e.g. normal, bold, ultra bold, etc)"""
@@ -460,28 +456,50 @@ class LabelStyle(BaseStyle):
460
456
  font_style: FontStyleEnum = FontStyleEnum.NORMAL
461
457
  """Style of the label (e.g. normal, italic, etc)"""
462
458
 
463
- font_name: Optional[str] = None
459
+ font_name: Optional[str] = "Inter"
464
460
  """Name of the font to use"""
465
461
 
466
462
  font_family: Optional[str] = None
467
463
  """Font family (e.g. 'monospace', 'sans-serif', 'serif', etc)"""
468
464
 
469
- line_spacing: Optional[int] = None
465
+ line_spacing: Optional[float] = None
470
466
  """Spacing between lines of text"""
471
467
 
472
- offset_x: int = 0
473
- """Horizontal offset of the label, in pixels. Negative values supported."""
468
+ anchor_point: AnchorPointEnum = AnchorPointEnum.BOTTOM_RIGHT
469
+ """Anchor point of label"""
474
470
 
475
- offset_y: int = 0
476
- """Vertical offset of the label, in pixels. Negative values supported."""
471
+ border_width: float = 0
472
+ """Width of border (also known as 'halos') around the text, in points"""
473
+
474
+ border_color: Optional[ColorStr] = None
475
+ """Color of border (also known as 'halos') around the text"""
476
+
477
+ offset_x: Union[float, int, str] = 0
478
+ """
479
+ Horizontal offset of the label, in points. Negative values supported.
480
+
481
+
482
+ **Auto Mode** (_experimental_): If the label is plotted as part of a marker (e.g. stars, via `marker()`, etc), then you can also
483
+ specify the offset as `"auto"` which will calculate the offset automatically based on the marker's size and place
484
+ the label just outside the marker (avoiding overlapping). To enable "auto" mode you have to specify BOTH offsets (x and y) as "auto."
485
+ """
477
486
 
478
- zorder: int = 101
487
+ offset_y: Union[float, int, str] = 0
488
+ """
489
+ Vertical offset of the label, in points. Negative values supported.
490
+
491
+ **Auto Mode** (_experimental_): If the label is plotted as part of a marker (e.g. stars, via `marker()`, etc), then you can also
492
+ specify the offset as `"auto"` which will calculate the offset automatically based on the marker's size and place
493
+ the label just outside the marker (avoiding overlapping). To enable "auto" mode you have to specify BOTH offsets (x and y) as "auto."
494
+ """
495
+
496
+ zorder: int = ZOrderEnum.LAYER_4
479
497
  """Zorder of the label"""
480
498
 
481
- def matplot_kwargs(self, size_multiplier: float = 1.0) -> dict:
499
+ def matplot_kwargs(self, scale: float = 1.0) -> dict:
482
500
  style = dict(
483
501
  color=self.font_color.as_hex(),
484
- fontsize=self.font_size * size_multiplier * FONT_SCALE,
502
+ fontsize=self.font_size * scale,
485
503
  fontstyle=self.font_style,
486
504
  fontname=self.font_name,
487
505
  weight=self.font_weight,
@@ -494,10 +512,45 @@ class LabelStyle(BaseStyle):
494
512
  if self.line_spacing:
495
513
  style["linespacing"] = self.line_spacing
496
514
 
515
+ if self.border_width != 0 and self.border_color is not None:
516
+ style["path_effects"] = [
517
+ patheffects.withStroke(
518
+ linewidth=self.border_width * scale,
519
+ foreground=self.border_color.as_hex(),
520
+ )
521
+ ]
522
+
497
523
  style.update(AnchorPointEnum(self.anchor_point).as_matplot())
498
524
 
499
525
  return style
500
526
 
527
+ def offset_from_marker(self, marker_symbol, marker_size, scale: float = 1.0):
528
+ if self.offset_x != "auto" or self.offset_y != "auto":
529
+ return self
530
+
531
+ new_style = self.model_copy()
532
+
533
+ x_direction = -1 if new_style.anchor_point.endswith("left") else 1
534
+ y_direction = -1 if new_style.anchor_point.startswith("bottom") else 1
535
+
536
+ offset = (marker_size**0.5 / 2) / scale
537
+
538
+ # matplotlib seems to use marker size differently depending on symbol (for scatter)
539
+ # it is NOT strictly the area of the bounding box of the marker
540
+ if marker_symbol in [MarkerSymbolEnum.POINT]:
541
+ offset /= PI
542
+
543
+ elif marker_symbol != MarkerSymbolEnum.SQUARE:
544
+ offset /= SQR_2
545
+ offset *= scale
546
+
547
+ offset += 1.1
548
+
549
+ new_style.offset_x = offset * float(x_direction)
550
+ new_style.offset_y = offset * float(y_direction)
551
+
552
+ return new_style
553
+
501
554
 
502
555
  class ObjectStyle(BaseStyle):
503
556
  """Defines the style for a sky object (e.g. star, DSO)"""
@@ -540,8 +593,8 @@ class LegendStyle(BaseStyle):
540
593
  label_padding: float = 1.6
541
594
  """Padding between legend labels"""
542
595
 
543
- symbol_size: int = 16
544
- """Relative size of symbols in the legend"""
596
+ symbol_size: int = 34
597
+ """Size of symbols in the legend, in points"""
545
598
 
546
599
  symbol_padding: float = 0.2
547
600
  """Padding between each symbol and its label"""
@@ -549,8 +602,8 @@ class LegendStyle(BaseStyle):
549
602
  border_padding: float = 1.28
550
603
  """Padding around legend border"""
551
604
 
552
- font_size: int = 9
553
- """Relative font size of the legend labels"""
605
+ font_size: int = 23
606
+ """Font size of the legend labels, in points"""
554
607
 
555
608
  font_color: ColorStr = ColorStr("#000")
556
609
  """Font color for legend labels"""
@@ -558,12 +611,12 @@ class LegendStyle(BaseStyle):
558
611
  zorder: int = ZOrderEnum.LAYER_5
559
612
  """Zorder of the legend"""
560
613
 
561
- def matplot_kwargs(self, size_multiplier: float = 1.0) -> dict:
614
+ def matplot_kwargs(self, scale: float = 1.0) -> dict:
562
615
  return dict(
563
616
  loc=self.location,
564
617
  ncols=self.num_columns,
565
618
  framealpha=self.background_alpha,
566
- fontsize=self.font_size * size_multiplier * FONT_SCALE,
619
+ fontsize=self.font_size * scale,
567
620
  labelcolor=self.font_color.as_hex(),
568
621
  borderpad=self.border_padding,
569
622
  labelspacing=self.label_padding,
@@ -578,16 +631,25 @@ class PlotStyle(BaseStyle):
578
631
  Defines the styling for a plot
579
632
  """
580
633
 
581
- # Base
582
634
  background_color: ColorStr = ColorStr("#fff")
583
635
  """Background color of the map region"""
584
636
 
585
637
  figure_background_color: ColorStr = ColorStr("#fff")
586
638
 
587
- text_border_width: int = 3
639
+ text_border_width: int = 2
640
+ """Text border (aka halos) width. This will apply to _all_ text labels on the plot. If you'd like to control these borders by object type, then set this global width to `0` and refer to the label style's `border_width` and `border_color` properties."""
641
+
588
642
  text_border_color: ColorStr = ColorStr("#fff")
589
- text_offset_x: float = 0.005
590
- text_offset_y: float = 0.005
643
+
644
+ text_anchor_fallbacks: List[AnchorPointEnum] = [
645
+ AnchorPointEnum.BOTTOM_RIGHT,
646
+ AnchorPointEnum.TOP_LEFT,
647
+ AnchorPointEnum.TOP_RIGHT,
648
+ AnchorPointEnum.BOTTOM_LEFT,
649
+ AnchorPointEnum.BOTTOM_CENTER,
650
+ AnchorPointEnum.TOP_CENTER,
651
+ ]
652
+ """If a label's preferred anchor point results in a collision, then these fallbacks will be tried in sequence until a collision-free position is found."""
591
653
 
592
654
  # Borders
593
655
  border_font_size: int = 18
@@ -608,10 +670,10 @@ class PlotStyle(BaseStyle):
608
670
 
609
671
  # Info text
610
672
  info_text: LabelStyle = LabelStyle(
611
- font_size=10,
673
+ font_size=30,
612
674
  zorder=ZOrderEnum.LAYER_5,
613
- font_family="monospace",
614
- line_spacing=2,
675
+ font_family="Inter",
676
+ line_spacing=1.2,
615
677
  anchor_point=AnchorPointEnum.BOTTOM_CENTER,
616
678
  )
617
679
  """Styling for info text (only applies to zenith and optic plots)"""
@@ -619,31 +681,53 @@ class PlotStyle(BaseStyle):
619
681
  # Stars
620
682
  star: ObjectStyle = ObjectStyle(
621
683
  marker=MarkerStyle(
622
- fill=FillStyleEnum.FULL, zorder=ZOrderEnum.LAYER_3, size=36, edge_color=None
684
+ fill=FillStyleEnum.FULL,
685
+ zorder=ZOrderEnum.LAYER_3 + 1,
686
+ size=40,
687
+ edge_color=None,
623
688
  ),
624
689
  label=LabelStyle(
625
- font_size=9, font_weight=FontWeightEnum.BOLD, zorder=ZOrderEnum.LAYER_4
690
+ font_size=24,
691
+ font_weight=FontWeightEnum.BOLD,
692
+ zorder=ZOrderEnum.LAYER_3 + 2,
693
+ offset_x="auto",
694
+ offset_y="auto",
626
695
  ),
627
696
  )
628
697
  """Styling for stars *(see [`ObjectStyle`][starplot.styles.ObjectStyle])*"""
629
698
 
630
699
  bayer_labels: LabelStyle = LabelStyle(
631
- font_size=7,
700
+ font_size=21,
632
701
  font_weight=FontWeightEnum.LIGHT,
702
+ font_name="GFS Didot",
633
703
  zorder=ZOrderEnum.LAYER_4,
634
704
  anchor_point=AnchorPointEnum.TOP_LEFT,
705
+ offset_x="auto",
706
+ offset_y="auto",
635
707
  )
636
708
  """Styling for Bayer labels of stars"""
637
709
 
710
+ flamsteed_labels: LabelStyle = LabelStyle(
711
+ font_size=13,
712
+ font_weight=FontWeightEnum.NORMAL,
713
+ zorder=ZOrderEnum.LAYER_4,
714
+ anchor_point=AnchorPointEnum.BOTTOM_LEFT,
715
+ offset_x="auto",
716
+ offset_y="auto",
717
+ )
718
+ """Styling for Flamsteed number labels of stars"""
719
+
638
720
  planets: ObjectStyle = ObjectStyle(
639
721
  marker=MarkerStyle(
640
722
  symbol=MarkerSymbolEnum.CIRCLE,
641
- size=4,
723
+ size=50,
642
724
  fill=FillStyleEnum.LEFT,
643
725
  ),
644
726
  label=LabelStyle(
645
- font_size=8,
727
+ font_size=28,
646
728
  font_weight=FontWeightEnum.BOLD,
729
+ offset_x="auto",
730
+ offset_y="auto",
647
731
  ),
648
732
  )
649
733
  """Styling for planets"""
@@ -651,15 +735,17 @@ class PlotStyle(BaseStyle):
651
735
  moon: ObjectStyle = ObjectStyle(
652
736
  marker=MarkerStyle(
653
737
  symbol=MarkerSymbolEnum.CIRCLE,
654
- size=14,
738
+ size=50,
655
739
  fill=FillStyleEnum.FULL,
656
740
  color="#c8c8c8",
657
741
  alpha=1,
658
742
  zorder=ZOrderEnum.LAYER_4,
659
743
  ),
660
744
  label=LabelStyle(
661
- font_size=8,
745
+ font_size=28,
662
746
  font_weight=FontWeightEnum.BOLD,
747
+ offset_x="auto",
748
+ offset_y="auto",
663
749
  ),
664
750
  )
665
751
  """Styling for the moon"""
@@ -667,13 +753,13 @@ class PlotStyle(BaseStyle):
667
753
  sun: ObjectStyle = ObjectStyle(
668
754
  marker=MarkerStyle(
669
755
  symbol=MarkerSymbolEnum.SUN,
670
- size=14,
756
+ size=80,
671
757
  fill=FillStyleEnum.FULL,
672
758
  color="#000",
673
759
  zorder=ZOrderEnum.LAYER_4 - 100,
674
760
  ),
675
761
  label=LabelStyle(
676
- font_size=8,
762
+ font_size=28,
677
763
  font_weight=FontWeightEnum.BOLD,
678
764
  ),
679
765
  )
@@ -683,14 +769,17 @@ class PlotStyle(BaseStyle):
683
769
  dso_open_cluster: ObjectStyle = ObjectStyle(
684
770
  marker=MarkerStyle(
685
771
  symbol=MarkerSymbolEnum.CIRCLE,
686
- size=7,
687
772
  fill=FillStyleEnum.FULL,
773
+ line_style=(0, (1, 2)),
774
+ edge_width=1.3,
775
+ zorder=ZOrderEnum.LAYER_3 - 1,
688
776
  ),
689
777
  label=LabelStyle(
690
- font_size=7,
691
- font_weight=FontWeightEnum.LIGHT,
692
- offset_x=10,
693
- offset_y=-10,
778
+ # font_weight=FontWeightEnum.LIGHT,
779
+ # offset_x=7,
780
+ # offset_y=-6,
781
+ offset_x="auto",
782
+ offset_y="auto",
694
783
  ),
695
784
  )
696
785
  """Styling for open star clusters"""
@@ -698,14 +787,15 @@ class PlotStyle(BaseStyle):
698
787
  dso_association_stars: ObjectStyle = ObjectStyle(
699
788
  marker=MarkerStyle(
700
789
  symbol=MarkerSymbolEnum.CIRCLE,
701
- size=7,
702
790
  fill=FillStyleEnum.FULL,
791
+ line_style=(0, (1, 2)),
792
+ edge_width=1.3,
793
+ zorder=ZOrderEnum.LAYER_3 - 1,
703
794
  ),
704
795
  label=LabelStyle(
705
- font_size=7,
706
796
  font_weight=FontWeightEnum.LIGHT,
707
- offset_x=10,
708
- offset_y=-10,
797
+ offset_x=7,
798
+ offset_y=-6,
709
799
  ),
710
800
  )
711
801
  """Styling for associations of stars"""
@@ -713,113 +803,132 @@ class PlotStyle(BaseStyle):
713
803
  dso_globular_cluster: ObjectStyle = ObjectStyle(
714
804
  marker=MarkerStyle(
715
805
  symbol=MarkerSymbolEnum.CIRCLE_CROSS,
716
- size=7,
717
806
  fill=FillStyleEnum.FULL,
718
807
  color="#555",
719
808
  alpha=0.8,
809
+ edge_width=1.2,
810
+ zorder=ZOrderEnum.LAYER_3 - 1,
720
811
  ),
721
- label=LabelStyle(font_size=7, offset_x=10, offset_y=-10),
812
+ label=LabelStyle(offset_x=7, offset_y=-6),
722
813
  )
723
814
  """Styling for globular star clusters"""
724
815
 
725
816
  dso_galaxy: ObjectStyle = ObjectStyle(
726
817
  marker=MarkerStyle(
727
- symbol=MarkerSymbolEnum.ELLIPSE, size=7, fill=FillStyleEnum.FULL
818
+ symbol=MarkerSymbolEnum.ELLIPSE,
819
+ fill=FillStyleEnum.FULL,
820
+ zorder=ZOrderEnum.LAYER_3 - 1,
728
821
  ),
729
- label=LabelStyle(font_size=7, offset_x=10, offset_y=-10),
822
+ label=LabelStyle(offset_x=1, offset_y=-1),
730
823
  )
731
824
  """Styling for galaxies"""
732
825
 
733
826
  dso_nebula: ObjectStyle = ObjectStyle(
734
827
  marker=MarkerStyle(
735
- symbol=MarkerSymbolEnum.SQUARE, size=7, fill=FillStyleEnum.FULL
828
+ symbol=MarkerSymbolEnum.SQUARE,
829
+ fill=FillStyleEnum.FULL,
830
+ zorder=ZOrderEnum.LAYER_3 - 1,
736
831
  ),
737
- label=LabelStyle(font_size=7, offset_x=10, offset_y=-10),
832
+ label=LabelStyle(offset_x=1, offset_y=-1),
738
833
  )
739
834
  """Styling for nebulas"""
740
835
 
836
+ dso_planetary_nebula: ObjectStyle = ObjectStyle(
837
+ marker=MarkerStyle(
838
+ symbol=MarkerSymbolEnum.CIRCLE_CROSSHAIR,
839
+ fill=FillStyleEnum.FULL,
840
+ edge_width=1.6,
841
+ size=26,
842
+ zorder=ZOrderEnum.LAYER_3 - 1,
843
+ ),
844
+ label=LabelStyle(offset_x=1, offset_y=-1),
845
+ )
846
+ """Styling for planetary nebulas"""
847
+
741
848
  dso_double_star: ObjectStyle = ObjectStyle(
742
849
  marker=MarkerStyle(
743
- symbol=MarkerSymbolEnum.CIRCLE, size=7, fill=FillStyleEnum.TOP
850
+ symbol=MarkerSymbolEnum.CIRCLE_LINE,
851
+ fill=FillStyleEnum.TOP,
852
+ zorder=ZOrderEnum.LAYER_3 - 1,
744
853
  ),
745
- label=LabelStyle(font_size=7),
854
+ label=LabelStyle(offset_x=1, offset_y=-1),
746
855
  )
747
856
  """Styling for double stars"""
748
857
 
749
858
  dso_dark_nebula: ObjectStyle = ObjectStyle(
750
859
  marker=MarkerStyle(
751
860
  symbol=MarkerSymbolEnum.SQUARE,
752
- size=7,
753
861
  fill=FillStyleEnum.TOP,
754
862
  color="#000",
863
+ zorder=ZOrderEnum.LAYER_3 - 1,
755
864
  ),
756
- label=LabelStyle(font_size=7),
865
+ label=LabelStyle(),
757
866
  )
758
867
  """Styling for dark nebulas"""
759
868
 
760
869
  dso_hii_ionized_region: ObjectStyle = ObjectStyle(
761
870
  marker=MarkerStyle(
762
871
  symbol=MarkerSymbolEnum.SQUARE,
763
- size=7,
764
872
  fill=FillStyleEnum.TOP,
765
873
  color="#000",
874
+ zorder=ZOrderEnum.LAYER_3 - 1,
766
875
  ),
767
- label=LabelStyle(font_size=7),
876
+ label=LabelStyle(),
768
877
  )
769
878
  """Styling for HII Ionized regions"""
770
879
 
771
880
  dso_supernova_remnant: ObjectStyle = ObjectStyle(
772
881
  marker=MarkerStyle(
773
882
  symbol=MarkerSymbolEnum.SQUARE,
774
- size=7,
775
883
  fill=FillStyleEnum.TOP,
776
884
  color="#000",
885
+ zorder=ZOrderEnum.LAYER_3 - 1,
777
886
  ),
778
- label=LabelStyle(font_size=7),
887
+ label=LabelStyle(),
779
888
  )
780
889
  """Styling for supernova remnants"""
781
890
 
782
891
  dso_nova_star: ObjectStyle = ObjectStyle(
783
892
  marker=MarkerStyle(
784
893
  symbol=MarkerSymbolEnum.SQUARE,
785
- size=7,
786
894
  fill=FillStyleEnum.TOP,
787
895
  color="#000",
896
+ zorder=ZOrderEnum.LAYER_3 - 1,
788
897
  ),
789
- label=LabelStyle(font_size=7),
898
+ label=LabelStyle(),
790
899
  )
791
900
  """Styling for nova stars"""
792
901
 
793
902
  dso_nonexistant: ObjectStyle = ObjectStyle(
794
903
  marker=MarkerStyle(
795
904
  symbol=MarkerSymbolEnum.SQUARE,
796
- size=7,
797
905
  fill=FillStyleEnum.TOP,
798
906
  color="#000",
907
+ zorder=ZOrderEnum.LAYER_3 - 1,
799
908
  ),
800
- label=LabelStyle(font_size=7),
909
+ label=LabelStyle(),
801
910
  )
802
911
  """Styling for 'nonexistent' (as designated by OpenNGC) deep sky objects"""
803
912
 
804
913
  dso_unknown: ObjectStyle = ObjectStyle(
805
914
  marker=MarkerStyle(
806
915
  symbol=MarkerSymbolEnum.SQUARE,
807
- size=7,
808
916
  fill=FillStyleEnum.TOP,
809
917
  color="#000",
918
+ zorder=ZOrderEnum.LAYER_3 - 1,
810
919
  ),
811
- label=LabelStyle(font_size=7),
920
+ label=LabelStyle(),
812
921
  )
813
922
  """Styling for 'unknown' (as designated by OpenNGC) types of deep sky objects"""
814
923
 
815
924
  dso_duplicate: ObjectStyle = ObjectStyle(
816
925
  marker=MarkerStyle(
817
926
  symbol=MarkerSymbolEnum.SQUARE,
818
- size=7,
819
927
  fill=FillStyleEnum.TOP,
820
928
  color="#000",
929
+ zorder=ZOrderEnum.LAYER_3 - 1,
821
930
  ),
822
- label=LabelStyle(font_size=7),
931
+ label=LabelStyle(),
823
932
  )
824
933
  """Styling for 'duplicate record' (as designated by OpenNGC) types of deep sky objects"""
825
934
 
@@ -827,8 +936,8 @@ class PlotStyle(BaseStyle):
827
936
  constellation: PathStyle = PathStyle(
828
937
  line=LineStyle(color="#c8c8c8"),
829
938
  label=LabelStyle(
830
- font_size=7,
831
- font_weight=FontWeightEnum.LIGHT,
939
+ font_size=21,
940
+ font_weight=FontWeightEnum.NORMAL,
832
941
  zorder=ZOrderEnum.LAYER_3,
833
942
  anchor_point=AnchorPointEnum.TOP_RIGHT,
834
943
  ),
@@ -837,9 +946,9 @@ class PlotStyle(BaseStyle):
837
946
 
838
947
  constellation_borders: LineStyle = LineStyle(
839
948
  color="#000",
840
- width=2,
949
+ width=1.5,
841
950
  style=LineStyleEnum.DASHED,
842
- alpha=0.2,
951
+ alpha=0.4,
843
952
  zorder=ZOrderEnum.LAYER_3,
844
953
  )
845
954
  """Styling for constellation borders (only applies to map plots)"""
@@ -849,7 +958,7 @@ class PlotStyle(BaseStyle):
849
958
  fill_color="#d9d9d9",
850
959
  alpha=0.36,
851
960
  edge_width=0,
852
- zorder=ZOrderEnum.LAYER_2,
961
+ zorder=ZOrderEnum.LAYER_1,
853
962
  )
854
963
  """Styling for the Milky Way (only applies to map plots)"""
855
964
 
@@ -867,9 +976,8 @@ class PlotStyle(BaseStyle):
867
976
  zorder=ZOrderEnum.LAYER_2,
868
977
  ),
869
978
  label=LabelStyle(
870
- font_size=9,
979
+ font_size=18,
871
980
  font_color="#000",
872
- font_weight=FontWeightEnum.LIGHT,
873
981
  font_alpha=1,
874
982
  anchor_point=AnchorPointEnum.BOTTOM_CENTER,
875
983
  ),
@@ -880,16 +988,15 @@ class PlotStyle(BaseStyle):
880
988
  ecliptic: PathStyle = PathStyle(
881
989
  line=LineStyle(
882
990
  color="#777",
883
- width=2,
991
+ width=3,
884
992
  style=LineStyleEnum.DOTTED,
885
993
  dash_capstyle=DashCapStyleEnum.ROUND,
886
- alpha=0.8,
994
+ alpha=1,
887
995
  zorder=ZOrderEnum.LAYER_3,
888
996
  ),
889
997
  label=LabelStyle(
890
- font_size=6,
998
+ font_size=22,
891
999
  font_color="#777",
892
- font_weight=FontWeightEnum.LIGHT,
893
1000
  font_alpha=1,
894
1001
  zorder=ZOrderEnum.LAYER_3,
895
1002
  ),
@@ -900,13 +1007,13 @@ class PlotStyle(BaseStyle):
900
1007
  celestial_equator: PathStyle = PathStyle(
901
1008
  line=LineStyle(
902
1009
  color="#999",
903
- width=2,
1010
+ width=3,
904
1011
  style=LineStyleEnum.DASHED_DOTS,
905
1012
  alpha=0.65,
906
1013
  zorder=ZOrderEnum.LAYER_3,
907
1014
  ),
908
1015
  label=LabelStyle(
909
- font_size=6,
1016
+ font_size=22,
910
1017
  font_color="#999",
911
1018
  font_weight=FontWeightEnum.LIGHT,
912
1019
  font_alpha=0.65,
@@ -918,7 +1025,7 @@ class PlotStyle(BaseStyle):
918
1025
  horizon: PathStyle = PathStyle(
919
1026
  line=LineStyle(
920
1027
  color="#fff",
921
- width=64,
1028
+ width=80,
922
1029
  edge_width=4,
923
1030
  edge_color="#000",
924
1031
  style=LineStyleEnum.SOLID,
@@ -929,7 +1036,7 @@ class PlotStyle(BaseStyle):
929
1036
  label=LabelStyle(
930
1037
  anchor_point=AnchorPointEnum.CENTER,
931
1038
  font_color="#000",
932
- font_size=23,
1039
+ font_size=64,
933
1040
  font_weight=FontWeightEnum.BOLD,
934
1041
  zorder=ZOrderEnum.LAYER_5,
935
1042
  ),
@@ -961,7 +1068,7 @@ class PlotStyle(BaseStyle):
961
1068
  DsoType.GROUP_OF_GALAXIES: self.dso_galaxy,
962
1069
  # Nebulas ----------
963
1070
  DsoType.NEBULA: self.dso_nebula,
964
- DsoType.PLANETARY_NEBULA: self.dso_nebula,
1071
+ DsoType.PLANETARY_NEBULA: self.dso_planetary_nebula,
965
1072
  DsoType.EMISSION_NEBULA: self.dso_nebula,
966
1073
  DsoType.STAR_CLUSTER_NEBULA: self.dso_nebula,
967
1074
  DsoType.REFLECTION_NEBULA: self.dso_nebula,