starplot 0.10.2__py2.py3-none-any.whl → 0.11.1__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 CHANGED
@@ -1,9 +1,17 @@
1
1
  """Star charts and maps"""
2
2
 
3
- __version__ = "0.10.2"
3
+ __version__ = "0.11.1"
4
4
 
5
5
  from .base import BasePlot # noqa: F401
6
6
  from .map import MapPlot, Projection # noqa: F401
7
- from .models import DSO, Star, Planet, Moon, Sun, ObjectList # noqa: F401
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
@@ -144,12 +144,20 @@ class BasePlot(ABC):
144
144
  label=label,
145
145
  )
146
146
 
147
- def _text(self, ra: float, dec: float, text: str, *args, **kwargs) -> None:
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:
148
156
  if not text:
149
157
  return
150
158
 
151
159
  x, y = self._prepare_coords(ra, dec)
152
- kwargs["path_effects"] = kwargs.get("path_effects") or [self.text_border]
160
+ kwargs["path_effects"] = kwargs.get("path_effects", [self.text_border])
153
161
  label = self.ax.annotate(
154
162
  text,
155
163
  (x, y),
@@ -157,13 +165,24 @@ class BasePlot(ABC):
157
165
  **kwargs,
158
166
  **self._plot_kwargs(),
159
167
  )
168
+ if kwargs.get("clip_on") is False:
169
+ return
170
+
160
171
  label.set_clip_on(True)
161
172
  label.set_clip_path(self._background_clip_path)
162
173
 
163
- self._maybe_remove_label(label)
174
+ if hide_on_collision:
175
+ self._maybe_remove_label(label)
164
176
 
165
177
  @use_style(LabelStyle)
166
- def text(self, text: str, ra: float, dec: float, style: LabelStyle = None):
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
+ ):
167
186
  """
168
187
  Plots text
169
188
 
@@ -172,6 +191,7 @@ class BasePlot(ABC):
172
191
  ra: Right ascension of text (0...24)
173
192
  dec: Declination of text (-90...90)
174
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
175
195
  """
176
196
  style = style or LabelStyle()
177
197
  self._text(
@@ -179,6 +199,7 @@ class BasePlot(ABC):
179
199
  dec,
180
200
  text,
181
201
  **style.matplot_kwargs(self._size_multiplier),
202
+ hide_on_collision=hide_on_collision,
182
203
  xytext=(style.offset_x, style.offset_y),
183
204
  textcoords="offset pixels",
184
205
  )
@@ -271,7 +292,7 @@ class BasePlot(ABC):
271
292
 
272
293
  Args:
273
294
  filename: Filename of exported file
274
- format: Format of file: "png" or "svg"
295
+ format: Format of file (options are "png", "jpeg", or "svg")
275
296
  padding: Padding (in inches) around the image
276
297
  **kwargs: Any keyword arguments to pass through to matplotlib's `savefig` method
277
298
 
@@ -480,7 +501,7 @@ class BasePlot(ABC):
480
501
  """Plots a polygon of points
481
502
 
482
503
  Args:
483
- points: List of polygon points `[(ra, dec), ...]`
504
+ points: List of polygon points `[(ra, dec), ...]` - **must be in counterclockwise order**
484
505
  style: Style of polygon
485
506
  """
486
507
  _points = [(ra * 15, dec) for ra, dec in points]
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
- TYCHO_1 = DATA_PATH / "stars.tycho-1.gz.parquet"
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"
@@ -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)
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
- TYCHO_1 = "tycho-1"
121
- """Tycho-1 Catalog = 1,055,115 stars"""
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
- def load_hipparcos():
125
- return read_parquet(DataFiles.HIPPARCOS)
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
- def load_tycho1():
129
- df = read_parquet(DataFiles.TYCHO_1)
130
- df = df.assign(
131
- ra_degrees=df["ra_hours"] * 15.0,
132
- epoch_year=1991.25,
133
- )
134
- return df.set_index("hip")
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.TYCHO_1:
139
- return load_tycho1()
140
- elif catalog == StarCatalog.HIPPARCOS:
141
- return load_hipparcos()
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!")