starplot 0.14.0__py2.py3-none-any.whl → 0.15.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.

Potentially problematic release.


This version of starplot might be problematic. Click here for more details.

Files changed (63) hide show
  1. starplot/__init__.py +3 -1
  2. starplot/base.py +149 -37
  3. starplot/cli.py +33 -0
  4. starplot/data/__init__.py +6 -24
  5. starplot/data/bigsky.py +58 -40
  6. starplot/data/constellation_lines.py +827 -0
  7. starplot/data/constellation_stars.py +1501 -0
  8. starplot/data/constellations.py +43 -32
  9. starplot/data/db.py +17 -0
  10. starplot/data/dsos.py +24 -141
  11. starplot/data/library/{stars.bigsky.mag11.parquet → bigsky.0.4.0.stars.mag11.parquet} +0 -0
  12. starplot/data/library/sky.db +0 -0
  13. starplot/data/stars.py +45 -24
  14. starplot/geod.py +0 -6
  15. starplot/geometry.py +105 -6
  16. starplot/horizon.py +118 -107
  17. starplot/map.py +45 -96
  18. starplot/mixins.py +75 -14
  19. starplot/models/__init__.py +1 -1
  20. starplot/models/base.py +10 -128
  21. starplot/models/constellation.py +55 -32
  22. starplot/models/dso.py +132 -67
  23. starplot/models/moon.py +57 -78
  24. starplot/models/planet.py +44 -69
  25. starplot/models/star.py +91 -60
  26. starplot/models/sun.py +32 -53
  27. starplot/optic.py +14 -17
  28. starplot/plotters/constellations.py +81 -78
  29. starplot/plotters/dsos.py +49 -68
  30. starplot/plotters/experimental.py +1 -1
  31. starplot/plotters/milkyway.py +18 -20
  32. starplot/plotters/stars.py +91 -116
  33. starplot/profile.py +16 -0
  34. starplot/settings.py +26 -0
  35. starplot/styles/__init__.py +2 -0
  36. starplot/styles/base.py +7 -17
  37. starplot/styles/ext/blue_gold.yml +135 -0
  38. starplot/styles/ext/blue_light.yml +5 -4
  39. starplot/styles/ext/blue_medium.yml +11 -7
  40. starplot/styles/extensions.py +1 -0
  41. starplot/warnings.py +5 -0
  42. {starplot-0.14.0.dist-info → starplot-0.15.1.dist-info}/METADATA +11 -11
  43. {starplot-0.14.0.dist-info → starplot-0.15.1.dist-info}/RECORD +46 -54
  44. starplot-0.15.1.dist-info/entry_points.txt +3 -0
  45. starplot/data/bayer.py +0 -3499
  46. starplot/data/flamsteed.py +0 -2682
  47. starplot/data/library/constellation_borders_inv.gpkg +0 -0
  48. starplot/data/library/constellation_lines_hips.json +0 -709
  49. starplot/data/library/constellation_lines_inv.gpkg +0 -0
  50. starplot/data/library/constellations.gpkg +0 -0
  51. starplot/data/library/constellations_hip.fab +0 -88
  52. starplot/data/library/milkyway.gpkg +0 -0
  53. starplot/data/library/milkyway_inv.gpkg +0 -0
  54. starplot/data/library/ongc.gpkg.zip +0 -0
  55. starplot/data/library/stars.hipparcos.parquet +0 -0
  56. starplot/data/messier.py +0 -111
  57. starplot/data/prep/__init__.py +0 -0
  58. starplot/data/prep/constellations.py +0 -108
  59. starplot/data/prep/dsos.py +0 -299
  60. starplot/data/prep/utils.py +0 -16
  61. starplot/models/geometry.py +0 -44
  62. {starplot-0.14.0.dist-info → starplot-0.15.1.dist-info}/LICENSE +0 -0
  63. {starplot-0.14.0.dist-info → starplot-0.15.1.dist-info}/WHEEL +0 -0
