starplot 0.20.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. starplot/__init__.py +59 -0
  2. starplot/callables.py +176 -0
  3. starplot/cli.py +29 -0
  4. starplot/config.py +80 -0
  5. starplot/coordinates.py +7 -0
  6. starplot/data/__init__.py +22 -0
  7. starplot/data/catalogs.py +356 -0
  8. starplot/data/constellations.py +71 -0
  9. starplot/data/db.py +33 -0
  10. starplot/data/dsos.py +85 -0
  11. starplot/data/ecliptic.py +201 -0
  12. starplot/data/library/constellation_names.parquet +0 -0
  13. starplot/data/library/dso_names.parquet +0 -0
  14. starplot/data/library/readme.md +1 -0
  15. starplot/data/library/star_designations.parquet +0 -0
  16. starplot/data/stars.py +79 -0
  17. starplot/data/translations.py +408 -0
  18. starplot/data/utils.py +35 -0
  19. starplot/geometry.py +319 -0
  20. starplot/mixins.py +360 -0
  21. starplot/models/__init__.py +21 -0
  22. starplot/models/base.py +77 -0
  23. starplot/models/comet.py +302 -0
  24. starplot/models/constellation.py +151 -0
  25. starplot/models/dso.py +317 -0
  26. starplot/models/milky_way.py +30 -0
  27. starplot/models/moon.py +130 -0
  28. starplot/models/objects.py +29 -0
  29. starplot/models/observer.py +125 -0
  30. starplot/models/optics.py +342 -0
  31. starplot/models/planet.py +137 -0
  32. starplot/models/satellite.py +138 -0
  33. starplot/models/star.py +253 -0
  34. starplot/models/sun.py +62 -0
  35. starplot/plots/__init__.py +7 -0
  36. starplot/plots/base.py +1023 -0
  37. starplot/plots/galaxy.py +372 -0
  38. starplot/plots/horizon.py +543 -0
  39. starplot/plots/map.py +515 -0
  40. starplot/plots/optic.py +469 -0
  41. starplot/plots/zenith.py +217 -0
  42. starplot/plotters/__init__.py +9 -0
  43. starplot/plotters/arrow.py +174 -0
  44. starplot/plotters/constellations.py +298 -0
  45. starplot/plotters/debug.py +21 -0
  46. starplot/plotters/dsos.py +294 -0
  47. starplot/plotters/experimental.py +722 -0
  48. starplot/plotters/gradients.py +153 -0
  49. starplot/plotters/legend.py +253 -0
  50. starplot/plotters/milkyway.py +51 -0
  51. starplot/plotters/stars.py +319 -0
  52. starplot/plotters/text.py +802 -0
  53. starplot/profile.py +16 -0
  54. starplot/projections.py +184 -0
  55. starplot/styles/__init__.py +6 -0
  56. starplot/styles/base.py +1344 -0
  57. starplot/styles/ext/antique.yml +175 -0
  58. starplot/styles/ext/blue_dark.yml +163 -0
  59. starplot/styles/ext/blue_gold.yml +147 -0
  60. starplot/styles/ext/blue_light.yml +123 -0
  61. starplot/styles/ext/blue_medium.yml +142 -0
  62. starplot/styles/ext/blue_night.yml +185 -0
  63. starplot/styles/ext/cb_wong.yml +124 -0
  64. starplot/styles/ext/color_print.yml +111 -0
  65. starplot/styles/ext/gradient_presets.yml +158 -0
  66. starplot/styles/ext/grayscale.yml +94 -0
  67. starplot/styles/ext/grayscale_dark.yml +136 -0
  68. starplot/styles/ext/map.yml +12 -0
  69. starplot/styles/ext/nord.yml +158 -0
  70. starplot/styles/ext/optic.yml +20 -0
  71. starplot/styles/ext/publication.yml +8 -0
  72. starplot/styles/extensions.py +129 -0
  73. starplot/styles/fonts-library/gfs-didot/DESCRIPTION.en_us.html +9 -0
  74. starplot/styles/fonts-library/gfs-didot/GFSDidot-Regular.ttf +0 -0
  75. starplot/styles/fonts-library/gfs-didot/METADATA.pb +16 -0
  76. starplot/styles/fonts-library/gfs-didot/OFL.txt +94 -0
  77. starplot/styles/fonts-library/inter/Inter-Bold.ttf +0 -0
  78. starplot/styles/fonts-library/inter/Inter-BoldItalic.ttf +0 -0
  79. starplot/styles/fonts-library/inter/Inter-ExtraBold.ttf +0 -0
  80. starplot/styles/fonts-library/inter/Inter-ExtraLight.ttf +0 -0
  81. starplot/styles/fonts-library/inter/Inter-ExtraLightItalic.ttf +0 -0
  82. starplot/styles/fonts-library/inter/Inter-Italic.ttf +0 -0
  83. starplot/styles/fonts-library/inter/Inter-Light.ttf +0 -0
  84. starplot/styles/fonts-library/inter/Inter-LightItalic.ttf +0 -0
  85. starplot/styles/fonts-library/inter/Inter-Regular.ttf +0 -0
  86. starplot/styles/fonts-library/inter/Inter-SemiBold.ttf +0 -0
  87. starplot/styles/fonts-library/inter/Inter-SemiBoldItalic.ttf +0 -0
  88. starplot/styles/fonts-library/inter/LICENSE.txt +92 -0
  89. starplot/styles/fonts.py +15 -0
  90. starplot/styles/helpers.py +93 -0
  91. starplot/styles/markers.py +308 -0
  92. starplot/utils.py +169 -0
  93. starplot/warnings.py +21 -0
  94. starplot-0.20.5.dist-info/METADATA +146 -0
  95. starplot-0.20.5.dist-info/RECORD +98 -0
  96. starplot-0.20.5.dist-info/WHEEL +4 -0
  97. starplot-0.20.5.dist-info/entry_points.txt +3 -0
  98. starplot-0.20.5.dist-info/licenses/LICENSE +21 -0
