starplot 0.10.1__py2.py3-none-any.whl → 0.11.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 +10 -2
- starplot/base.py +45 -18
- starplot/data/__init__.py +12 -1
- starplot/data/bigsky.py +97 -0
- starplot/data/library/{stars.tycho-1.gz.parquet → stars.bigsky.mag11.parquet} +0 -0
- starplot/data/stars.py +30 -16
- starplot/data/utils.py +27 -0
- starplot/map.py +213 -77
- starplot/models/__init__.py +1 -0
- starplot/models/base.py +17 -0
- starplot/models/constellation.py +72 -0
- starplot/models/star.py +8 -0
- starplot/optic.py +2 -2
- starplot/plotters/stars.py +25 -5
- starplot/projections.py +11 -0
- starplot/styles/base.py +71 -4
- starplot/styles/ext/antique.yml +16 -0
- starplot/styles/ext/blue_dark.yml +16 -1
- starplot/styles/ext/blue_light.yml +18 -0
- starplot/styles/ext/blue_medium.yml +18 -0
- starplot/styles/ext/cb_wong.yml +20 -1
- starplot/styles/ext/color_print.yml +108 -0
- starplot/styles/ext/grayscale.yml +18 -0
- starplot/styles/ext/grayscale_dark.yml +20 -4
- starplot/styles/ext/nord.yml +21 -4
- starplot/styles/ext/optic.yml +1 -1
- starplot/styles/extensions.py +1 -0
- {starplot-0.10.1.dist-info → starplot-0.11.0.dist-info}/METADATA +7 -3
- {starplot-0.10.1.dist-info → starplot-0.11.0.dist-info}/RECORD +31 -28
- starplot/data/library/readme.md +0 -9
- {starplot-0.10.1.dist-info → starplot-0.11.0.dist-info}/LICENSE +0 -0
- {starplot-0.10.1.dist-info → starplot-0.11.0.dist-info}/WHEEL +0 -0
starplot/__init__.py
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
"""Star charts and maps"""
|
|
2
2
|
|
|
3
|
-
__version__ = "0.
|
|
3
|
+
__version__ = "0.11.0"
|
|
4
4
|
|
|
5
5
|
from .base import BasePlot # noqa: F401
|
|
6
6
|
from .map import MapPlot, Projection # noqa: F401
|
|
7
|
-
from .models import
|
|
7
|
+
from .models import (
|
|
8
|
+
DSO, # noqa: F401
|
|
9
|
+
Star, # noqa: F401
|
|
10
|
+
Constellation, # noqa: F401
|
|
11
|
+
Planet, # noqa: F401
|
|
12
|
+
Moon, # noqa: F401
|
|
13
|
+
Sun, # noqa: F401
|
|
14
|
+
ObjectList, # noqa: F401
|
|
15
|
+
)
|
|
8
16
|
from .optic import OpticPlot # noqa: F401
|
|
9
17
|
from .styles import * # noqa: F401 F403
|
starplot/base.py
CHANGED
|
@@ -22,6 +22,7 @@ from starplot.styles import (
|
|
|
22
22
|
LabelStyle,
|
|
23
23
|
LegendLocationEnum,
|
|
24
24
|
LegendStyle,
|
|
25
|
+
MarkerSymbolEnum,
|
|
25
26
|
PathStyle,
|
|
26
27
|
PolygonStyle,
|
|
27
28
|
)
|
|
@@ -143,12 +144,20 @@ class BasePlot(ABC):
|
|
|
143
144
|
label=label,
|
|
144
145
|
)
|
|
145
146
|
|
|
146
|
-
def _text(
|
|
147
|
+
def _text(
|
|
148
|
+
self,
|
|
149
|
+
ra: float,
|
|
150
|
+
dec: float,
|
|
151
|
+
text: str,
|
|
152
|
+
hide_on_collision: bool = True,
|
|
153
|
+
*args,
|
|
154
|
+
**kwargs,
|
|
155
|
+
) -> None:
|
|
147
156
|
if not text:
|
|
148
157
|
return
|
|
149
158
|
|
|
150
159
|
x, y = self._prepare_coords(ra, dec)
|
|
151
|
-
kwargs["path_effects"] = kwargs.get("path_effects"
|
|
160
|
+
kwargs["path_effects"] = kwargs.get("path_effects", [self.text_border])
|
|
152
161
|
label = self.ax.annotate(
|
|
153
162
|
text,
|
|
154
163
|
(x, y),
|
|
@@ -156,13 +165,24 @@ class BasePlot(ABC):
|
|
|
156
165
|
**kwargs,
|
|
157
166
|
**self._plot_kwargs(),
|
|
158
167
|
)
|
|
168
|
+
if kwargs.get("clip_on") is False:
|
|
169
|
+
return
|
|
170
|
+
|
|
159
171
|
label.set_clip_on(True)
|
|
160
172
|
label.set_clip_path(self._background_clip_path)
|
|
161
173
|
|
|
162
|
-
|
|
174
|
+
if hide_on_collision:
|
|
175
|
+
self._maybe_remove_label(label)
|
|
163
176
|
|
|
164
177
|
@use_style(LabelStyle)
|
|
165
|
-
def text(
|
|
178
|
+
def text(
|
|
179
|
+
self,
|
|
180
|
+
text: str,
|
|
181
|
+
ra: float,
|
|
182
|
+
dec: float,
|
|
183
|
+
style: LabelStyle = None,
|
|
184
|
+
hide_on_collision: bool = True,
|
|
185
|
+
):
|
|
166
186
|
"""
|
|
167
187
|
Plots text
|
|
168
188
|
|
|
@@ -171,6 +191,7 @@ class BasePlot(ABC):
|
|
|
171
191
|
ra: Right ascension of text (0...24)
|
|
172
192
|
dec: Declination of text (-90...90)
|
|
173
193
|
style: Styling of the text
|
|
194
|
+
hide_on_collision: If True, then the text will not be plotted if it collides with another label
|
|
174
195
|
"""
|
|
175
196
|
style = style or LabelStyle()
|
|
176
197
|
self._text(
|
|
@@ -178,6 +199,7 @@ class BasePlot(ABC):
|
|
|
178
199
|
dec,
|
|
179
200
|
text,
|
|
180
201
|
**style.matplot_kwargs(self._size_multiplier),
|
|
202
|
+
hide_on_collision=hide_on_collision,
|
|
181
203
|
xytext=(style.offset_x, style.offset_y),
|
|
182
204
|
textcoords="offset pixels",
|
|
183
205
|
)
|
|
@@ -213,30 +235,33 @@ class BasePlot(ABC):
|
|
|
213
235
|
Args:
|
|
214
236
|
style: Styling of the legend. If None, then the plot's style (specified when creating the plot) will be used
|
|
215
237
|
"""
|
|
216
|
-
if not self._legend_handles:
|
|
217
|
-
return
|
|
218
|
-
|
|
219
238
|
if self._legend is not None:
|
|
220
239
|
self._legend.remove()
|
|
221
240
|
|
|
241
|
+
if not self._legend_handles:
|
|
242
|
+
return
|
|
243
|
+
|
|
222
244
|
bbox_kwargs = {}
|
|
223
245
|
|
|
224
246
|
if style.location == LegendLocationEnum.OUTSIDE_BOTTOM:
|
|
225
|
-
|
|
226
|
-
|
|
247
|
+
style.location = "lower center"
|
|
248
|
+
offset_y = -0.08
|
|
249
|
+
if getattr(self, "_axis_labels", False):
|
|
250
|
+
offset_y -= 0.05
|
|
227
251
|
bbox_kwargs = dict(
|
|
228
|
-
bbox_to_anchor=(0.5,
|
|
252
|
+
bbox_to_anchor=(0.5, offset_y),
|
|
229
253
|
)
|
|
230
254
|
|
|
231
255
|
elif style.location == LegendLocationEnum.OUTSIDE_TOP:
|
|
232
|
-
|
|
256
|
+
style.location = "upper center"
|
|
257
|
+
offset_y = 1.08
|
|
258
|
+
if getattr(self, "_axis_labels", False):
|
|
259
|
+
offset_y += 0.05
|
|
233
260
|
bbox_kwargs = dict(
|
|
234
|
-
bbox_to_anchor=(0.5,
|
|
261
|
+
bbox_to_anchor=(0.5, offset_y),
|
|
235
262
|
)
|
|
236
|
-
else:
|
|
237
|
-
target = self.ax
|
|
238
263
|
|
|
239
|
-
self._legend =
|
|
264
|
+
self._legend = self.ax.legend(
|
|
240
265
|
handles=self._legend_handles.values(),
|
|
241
266
|
**style.matplot_kwargs(size_multiplier=self._size_multiplier),
|
|
242
267
|
**bbox_kwargs,
|
|
@@ -267,7 +292,7 @@ class BasePlot(ABC):
|
|
|
267
292
|
|
|
268
293
|
Args:
|
|
269
294
|
filename: Filename of exported file
|
|
270
|
-
format: Format of file
|
|
295
|
+
format: Format of file (options are "png", "jpeg", or "svg")
|
|
271
296
|
padding: Padding (in inches) around the image
|
|
272
297
|
**kwargs: Any keyword arguments to pass through to matplotlib's `savefig` method
|
|
273
298
|
|
|
@@ -388,7 +413,7 @@ class BasePlot(ABC):
|
|
|
388
413
|
|
|
389
414
|
Args:
|
|
390
415
|
style: Styling of the Sun. If None, then the plot's style (specified when creating the plot) will be used
|
|
391
|
-
true_size: If True, then the Sun's true apparent size in the sky will be plotted. If False, then the style's marker size will be used.
|
|
416
|
+
true_size: If True, then the Sun's true apparent size in the sky will be plotted as a circle (the marker style's symbol will be ignored). If False, then the style's marker size will be used.
|
|
392
417
|
label: How the Sun will be labeled on the plot and legend
|
|
393
418
|
"""
|
|
394
419
|
s = models.Sun.get(
|
|
@@ -413,6 +438,7 @@ class BasePlot(ABC):
|
|
|
413
438
|
style=polygon_style,
|
|
414
439
|
)
|
|
415
440
|
|
|
441
|
+
style.marker.symbol = MarkerSymbolEnum.CIRCLE
|
|
416
442
|
self._add_legend_handle_marker(legend_label, style.marker)
|
|
417
443
|
|
|
418
444
|
if label:
|
|
@@ -584,7 +610,7 @@ class BasePlot(ABC):
|
|
|
584
610
|
|
|
585
611
|
Args:
|
|
586
612
|
style: Styling of the Moon. If None, then the plot's style (specified when creating the plot) will be used
|
|
587
|
-
true_size: If True, then the Moon's true apparent size in the sky will be plotted. If False, then the style's marker size will be used.
|
|
613
|
+
true_size: If True, then the Moon's true apparent size in the sky will be plotted as a circle (the marker style's symbol will be ignored). If False, then the style's marker size will be used.
|
|
588
614
|
show_phase: If True, and if `true_size = True`, then the approximate phase of the moon will be illustrated. The dark side of the moon will be colored with the marker's `edge_color`.
|
|
589
615
|
label: How the Moon will be labeled on the plot and legend
|
|
590
616
|
"""
|
|
@@ -620,6 +646,7 @@ class BasePlot(ABC):
|
|
|
620
646
|
style=polygon_style,
|
|
621
647
|
)
|
|
622
648
|
|
|
649
|
+
style.marker.symbol = MarkerSymbolEnum.CIRCLE
|
|
623
650
|
self._add_legend_handle_marker(legend_label, style.marker)
|
|
624
651
|
|
|
625
652
|
if label:
|
starplot/data/__init__.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
1
3
|
from enum import Enum
|
|
2
4
|
from pathlib import Path
|
|
3
5
|
|
|
@@ -9,12 +11,21 @@ DATA_PATH = HERE / "library"
|
|
|
9
11
|
load = Loader(DATA_PATH)
|
|
10
12
|
|
|
11
13
|
|
|
14
|
+
def env(name, default):
|
|
15
|
+
return os.environ.get(name) or default
|
|
16
|
+
|
|
17
|
+
|
|
12
18
|
class DataFiles(str, Enum):
|
|
19
|
+
# Built-In Files
|
|
13
20
|
CONSTELLATION_LINES = DATA_PATH / "constellation_lines_inv.gpkg"
|
|
14
21
|
CONSTELLATION_LINES_HIP = DATA_PATH / "constellation_lines_hips.json"
|
|
15
22
|
CONSTELLATION_BORDERS = DATA_PATH / "constellation_borders_inv.gpkg"
|
|
16
23
|
MILKY_WAY = DATA_PATH / "milkyway.gpkg"
|
|
17
24
|
HIPPARCOS = DATA_PATH / "stars.hipparcos.parquet"
|
|
18
|
-
|
|
25
|
+
BIG_SKY_MAG11 = DATA_PATH / "stars.bigsky.mag11.parquet"
|
|
19
26
|
ONGC = DATA_PATH / "ongc.gpkg.zip"
|
|
20
27
|
CONSTELLATIONS = DATA_PATH / "constellations.gpkg"
|
|
28
|
+
|
|
29
|
+
# Downloaded Files
|
|
30
|
+
_DOWNLOAD_PATH = Path(env("STARPLOT_DOWNLOAD_PATH", str(DATA_PATH)))
|
|
31
|
+
BIG_SKY = _DOWNLOAD_PATH / "stars.bigsky.parquet"
|
starplot/data/bigsky.py
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import pandas as pd
|
|
4
|
+
|
|
5
|
+
from starplot.data import DATA_PATH, DataFiles, utils
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
BIG_SKY_VERSION = "0.1.0"
|
|
9
|
+
|
|
10
|
+
BIG_SKY_FILENAME = "bigsky.stars.csv.gz"
|
|
11
|
+
|
|
12
|
+
BIG_SKY_URL = f"https://github.com/steveberardi/bigsky/releases/download/v{BIG_SKY_VERSION}/{BIG_SKY_FILENAME}"
|
|
13
|
+
|
|
14
|
+
DOWNLOADED_PATH = DATA_PATH / BIG_SKY_FILENAME
|
|
15
|
+
|
|
16
|
+
DIGITS = 4
|
|
17
|
+
|
|
18
|
+
BIG_SKY_ASSETS = {
|
|
19
|
+
DataFiles.BIG_SKY: "bigsky.stars.csv.gz",
|
|
20
|
+
DataFiles.BIG_SKY_MAG11: "bigsky.stars.mag11.csv.gz",
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def url(filename: str, version: str):
|
|
25
|
+
return f"https://github.com/steveberardi/bigsky/releases/download/v{version}/{filename}"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def download(
|
|
29
|
+
filename: str = BIG_SKY_FILENAME,
|
|
30
|
+
version: str = BIG_SKY_VERSION,
|
|
31
|
+
download_path: str = None,
|
|
32
|
+
digits: int = 4,
|
|
33
|
+
):
|
|
34
|
+
download_path = download_path or str(DATA_PATH / filename)
|
|
35
|
+
utils.download(
|
|
36
|
+
url(filename, version),
|
|
37
|
+
download_path,
|
|
38
|
+
"Big Sky Star Catalog",
|
|
39
|
+
)
|
|
40
|
+
to_parquet(
|
|
41
|
+
download_path,
|
|
42
|
+
DataFiles.BIG_SKY,
|
|
43
|
+
digits,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def to_parquet(source_path: str, destination_path: str, digits: int = DIGITS):
|
|
48
|
+
print("Preparing Big Sky Catalog for Starplot...")
|
|
49
|
+
|
|
50
|
+
df = pd.read_csv(
|
|
51
|
+
source_path,
|
|
52
|
+
header=0,
|
|
53
|
+
names=[
|
|
54
|
+
"tyc_id",
|
|
55
|
+
"hip_id",
|
|
56
|
+
"ccdm",
|
|
57
|
+
"magnitude",
|
|
58
|
+
"bv",
|
|
59
|
+
"ra_degrees_j2000",
|
|
60
|
+
"dec_degrees_j2000",
|
|
61
|
+
"ra_mas_per_year",
|
|
62
|
+
"dec_mas_per_year",
|
|
63
|
+
"parallax_mas",
|
|
64
|
+
],
|
|
65
|
+
compression="gzip",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
df["ra_hours"] = df.apply(
|
|
69
|
+
lambda row: round(row.ra_degrees_j2000 / 15, digits), axis=1
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
df = df.assign(epoch_year=2000)
|
|
73
|
+
|
|
74
|
+
df = df.rename(
|
|
75
|
+
columns={
|
|
76
|
+
"hip_id": "hip",
|
|
77
|
+
"ra_degrees_j2000": "ra_degrees",
|
|
78
|
+
"dec_degrees_j2000": "dec_degrees",
|
|
79
|
+
}
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
df.to_parquet(destination_path, compression="gzip")
|
|
83
|
+
|
|
84
|
+
print(f"Done! {destination_path.value}")
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def load(path):
|
|
88
|
+
if not exists(path):
|
|
89
|
+
download(filename=BIG_SKY_ASSETS.get(path))
|
|
90
|
+
|
|
91
|
+
df = pd.read_parquet(path)
|
|
92
|
+
|
|
93
|
+
return df.set_index("tyc_id")
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def exists(path) -> bool:
|
|
97
|
+
return os.path.isfile(path)
|
|
Binary file
|
starplot/data/stars.py
CHANGED
|
@@ -2,7 +2,7 @@ from enum import Enum
|
|
|
2
2
|
|
|
3
3
|
from pandas import read_parquet
|
|
4
4
|
|
|
5
|
-
from starplot.data import DataFiles
|
|
5
|
+
from starplot.data import bigsky, DataFiles
|
|
6
6
|
|
|
7
7
|
STAR_NAMES = {
|
|
8
8
|
7588: "Achernar",
|
|
@@ -117,27 +117,41 @@ class StarCatalog(str, Enum):
|
|
|
117
117
|
HIPPARCOS = "hipparcos"
|
|
118
118
|
"""Hipparcos Catalog = 118,218 stars"""
|
|
119
119
|
|
|
120
|
-
|
|
121
|
-
"""
|
|
120
|
+
BIG_SKY_MAG11 = "big-sky-mag11"
|
|
121
|
+
"""
|
|
122
|
+
[Big Sky Catalog](https://github.com/steveberardi/bigsky) ~ 900k stars up to magnitude 11
|
|
123
|
+
|
|
124
|
+
This is an _abridged_ version of the Big Sky Catalog, including stars up to a limiting magnitude of 11 (total = 981,852).
|
|
122
125
|
|
|
126
|
+
This catalog is included with Starplot, so does not require downloading any files.
|
|
127
|
+
"""
|
|
123
128
|
|
|
124
|
-
|
|
125
|
-
|
|
129
|
+
BIG_SKY = "big-sky"
|
|
130
|
+
"""
|
|
131
|
+
[Big Sky Catalog](https://github.com/steveberardi/bigsky) ~ 2.5M stars
|
|
126
132
|
|
|
133
|
+
This is the full version of the Big Sky Catalog, which includes 2,557,499 stars from Hipparcos, Tycho-1, and Tycho-2.
|
|
127
134
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
+
This catalog is very large (50+ MB), so it's not built-in to Starplot. When you plot stars and specify this catalog, the catalog
|
|
136
|
+
will be downloaded from the [Big Sky GitHub repository](https://github.com/steveberardi/bigsky) and saved to Starplot's data library
|
|
137
|
+
directory. You can override this download path with the environment variable `STARPLOT_DOWNLOAD_PATH`
|
|
138
|
+
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def load_bigsky():
|
|
143
|
+
if not bigsky.exists():
|
|
144
|
+
bigsky.download()
|
|
145
|
+
|
|
146
|
+
return bigsky.load(DataFiles.BIG_SKY)
|
|
135
147
|
|
|
136
148
|
|
|
137
149
|
def load(catalog: StarCatalog = StarCatalog.HIPPARCOS):
|
|
138
|
-
if catalog == StarCatalog.
|
|
139
|
-
return
|
|
140
|
-
elif catalog == StarCatalog.
|
|
141
|
-
return
|
|
150
|
+
if catalog == StarCatalog.HIPPARCOS:
|
|
151
|
+
return read_parquet(DataFiles.HIPPARCOS)
|
|
152
|
+
elif catalog == StarCatalog.BIG_SKY_MAG11:
|
|
153
|
+
return bigsky.load(DataFiles.BIG_SKY_MAG11)
|
|
154
|
+
elif catalog == StarCatalog.BIG_SKY:
|
|
155
|
+
return bigsky.load(DataFiles.BIG_SKY)
|
|
142
156
|
else:
|
|
143
157
|
raise ValueError("Unrecognized star catalog.")
|
starplot/data/utils.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
import requests
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def download(url, download_path, description=""):
|
|
7
|
+
with open(download_path, "wb") as f:
|
|
8
|
+
print(f"Downloading {description}...")
|
|
9
|
+
|
|
10
|
+
response = requests.get(url, stream=True)
|
|
11
|
+
total_size = response.headers.get("content-length")
|
|
12
|
+
|
|
13
|
+
if total_size is None:
|
|
14
|
+
f.write(response.content)
|
|
15
|
+
return
|
|
16
|
+
|
|
17
|
+
bytes_written = 0
|
|
18
|
+
total_size = int(total_size)
|
|
19
|
+
for chunk in response.iter_content(chunk_size=4096):
|
|
20
|
+
bytes_written += len(chunk)
|
|
21
|
+
f.write(chunk)
|
|
22
|
+
|
|
23
|
+
progress = int(25 * bytes_written / total_size)
|
|
24
|
+
sys.stdout.write("\r[%s%s]" % ("=" * progress, " " * (25 - progress)))
|
|
25
|
+
sys.stdout.flush()
|
|
26
|
+
|
|
27
|
+
print("Download complete!")
|