starplot/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Star charts and maps of the sky"""
2
2
 
3
- __version__ = "0.14.0"
3
+ __version__ = "0.15.1"
4
4
 
5
5
  from .base import BasePlot # noqa: F401
6
6
  from .map import MapPlot, Projection # noqa: F401
@@ -8,6 +8,7 @@ from .horizon import HorizonPlot # noqa: F401
8
8
  from .optic import OpticPlot # noqa: F401
9
9
  from .models import (
10
10
  DSO, # noqa: F401
11
+ DsoType, # noqa: F401
11
12
  Star, # noqa: F401
12
13
  Constellation, # noqa: F401
13
14
  Planet, # noqa: F401
@@ -16,3 +17,4 @@ from .models import (
16
17
  ObjectList, # noqa: F401
17
18
  )
18
19
  from .styles import * # noqa: F401 F403
20
+ from ibis import _ # noqa: F401 F403
starplot/base.py CHANGED
@@ -33,10 +33,10 @@ from starplot.styles import (
33
33
  )
34
34
  from starplot.styles.helpers import use_style
35
35
  from starplot.geometry import (
36
- unwrap_polygon,
36
+ unwrap_polygon_360,
37
37
  random_point_in_polygon_at_distance,
38
38
  )
39
-
39
+ from starplot.profile import profile
40
40
 
41
41
  LOGGER = logging.getLogger("starplot")
42
42
  LOG_HANDLER = logging.StreamHandler()
@@ -48,7 +48,11 @@ LOGGER.addHandler(LOG_HANDLER)
48
48
 
49
49
 
50
50
  DEFAULT_FOV_STYLE = PolygonStyle(
51
- fill_color=None, edge_color="red", line_style="dashed", edge_width=4, zorder=1000
51
+ fill_color=None,
52
+ edge_color="red",
53
+ line_style=[1, [2, 3]],
54
+ edge_width=3,
55
+ zorder=-1000,
52
56
  )
53
57
  """Default style for plotting scope and bino field of view circles"""
54
58
 
@@ -61,6 +65,7 @@ DPI = 100
61
65
 
62
66
  class BasePlot(ABC):
63
67
  _background_clip_path = None
68
+ _clip_path_polygon: Polygon = None # clip path in display coordinates
64
69
  _coordinate_system = CoordinateSystem.RA_DEC
65
70
 
66
71
  def __init__(
@@ -95,11 +100,13 @@ class BasePlot(ABC):
95
100
  self.dt = dt or timezone("UTC").localize(datetime.now())
96
101
  self._ephemeris_name = ephemeris
97
102
  self.ephemeris = load(ephemeris)
103
+ self.earth = self.ephemeris["earth"]
98
104
 
99
105
  self.labels = []
100
106
  self._labels_rtree = rtree.index.Index()
101
107
  self._constellations_rtree = rtree.index.Index()
102
108
  self._stars_rtree = rtree.index.Index()
109
+ self._markers_rtree = rtree.index.Index()
103
110
 
104
111
  self._background_clip_path = None
105
112
 
@@ -126,6 +133,10 @@ class BasePlot(ABC):
126
133
  def _prepare_coords(self, ra, dec) -> tuple[float, float]:
127
134
  return ra, dec
128
135
 
136
+ def _update_clip_path_polygon(self, buffer=8):
137
+ coords = self._background_clip_path.get_verts()
138
+ self._clip_path_polygon = Polygon(coords).buffer(-1 * buffer)
139
+
129
140
  def _is_label_collision(self, bbox) -> bool:
130
141
  ix = list(self._labels_rtree.intersection(bbox))
131
142
  return len(ix) > 0
@@ -138,11 +149,18 @@ class BasePlot(ABC):
138
149
  ix = list(self._stars_rtree.intersection(bbox))
139
150
  return len(ix) > 0
140
151
 
152
+ def _is_marker_collision(self, bbox) -> bool:
153
+ ix = list(self._markers_rtree.intersection(bbox))
154
+ return len(ix) > 0
155
+
141
156
  def _is_clipped(self, points) -> bool:
142
- radius = -1.5 * int(self._background_clip_path.get_linewidth())
143
- return self._background_clip_path is not None and not all(
144
- self._background_clip_path.contains_points(points, radius=radius)
145
- )
157
+ p = self._clip_path_polygon
158
+
159
+ for x, y in points:
160
+ if not p.contains(Point(x, y)):
161
+ return True
162
+
163
+ return False
146
164
 
147
165
  def _add_label_to_rtree(self, label, extent=None):
148
166
  extent = extent or label.get_window_extent(
@@ -153,6 +171,53 @@ class BasePlot(ABC):
153
171
  0, np.array((extent.x0 - 1, extent.y0 - 1, extent.x1 + 1, extent.y1 + 1))
154
172
  )
155
173
 
174
+ def _is_open_space(
175
+ self,
176
+ bbox: tuple[float, float, float, float],
177
+ padding=0,
178
+ avoid_clipped=True,
179
+ avoid_label_collisions=True,
180
+ avoid_marker_collisions=True,
181
+ avoid_constellation_collision=True,
182
+ ) -> bool:
183
+ """
184
+ Returns true if the boox covers an open space (i.e. no collisions)
185
+
186
+ Args:
187
+ bbox: 4-element tuple of lower left and upper right coordinates
188
+ """
189
+ x0, y0, x1, y1 = bbox
190
+ points = [(x0, y0), (x1, y1)]
191
+ bbox = (
192
+ x0 - padding,
193
+ y0 - padding,
194
+ x1 + padding,
195
+ y1 + padding,
196
+ )
197
+
198
+ if any([np.isnan(c) for c in (x0, y0, x1, y1)]):
199
+ return False
200
+
201
+ if avoid_clipped and self._is_clipped(points):
202
+ return False
203
+
204
+ if avoid_label_collisions and self._is_label_collision(bbox):
205
+ return False
206
+
207
+ if avoid_marker_collisions and (
208
+ self._is_star_collision(bbox) or self._is_marker_collision(bbox)
209
+ ):
210
+ return False
211
+
212
+ if avoid_constellation_collision and self._is_constellation_collision(bbox):
213
+ return False
214
+
215
+ return True
216
+
217
+ def _get_label_bbox(self, label):
218
+ extent = label.get_window_extent(renderer=self.fig.canvas.get_renderer())
219
+ return (extent.x0, extent.y0, extent.x1, extent.y1)
220
+
156
221
  def _maybe_remove_label(
157
222
  self,
158
223
  label,
@@ -171,11 +236,6 @@ class BasePlot(ABC):
171
236
  )
172
237
  points = [(extent.x0, extent.y0), (extent.x1, extent.y1)]
173
238
 
174
- # if label.get_text() == "CANIS MAJOR":
175
- # print(bbox)
176
- # if label.get_text() == "Electra":
177
- # print(bbox)
178
-
179
239
  if any([np.isnan(c) for c in (extent.x0, extent.y0, extent.x1, extent.y1)]):
180
240
  label.remove()
181
241
  return True
@@ -185,7 +245,9 @@ class BasePlot(ABC):
185
245
  return True
186
246
 
187
247
  if remove_on_collision and (
188
- self._is_label_collision(bbox) or self._is_star_collision(bbox)
248
+ self._is_label_collision(bbox)
249
+ or self._is_star_collision(bbox)
250
+ or self._is_marker_collision(bbox)
189
251
  ):
190
252
  label.remove()
191
253
  return True
@@ -344,32 +406,41 @@ class BasePlot(ABC):
344
406
  **kwargs,
345
407
  ) -> None:
346
408
  kwargs["path_effects"] = kwargs.get("path_effects", [self.text_border])
409
+ kwargs["va"] = "center"
410
+ kwargs["ha"] = "center"
347
411
 
348
412
  avoid_constellation_lines = settings.get("avoid_constellation_lines", False)
349
413
  padding = settings.get("label_padding", 3)
350
- buffer = settings.get("buffer", 0.1)
414
+ settings.get("buffer", 0.1)
351
415
  max_distance = settings.get("max_distance", 300)
352
416
  distance_step_size = settings.get("distance_step_size", 1)
353
417
  point_iterations = settings.get("point_generation_max_iterations", 500)
354
418
  random_seed = settings.get("seed")
355
419
 
420
+ attempts = 0
421
+ height = None
422
+ width = None
423
+ bbox = None
356
424
  areas = (
357
425
  [p for p in area.geoms] if "MultiPolygon" == str(area.geom_type) else [area]
358
426
  )
359
427
  new_areas = []
428
+ origin = Point(ra, dec)
360
429
 
361
430
  for a in areas:
362
- unwrapped = unwrap_polygon(a)
363
- buffer = unwrapped.area / 10 * -1 * buffer * self.scale
364
- new_areas.append(unwrapped.buffer(buffer))
431
+ unwrapped = unwrap_polygon_360(a)
432
+ # new_buffer = unwrapped.area / 10 * -1 * buffer * self.scale
433
+ # new_buffer = -1 * buffer * self.scale
434
+ # new_poly = unwrapped.buffer(new_buffer)
435
+ new_areas.append(unwrapped)
365
436
 
366
437
  for d in range(0, max_distance, distance_step_size):
367
- distance = d / 10
438
+ distance = d / 20
368
439
  poly = randrange(len(new_areas))
369
440
  point = random_point_in_polygon_at_distance(
370
441
  new_areas[poly],
371
- Point(ra, dec),
372
- distance,
442
+ origin_point=origin,
443
+ distance=distance,
373
444
  max_iterations=point_iterations,
374
445
  seed=random_seed,
375
446
  )
@@ -378,20 +449,45 @@ class BasePlot(ABC):
378
449
  continue
379
450
 
380
451
  x, y = self._prepare_coords(point.x, point.y)
381
- label = self._text(x, y, text, **kwargs)
382
- removed = self._maybe_remove_label(
383
- label,
384
- remove_on_collision=hide_on_collision,
385
- remove_on_clipped=clip_on,
386
- remove_on_constellation_collision=avoid_constellation_lines,
452
+
453
+ if height and width:
454
+ data_xy = self._proj.transform_point(x, y, self._crs)
455
+ display_x, display_y = self.ax.transData.transform(data_xy)
456
+ bbox = (
457
+ display_x - width / 2,
458
+ display_y - height / 2,
459
+ display_x + width / 2,
460
+ display_y + height / 2,
461
+ )
462
+ label = None
463
+
464
+ else:
465
+ label = self._text(x, y, text, **kwargs)
466
+ bbox = self._get_label_bbox(label)
467
+ height = bbox[3] - bbox[1]
468
+ width = bbox[2] - bbox[0]
469
+
470
+ is_open = self._is_open_space(
471
+ bbox,
387
472
  padding=padding,
473
+ avoid_clipped=clip_on,
474
+ avoid_constellation_collision=avoid_constellation_lines,
475
+ avoid_marker_collisions=hide_on_collision,
476
+ avoid_label_collisions=hide_on_collision,
388
477
  )
389
478
 
390
- # TODO : remove label if not fully inside area?
479
+ # # TODO : remove label if not fully inside area?
480
+
481
+ attempts += 1
482
+
483
+ if is_open and label is None:
484
+ label = self._text(x, y, text, **kwargs)
391
485
 
392
- if not removed:
486
+ if is_open:
393
487
  self._add_label_to_rtree(label)
394
488
  return label
489
+ elif label is not None:
490
+ label.remove()
395
491
 
396
492
  @use_style(LabelStyle)
397
493
  def text(
@@ -522,6 +618,7 @@ class BasePlot(ABC):
522
618
  if self.fig:
523
619
  plt.close(self.fig)
524
620
 
621
+ @profile
525
622
  def export(self, filename: str, format: str = "png", padding: float = 0, **kwargs):
526
623
  """Exports the plot to an image file.