starplot/__init__.py ADDED
@@ -0,0 +1,59 @@
1
+ # ruff: noqa: F401,F403
2
+
3
+ """Star charts and maps of the sky"""
4
+
5
+ __version__ = "0.20.5"
6
+
7
+ from .plots import (
8
+ MapPlot,
9
+ HorizonPlot,
10
+ OpticPlot,
11
+ ZenithPlot,
12
+ GalaxyPlot,
13
+ )
14
+ from .models import (
15
+ DSO,
16
+ DsoType,
17
+ Star,
18
+ Constellation,
19
+ ConstellationBorder,
20
+ Comet,
21
+ Planet,
22
+ Moon,
23
+ Sun,
24
+ ObjectList,
25
+ Scope,
26
+ Binoculars,
27
+ Reflector,
28
+ Refractor,
29
+ Camera,
30
+ Satellite,
31
+ Observer,
32
+ MilkyWay,
33
+ )
34
+ from .data import Catalog
35
+ from .styles import *
36
+ from .projections import *
37
+ from .config import settings
38
+ from .plotters.text import CollisionHandler
39
+
40
+ from ibis import _
41
+
42
+
43
+ import contextlib
44
+
45
+
46
+ @contextlib.contextmanager
47
+ def override_settings(**kwargs):
48
+ original = {}
49
+
50
+ for key, value in kwargs.items():
51
+ original[key] = getattr(settings, key, None)
52
+ setattr(settings, key, value)
53
+
54
+ try:
55
+ yield
56
+
57
+ finally:
58
+ for key, value in original.items():
59
+ setattr(settings, key, value)
starplot/callables.py ADDED
@@ -0,0 +1,176 @@
1
+ import math
2
+
3
+ from typing import Callable
4
+
5
+ from starplot.models import Star
6
+ from starplot.utils import bv_to_hex_color
7
+
8
+
9
+ def size_by_magnitude_factory(
10
+ threshold: float,
11
+ over_threshold_size: float,
12
+ base: float = 20,
13
+ ) -> Callable[[Star], float]:
14
+ """
15
+ Creates a new version of `size_by_magnitude_log` with a custom threshold and base multiplier:
16
+
17
+ ```python
18
+ if magnitude >= threshold:
19
+ size = over_threshold_size
20
+ else:
21
+ size = base ** math.log(threshold - magnitude)
22
+ ```
23
+
24
+ Args:
25
+ threshold: The threshold at which size will be a constant value. In other words, if an object's magnitude is more than or equal to this number, then its size will be the constant `under_threshold_size`
26
+ over_threshold_size: Size for objects that have a magnitude greater than or equal to the treshold
27
+ base: Base for objects that have a magnitude less than the threshold
28
+
29
+ Returns:
30
+ A callable for calculating size based on magnitude
31
+
32
+ """
33
+
34
+ def size_fn(star: Star) -> float:
35
+ m = star.magnitude
36
+ if m >= threshold:
37
+ size = over_threshold_size
38
+ else:
39
+ size = base ** math.log(threshold - m)
40
+
41
+ return size * 9
42
+
43
+ return size_fn
44
+
45
+
46
+ _size_by_magnitude_default = size_by_magnitude_factory(7.6, 4)
47
+
48
+
49
+ def size_by_magnitude_log(star: Star) -> float:
50
+ """
51
+ Calculates size by logarithmic scale of magnitude:
52
+
53
+ ```python
54
+ if magnitude >= 7.6:
55
+ size = 2.36
56
+ else:
57
+ size = 20 ** math.log(8 - magnitude)
58
+ ```
59
+ """
60
+ return _size_by_magnitude_default(star)
61
+
62
+
63
+ def size_by_magnitude(star: Star) -> float:
64
+ """
65
+ Simple sizing by magnitude, using a step size of 1.
66
+
67
+ ```python
68
+ if mag <= 0:
69
+ size = 3800
70
+ elif mag <= 1: # 0..1
71
+ size = 2400
72
+ elif mag <= 2: # 1..2
73
+ size = 1600
74
+ elif mag <= 3: # 2..3
75
+ size = 1000
76
+ elif mag <= 4: # 3..4
77
+ size = 600
78
+ elif mag <= 5: # 4..5
79
+ size = 300
80
+ elif mag <= 6: # 5..6
81
+ size = 120
82
+ elif mag <= 7: # 6..7
83
+ size = 60
84
+ elif mag <= 8: # 7..8
85
+ size = 40
86
+ else: # > 8
87
+ size = 20
88
+
89
+ ```
90
+ """
91
+ mag = star.magnitude
92
+ size = 0
93
+ if mag <= 0:
94
+ size = 3800
95
+ elif mag <= 1: # 0..1
96
+ size = 2400
97
+ elif mag <= 2: # 1..2
98
+ size = 1600
99
+ elif mag <= 3: # 2..3
100
+ size = 1000
101
+ elif mag <= 4: # 3..4
102
+ size = 600
103
+ elif mag <= 5: # 4..5
104
+ size = 300
105
+ elif mag <= 6: # 5..6
106
+ size = 120
107
+ elif mag <= 7: # 6..7
108
+ size = 60
109
+ elif mag <= 8: # 7..8
110
+ size = 40
111
+ else: # > 8
112
+ size = 20
113
+
114
+ return size
115
+
116
+
117
+ def size_by_magnitude_simple(star: Star) -> float:
118
+ """Very simple sizer by magnitude for map plots"""
119
+ m = star.magnitude
120
+ if m < 1.6:
121
+ return (9 - m) ** 2.85
122
+ elif m < 4.6:
123
+ return (8 - m) ** 2.92
124
+ elif m < 5.8:
125
+ return (9 - m) ** 2.46
126
+
127
+ return 2.23
128
+
129
+
130
+ def size_by_magnitude_for_optic(star: Star) -> float:
131
+ """Very simple sizer by magnitude for optic plots"""
132
+ m = star.magnitude
133
+
134
+ if m < 4.6:
135
+ return (9 - m) ** 3.6 * 9
136
+ elif m < 5.85:
137
+ return (9 - m) ** 3.6 * 9
138
+ elif m < 9:
139
+ return (13 - m) ** 1.8 * 9
140
+
141
+ return 4.8 * 6
142
+
143
+
144
+ def alpha_by_magnitude(star: Star) -> float:
145
+ """
146
+ Basic calculator for alpha, based on magnitude:
147
+
148
+ ```python
149
+ if magnitude < 4.6:
150
+ alpha = 1
151
+ elif magnitude < 5.8:
152
+ alpha = 0.9
153
+ else:
154
+ alpha = (16 - m) * 0.09
155
+ ```
156
+ """
157
+ m = star.magnitude
158
+ if m < 4.6:
159
+ return 1
160
+ elif m < 5.8:
161
+ return 0.9
162
+
163
+ return (16 - m) * 0.09
164
+
165
+
166
+ def color_by_bv(star: Star) -> str:
167
+ """
168
+ Calculates color by the object's [B-V index](https://en.wikipedia.org/wiki/Color_index)
169
+
170
+ Color hex values from: [Mitchell Charity](http://www.vendian.org/mncharity/dir3/starcolor/details.html)
171
+ """
172
+ if math.isnan(star.bv):
173
+ bv = 0
174
+ else:
175
+ bv = star.bv
176
+ return bv_to_hex_color(bv)
starplot/cli.py ADDED
@@ -0,0 +1,29 @@
1
+ import sys
2
+
3
+ from starplot.styles import fonts
4
+ from starplot.config import settings
5
+ from starplot.data import db
6
+ from starplot.data.catalogs import download_all_catalogs
7
+
8
+ COMMANDS = ["setup"]
9
+
10
+
11
+ def setup(options):
12
+ print("Installing DuckDB spatial extension...")
13
+ db.connect() # installs spatial extension as side-effect
14
+
15
+ print("Building font cache...")
16
+ fonts.load()
17
+
18
+ print(f"Downloading data catalogs to: {settings.data_path}")
19
+ download_all_catalogs()
20
+
21
+
22
+ def main():
23
+ command = sys.argv[1].lower()
24
+
25
+ if command not in COMMANDS:
26
+ print(f"Unrecognized command: {command}")
27
+
28
+ if command == "setup":
29
+ setup(sys.argv[2:])
starplot/config.py ADDED
@@ -0,0 +1,80 @@
1
+ import os
2
+
3
+ from enum import Enum
4
+ from pathlib import Path
5
+ from dataclasses import dataclass, field
6
+
7
+
8
+ def _get_path(var_name, default) -> Path:
9
+ def _get():
10
+ value = os.environ.get(var_name, default)
11
+ return Path(value)
12
+
13
+ return _get
14
+
15
+
16
+ def _get_boolean(var_name, default) -> bool:
17
+ def _get():
18
+ value = os.environ.get(var_name)
19
+ return default if not value else bool(value.lower() == "true")
20
+
21
+ return _get
22
+
23
+
24
+ class SvgTextType(str, Enum):
25
+ PATH = "path"
26
+ ELEMENT = "element"
27
+
28
+
29
+ @dataclass
30
+ class Settings:
31
+ data_path: Path = field(default_factory=_get_path("STARPLOT_DATA_PATH", Path.cwd()))
32
+ """
33
+ Path that Starplot will use for data and the DuckDB spatial extension, which is required for the data backend.
34
+
35
+ Default = current working directory
36
+ """
37
+
38
+ svg_text_type: SvgTextType = field(
39
+ default_factory=lambda: os.environ.get(
40
+ "STARPLOT_SVG_TEXT_TYPE", SvgTextType.PATH
41
+ )
42
+ )
43
+ """
44
+ Method for rendering text in SVG exports:
45
+
46
+ - `"path"` (default) will render all text as paths. This will increase the filesize,
47
+ but allow all viewers to see the font correctly (even if they don't have the font
48
+ installed on their system).
49
+
50
+ - `"element"` will render all text as an [SVG `<text>` element](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/text),
51
+ which means the text will be editable in graphic design applications but the text may render in a system default font if the original
52
+ font isn't available. **Important: when using the "element" method, text borders will be turned OFF.**
53
+
54
+ """
55
+
56
+ language: str = field(
57
+ default_factory=lambda: os.environ.get("STARPLOT_LANGUAGE", "en-US")
58
+ )
59
+ """
60
+ Default language for plotted labels, as an ISO-639 code. Case insensitive.
61
+
62
+ Supported values:
63
+
64
+ - `en-us` = English (default)
65
+ - `es` = Spanish
66
+ - `fa` = Persian (Farsi). Make sure you have a Persian font installed that supports RTL (such as [Vazir](https://github.com/rastikerdar/vazir-font) or [Noto Sans Arabic](https://fonts.google.com/noto/specimen/Noto+Sans+Arabic)) and set it as the font in your plot's style.
67
+ - `fr` = French
68
+ - `it` = Italian
69
+ - `lt` = Lithuanian
70
+ - `zh-cn` = Chinese. Make sure you have a good Chinese font installed (such as [Noto Sans SC](https://fonts.google.com/noto/specimen/Noto+Sans+SC)) and you'll also need to set that as the font in your plot's style.
71
+ - `zh-tw` = Traditional Chinese
72
+
73
+ **🌐 Want to see another language available? Please help us add it! [Details here](https://github.com/steveberardi/starplot/tree/main/data/raw/translations).**
74
+ """
75
+
76
+ debug: bool = field(default_factory=_get_boolean("STARPLOT_DEBUG", False))
77
+ """Global setting for debug mode. When this is enabled, Starplot will log debugging information and plot polygons for debugging text issues"""
78
+
79
+
80
+ settings = Settings()
@@ -0,0 +1,7 @@
1
+ class CoordinateSystem:
2
+ RA_DEC = "radec"
3
+ AZ_ALT = "azalt"
4
+ AXES = "axes"
5
+ PROJECTED = "projected"
6
+ DISPLAY = "display"
7
+ GALACTIC = "galactic"
@@ -0,0 +1,22 @@
1
+ # ruff: noqa: F401,F403
2
+
3
+ from pathlib import Path
4
+
5
+ from skyfield.api import Loader
6
+
7
+ from starplot.config import settings
8
+ from .catalogs import Catalog
9
+
10
+ load = Loader(settings.data_path) # used for loading ephemeris
11
+
12
+
13
+ HERE = Path(__file__).resolve().parent
14
+
15
+ INTERNAL_DATA_PATH = HERE / "library"
16
+ """Path of starplot data"""
17
+
18
+
19
+ class DataFiles:
20
+ STAR_DESIGNATIONS = INTERNAL_DATA_PATH / "star_designations.parquet"
21
+ CONSTELLATION_NAMES = INTERNAL_DATA_PATH / "constellation_names.parquet"
22
+ DSO_NAMES = INTERNAL_DATA_PATH / "dso_names.parquet"