527
624
 
@@ -568,18 +665,35 @@ class BasePlot(ABC):
568
665
  if not skip_bounds_check and not self.in_bounds(ra, dec):
569
666
  return
570
667
 
668
+ # Plot marker
571
669
  x, y = self._prepare_coords(ra, dec)
572
-
670
+ style_kwargs = style.marker.matplot_scatter_kwargs(self.scale)
573
671
  self.ax.scatter(
574
672
  x,
575
673
  y,
576
- **style.marker.matplot_scatter_kwargs(self.scale),
674
+ **style_kwargs,
577
675
  **self._plot_kwargs(),
578
676
  clip_on=True,
579
677
  clip_path=self._background_clip_path,
580
678
  gid=kwargs.get("gid_marker") or "marker",
581
679
  )
582
680
 
681
+ # Add to spatial index
682
+ data_xy = self._proj.transform_point(x, y, self._crs)
683
+ display_x, display_y = self.ax.transData.transform(data_xy)
684
+ if display_x > 0 and display_y > 0:
685
+ radius = style_kwargs.get("s", 1) ** 0.5 / 5
686
+ bbox = np.array(
687
+ (
688
+ display_x - radius,
689
+ display_y - radius,
690
+ display_x + radius,
691
+ display_y + radius,
692
+ )
693
+ )
694
+ self._markers_rtree.insert(0, bbox, None)
695
+
696
+ # Plot label
583
697
  if label:
584
698
  label_style = style.label
585
699
  if label_style.offset_x == "auto" or label_style.offset_y == "auto":
@@ -748,7 +862,6 @@ class BasePlot(ABC):
748
862
  raise NotImplementedError
749
863
 
750
864
  def _polygon(self, points: list, style: PolygonStyle, **kwargs):
751
- points = [geod.to_radec(p) for p in points]
752
865
  points = [self._prepare_coords(*p) for p in points]
753
866
  patch = patches.Polygon(
754
867
  points,
@@ -787,8 +900,7 @@ class BasePlot(ABC):
787
900
  if geometry is not None:
788
901
  points = list(zip(*geometry.exterior.coords.xy))
789
902
 
790
- _points = [(ra * 15, dec) for ra, dec in points]
791
- self._polygon(_points, style, gid=kwargs.get("gid") or "polygon")
903
+ self._polygon(points, style, gid=kwargs.get("gid") or "polygon")
792
904
 
793
905
  if legend_label is not None:
794
906
  self._add_legend_handle_marker(
@@ -1156,11 +1268,11 @@ class BasePlot(ABC):
1156
1268
  inbounds = []
1157
1269
 
1158
1270
  for ra, dec in ecliptic.RA_DECS:
1159
- x0, y0 = self._prepare_coords(ra, dec)
1271
+ x0, y0 = self._prepare_coords(ra * 15, dec)
1160
1272
  x.append(x0)
1161
1273
  y.append(y0)
1162
- if self.in_bounds(ra, dec):
1163
- inbounds.append((ra, dec))
1274
+ if self.in_bounds(ra * 15, dec):
1275
+ inbounds.append((ra * 15, dec))
1164
1276
 
1165
1277
  self.ax.plot(
1166
1278
  x,
@@ -1195,7 +1307,7 @@ class BasePlot(ABC):
1195
1307
  # TODO : handle wrapping
1196
1308
 
1197
1309
  for ra in range(25):
1198
- x0, y0 = self._prepare_coords(ra, 0)
1310
+ x0, y0 = self._prepare_coords(ra * 15, 0)
1199
1311
  x.append(x0)
1200
1312
  y.append(y0)
1201
1313
 
starplot/cli.py ADDED
@@ -0,0 +1,33 @@
1
+ import sys
2
+
3
+ from starplot.styles import fonts
4
+
5
+ COMMANDS = ["setup"]
6
+
7
+
8
+ def setup(options):
9
+ from starplot import settings
10
+ from starplot.data import db, bigsky
11
+
12
+ print("Installing DuckDB spatial extension...")
13
+
14
+ con = db.connect()
15
+ con.load_extension("spatial")
16
+
17
+ fonts.load()
18
+
19
+ print(f"Installed to: {settings.DUCKDB_EXTENSION_PATH}")
20
+
21
+ if "--install-big-sky" in options:
22
+ bigsky.download_if_not_exists()
23
+ print(f"Big Sky Catalog downloaded and installed to: {settings.DOWNLOAD_PATH}")
24
+
25
+
26
+ def main():
27
+ command = sys.argv[1].lower()
28
+
29
+ if command not in COMMANDS:
30
+ print(f"Unrecognized command: {command}")
31
+
32
+ if command == "setup":
33
+ setup(sys.argv[2:])
starplot/data/__init__.py CHANGED
@@ -1,31 +1,13 @@
1
- import os
2
-
3
- from enum import Enum
4
- from pathlib import Path
5
-
6
1
  from skyfield.api import Loader
7
2
 
8
- HERE = Path(__file__).resolve().parent
9
- DATA_PATH = HERE / "library"
10
-
11
- load = Loader(DATA_PATH)
3
+ from starplot import settings
12
4
 
5
+ load = Loader(settings.DATA_PATH)
13
6
 
14
- def env(name, default):
15
- return os.environ.get(name) or default
16
7
 
8
+ class DataFiles:
9
+ BIG_SKY = settings.DOWNLOAD_PATH / "bigsky.0.4.0.stars.parquet"
17
10
 
18
- class DataFiles(str, Enum):
19
- # Built-In Files
20
- CONSTELLATION_LINES = DATA_PATH / "constellation_lines_inv.gpkg"
21
- CONSTELLATION_LINES_HIP = DATA_PATH / "constellation_lines_hips.json"
22
- CONSTELLATION_BORDERS = DATA_PATH / "constellation_borders_inv.gpkg"
23
- MILKY_WAY = DATA_PATH / "milkyway.gpkg"
24
- HIPPARCOS = DATA_PATH / "stars.hipparcos.parquet"
25
- BIG_SKY_MAG11 = DATA_PATH / "stars.bigsky.mag11.parquet"
26
- ONGC = DATA_PATH / "ongc.gpkg.zip"
27
- CONSTELLATIONS = DATA_PATH / "constellations.gpkg"
11
+ BIG_SKY_MAG11 = settings.DATA_PATH / "bigsky.0.4.0.stars.mag11.parquet"
28
12
 
29
- # Downloaded Files
30
- _DOWNLOAD_PATH = Path(env("STARPLOT_DOWNLOAD_PATH", str(DATA_PATH)))
31
- BIG_SKY = _DOWNLOAD_PATH / "stars.bigsky.parquet"
13
+ DATABASE = settings.DATA_PATH / "sky.db"
starplot/data/bigsky.py CHANGED
@@ -1,56 +1,58 @@
1
1
  import os
2
+ from pathlib import Path
2
3
 
3
4
  import pandas as pd
4
5
 
5
- from starplot.data import DATA_PATH, DataFiles, utils
6
+ from starplot import settings
7
+ from starplot.data import DataFiles, utils
6
8
 
7
9
 
8
- BIG_SKY_VERSION = "0.1.0"
10
+ BIG_SKY_VERSION = "0.4.0"
11
+ BIG_SKY_FILENAME = f"bigsky.{BIG_SKY_VERSION}.stars.csv.gz"
12
+ BIG_SKY_PQ_FILENAME = f"bigsky.{BIG_SKY_VERSION}.stars.parquet"
9
13
 
10
- BIG_SKY_FILENAME = "bigsky.stars.csv.gz"
14
+ BIG_SKY_MAG11_FILENAME = f"bigsky.{BIG_SKY_VERSION}.stars.mag11.csv.gz"
15
+ BIG_SKY_MAG11_PQ_FILENAME = f"bigsky.{BIG_SKY_VERSION}.stars.mag11.parquet"
11
16
 
12
- BIG_SKY_URL = f"https://github.com/steveberardi/bigsky/releases/download/v{BIG_SKY_VERSION}/{BIG_SKY_FILENAME}"
13
17
 
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):
18
+ def get_url(version: str = BIG_SKY_VERSION, filename: str = BIG_SKY_FILENAME):
25
19
  return f"https://github.com/steveberardi/bigsky/releases/download/v{version}/{filename}"
26
20
 
27
21
 
28
22
  def download(
29
- filename: str = BIG_SKY_FILENAME,
30
- version: str = BIG_SKY_VERSION,
31
- download_path: str = None,
32
- digits: int = 4,
23
+ url: str = None,
24
+ download_path: str = settings.DOWNLOAD_PATH,
25
+ download_filename: str = BIG_SKY_FILENAME,
26
+ build_file: str = DataFiles.BIG_SKY,
33
27
  ):
34
- download_path = download_path or str(DATA_PATH / filename)
28
+ url = url or get_url()
29
+ download_path = Path(download_path)
30
+
31
+ if not os.path.exists(download_path):
32
+ os.makedirs(download_path)
33
+
34
+ full_download_path = download_path / download_filename
35
35
  utils.download(
36
- url(filename, version),
37
- download_path,
36
+ url,
37
+ full_download_path,
38
38
  "Big Sky Star Catalog",
39
39
  )
40
40
  to_parquet(
41
- download_path,
42
- DataFiles.BIG_SKY,
43
- digits,
41
+ full_download_path,
42
+ build_file,
44
43
  )
45
44
 
46
45
 
47
- def to_parquet(source_path: str, destination_path: str, digits: int = DIGITS):
46
+ def to_parquet(source_path: str, destination_path: str):
47
+ import pyarrow as pa
48
+ import pyarrow.parquet as pq
49
+
48
50
  print("Preparing Big Sky Catalog for Starplot...")
49
51
 
50
52
  df = pd.read_csv(
51
53
  source_path,
52
54
  header=0,
53
- names=[
55
+ usecols=[
54
56
  "tyc_id",
55
57
  "hip_id",
56
58
  "ccdm",
@@ -61,14 +63,11 @@ def to_parquet(source_path: str, destination_path: str, digits: int = DIGITS):
61
63
  "ra_mas_per_year",
62
64
  "dec_mas_per_year",
63
65
  "parallax_mas",
66
+ "constellation",
64
67
  ],
65
68
  compression="gzip",
66
69
  )
67
70
 
68
- df["ra_hours"] = df.apply(
69
- lambda row: round(row.ra_degrees_j2000 / 15, digits), axis=1
70
- )
71
-
72
71
  df = df.assign(epoch_year=2000)
73
72
 
74
73
  df = df.rename(
@@ -79,19 +78,38 @@ def to_parquet(source_path: str, destination_path: str, digits: int = DIGITS):
79
78
  }
80
79
  )
81
80
 
82
- df.to_parquet(destination_path, compression="gzip")
83
-
84
- print(f"Done! {destination_path.value}")
81
+ df = df.sort_values(["magnitude"])
85
82
 
83
+ table = pa.Table.from_pandas(df)
84
+ table = table.drop_columns("__index_level_0__")
86
85
 
87
- def load(path):
88
- if not exists(path):
89
- download(filename=BIG_SKY_ASSETS.get(path))
90
-
91
- df = pd.read_parquet(path)
86
+ pq.write_table(
87
+ table,
88
+ destination_path,
89
+ compression="none",
90
+ sorting_columns=[
91
+ pq.SortingColumn(df.columns.get_loc("magnitude")),
92
+ ],
93
+ )
92
94
 
93
- return df.set_index("tyc_id")
95
+ print(f"Done! {destination_path}")
94
96
 
95
97
 
96
98
  def exists(path) -> bool:
97
99
  return os.path.isfile(path)
100
+
101
+
102
+ def download_if_not_exists(
103
+ filename: str = DataFiles.BIG_SKY,
104
+ url: str = None,
105
+ download_path: str = settings.DOWNLOAD_PATH,
106
+ download_filename: str = BIG_SKY_FILENAME,
107
+ build_file: str = DataFiles.BIG_SKY,
108
+ ):
109
+ if not exists(filename):
110
+ download(
111
+ url=url,
112
+ download_path=download_path,
113
+ download_filename=download_filename,
114
+ build_file=build_file,
115
+ )