starplot 0.13.0__py2.py3-none-any.whl → 0.15.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.
Files changed (74) hide show
  1. starplot/__init__.py +5 -2
  2. starplot/base.py +311 -197
  3. starplot/cli.py +33 -0
  4. starplot/coordinates.py +6 -0
  5. starplot/data/__init__.py +6 -24
  6. starplot/data/bigsky.py +58 -40
  7. starplot/data/constellation_lines.py +827 -0
  8. starplot/data/constellation_stars.py +1501 -0
  9. starplot/data/constellations.py +600 -27
  10. starplot/data/db.py +17 -0
  11. starplot/data/dsos.py +24 -141
  12. starplot/data/stars.py +45 -24
  13. starplot/geod.py +0 -6
  14. starplot/geometry.py +181 -0
  15. starplot/horizon.py +302 -231
  16. starplot/map.py +100 -463
  17. starplot/mixins.py +75 -14
  18. starplot/models/__init__.py +1 -1
  19. starplot/models/base.py +18 -129
  20. starplot/models/constellation.py +55 -32
  21. starplot/models/dso.py +132 -67
  22. starplot/models/moon.py +57 -78
  23. starplot/models/planet.py +44 -69
  24. starplot/models/star.py +91 -60
  25. starplot/models/sun.py +32 -53
  26. starplot/optic.py +21 -18
  27. starplot/plotters/__init__.py +2 -0
  28. starplot/plotters/constellations.py +342 -0
  29. starplot/plotters/dsos.py +49 -68
  30. starplot/plotters/experimental.py +171 -0
  31. starplot/plotters/milkyway.py +39 -0
  32. starplot/plotters/stars.py +126 -122
  33. starplot/profile.py +16 -0
  34. starplot/settings.py +26 -0
  35. starplot/styles/__init__.py +2 -0
  36. starplot/styles/base.py +56 -34
  37. starplot/styles/ext/antique.yml +11 -9
  38. starplot/styles/ext/blue_dark.yml +8 -10
  39. starplot/styles/ext/blue_gold.yml +135 -0
  40. starplot/styles/ext/blue_light.yml +14 -12
  41. starplot/styles/ext/blue_medium.yml +23 -20
  42. starplot/styles/ext/cb_wong.yml +9 -7
  43. starplot/styles/ext/grayscale.yml +4 -3
  44. starplot/styles/ext/grayscale_dark.yml +7 -5
  45. starplot/styles/ext/map.yml +9 -6
  46. starplot/styles/ext/nord.yml +7 -7
  47. starplot/styles/ext/optic.yml +1 -1
  48. starplot/styles/extensions.py +1 -0
  49. starplot/utils.py +19 -0
  50. starplot/warnings.py +21 -0
  51. {starplot-0.13.0.dist-info → starplot-0.15.0.dist-info}/METADATA +19 -18
  52. starplot-0.15.0.dist-info/RECORD +97 -0
  53. starplot-0.15.0.dist-info/entry_points.txt +3 -0
  54. starplot/data/bayer.py +0 -3499
  55. starplot/data/flamsteed.py +0 -2682
  56. starplot/data/library/constellation_borders_inv.gpkg +0 -0
  57. starplot/data/library/constellation_lines_hips.json +0 -709
  58. starplot/data/library/constellation_lines_inv.gpkg +0 -0
  59. starplot/data/library/constellations.gpkg +0 -0
  60. starplot/data/library/constellations_hip.fab +0 -88
  61. starplot/data/library/milkyway.gpkg +0 -0
  62. starplot/data/library/milkyway_inv.gpkg +0 -0
  63. starplot/data/library/ongc.gpkg.zip +0 -0
  64. starplot/data/library/stars.bigsky.mag11.parquet +0 -0
  65. starplot/data/library/stars.hipparcos.parquet +0 -0
  66. starplot/data/messier.py +0 -111
  67. starplot/data/prep/__init__.py +0 -0
  68. starplot/data/prep/constellations.py +0 -108
  69. starplot/data/prep/dsos.py +0 -299
  70. starplot/data/prep/utils.py +0 -16
  71. starplot/models/geometry.py +0 -44
  72. starplot-0.13.0.dist-info/RECORD +0 -101
  73. {starplot-0.13.0.dist-info → starplot-0.15.0.dist-info}/LICENSE +0 -0
  74. {starplot-0.13.0.dist-info → starplot-0.15.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,342 @@
1
+ import numpy as np
2
+
3
+ import rtree
4
+ from shapely import (
5
+ MultiPoint,
6
+ )
7
+ from matplotlib.collections import LineCollection
8
+ from ibis import _
9
+
10
+ from starplot.coordinates import CoordinateSystem
11
+ from starplot.data import constellations as condata, constellation_lines as conlines
12
+ from starplot.data.stars import load as load_stars, StarCatalog
13
+ from starplot.data.constellations import (
14
+ CONSTELLATIONS_FULL_NAMES,
15
+ CONSTELLATION_HIP_IDS,
16
+ )
17
+ from starplot.data.constellation_stars import CONSTELLATION_HIPS
18
+ from starplot.models.constellation import from_tuple as constellation_from_tuple
19
+ from starplot.projections import Projection
20
+ from starplot.profile import profile
21
+ from starplot.styles import PathStyle, LineStyle, LabelStyle
22
+ from starplot.styles.helpers import use_style
23
+ from starplot.utils import points_on_line
24
+ from starplot.geometry import is_wrapped_polygon
25
+
26
+ DEFAULT_AUTO_ADJUST_SETTINGS = {
27
+ "avoid_constellation_lines": False,
28
+ "point_generation_max_iterations": 10,
29
+ "distance_step_size": 2,
30
+ "max_distance": 3_000,
31
+ "label_padding": 6,
32
+ "buffer": 0.3,
33
+ "seed": None,
34
+ }
35
+ """Default settings for auto-adjusting constellation labels"""
36
+
37
+
38
+ class ConstellationPlotterMixin:
39
+ def inbounds_temp(self, x, y):
40
+ data_x, data_y = self._proj.transform_point(x, y, self._geodetic)
41
+ display_x, display_y = self.ax.transData.transform((data_x, data_y))
42
+ return display_x > 0 and display_y > 0
43
+
44
+ @profile
45
+ def _prepare_constellation_stars(self) -> dict[int, tuple[float, float]]:
46
+ """
47
+ Returns dictionary of stars and their position:
48
+
49
+ {hip: (x,y)}
50
+
51
+ Where (x, y) is the plotted coordinate system (RA/DEC or AZ/ALT)
52
+ """
53
+ results = load_stars(
54
+ catalog=StarCatalog.BIG_SKY_MAG11,
55
+ filters=[_.hip.isin(CONSTELLATION_HIPS)],
56
+ )
57
+ df = results.to_pandas()
58
+ df = self._prepare_star_coords(df, limit_by_altaz=False)
59
+
60
+ return {star.hip: (star.x, star.y) for star in df.itertuples()}
61
+
62
+ @profile
63
+ @use_style(LineStyle, "constellation_lines")
64
+ def constellations(
65
+ self,
66
+ style: LineStyle = None,
67
+ where: list = None,
68
+ ):
69
+ """Plots the constellation lines **only**. To plot constellation borders and/or labels, see separate functions for them.
70
+
71
+ **Important:** If you're plotting the constellation lines, then it's good to plot them _first_, because Starplot will use the constellation lines to determine where to place labels that are plotted afterwards (labels will look better if they're not crossing a constellation line).
72
+
73
+ Args:
74
+ style: Styling of the constellations. If None, then the plot's style (specified when creating the plot) will be used
75
+ where: A list of expressions that determine which constellations to plot. See [Selecting Objects](/reference-selecting-objects/) for details.
76
+ """
77
+ self.logger.debug("Plotting constellation lines...")
78
+
79
+ where = where or []
80
+ ctr = 0
81
+
82
+ extent = self._extent_mask()
83
+ results = condata.load(extent=extent, filters=where)
84
+ constellations_df = results.to_pandas()
85
+
86
+ if constellations_df.empty:
87
+ return
88
+
89
+ if getattr(self, "projection", None) in [
90
+ Projection.MERCATOR,
91
+ Projection.MILLER,
92
+ ]:
93
+ transform = self._plate_carree
94
+ else:
95
+ transform = self._geodetic
96
+
97
+ style_kwargs = style.matplot_kwargs(self.scale)
98
+ constellation_points_to_index = []
99
+ lines = []
100
+ constars = self._prepare_constellation_stars()
101
+
102
+ for c in constellations_df.itertuples():
103
+ hiplines = conlines.hips[c.iau_id]
104
+ inbounds = False
105
+
106
+ for s1_hip, s2_hip in hiplines:
107
+ if not constars.get(s2_hip):
108
+ continue
109
+ s1_ra, s1_dec = constars.get(s1_hip)
110
+ s2_ra, s2_dec = constars.get(s2_hip)
111
+
112
+ if s1_ra - s2_ra > 60:
113
+ s2_ra += 360
114
+ elif s2_ra - s1_ra > 60:
115
+ s1_ra += 360
116
+
117
+ x1, x2 = s1_ra, s2_ra
118
+ y1, y2 = s1_dec, s2_dec
119
+ if not inbounds and (
120
+ self._in_bounds_xy(x1, y1) or self._in_bounds_xy(x2, y2)
121
+ ):
122
+ inbounds = True
123
+ elif not inbounds:
124
+ continue
125
+
126
+ if self._coordinate_system == CoordinateSystem.RA_DEC:
127
+ x1 *= -1
128
+ x2 *= -1
129
+
130
+ lines.append([(x1, y1), (x2, y2)])
131
+
132
+ start = self._proj.transform_point(x1, y1, self._geodetic)
133
+ end = self._proj.transform_point(x2, y2, self._geodetic)
134
+ radius = style.width or 1
135
+
136
+ if any([np.isnan(n) for n in start + end]):
137
+ continue
138
+
139
+ for x, y in points_on_line(start, end, 25):
140
+ display_x, display_y = self.ax.transData.transform((x, y))
141
+ if display_x < 0 or display_y < 0:
142
+ continue
143
+ constellation_points_to_index.append(
144
+ (
145
+ ctr,
146
+ (
147
+ display_x - radius,
148
+ display_y - radius,
149
+ display_x + radius,
150
+ display_y + radius,
151
+ ),
152
+ None,
153
+ )
154
+ )
155
+ ctr += 1
156
+
157
+ if inbounds:
158
+ obj = constellation_from_tuple(c)
159
+ self._objects.constellations.append(obj)
160
+
161
+ style_kwargs = style.matplot_line_collection_kwargs(self.scale)
162
+
163
+ line_collection = LineCollection(
164
+ lines,
165
+ **style_kwargs,
166
+ transform=transform,
167
+ clip_on=True,
168
+ clip_path=self._background_clip_path,
169
+ gid="constellations-line",
170
+ )
171
+
172
+ self.ax.add_collection(line_collection)
173
+
174
+ if self._constellations_rtree.get_size() == 0:
175
+ self._constellations_rtree = rtree.index.Index(
176
+ constellation_points_to_index
177
+ )
178
+ else:
179
+ for bbox in constellation_points_to_index:
180
+ self._constellations_rtree.insert(
181
+ 0,
182
+ bbox,
183
+ None,
184
+ )
185
+
186
+ def _plot_constellation_labels(
187
+ self,
188
+ style: PathStyle = None,
189
+ labels: dict[str, str] = CONSTELLATIONS_FULL_NAMES,
190
+ ):
191
+ """
192
+ TODO:
193
+ 1. plot label, if removed then get size in display coords
194
+ 2. generate random points in polygon, convert to display coords, test for intersections
195
+ 3. plot best score
196
+
197
+ problem = constellations usually plotted first, so wont have star data (or could use stars from constellations only?)
198
+
199
+ constellation names CAN cross lines but not stars
200
+
201
+ """
202
+ style = style or self.style.constellation.label
203
+ self._constellation_labels = []
204
+
205
+ for con in condata.iterator():
206
+ _, ra, dec = condata.get(con)
207
+ text = labels.get(con.lower())
208
+ label = self.text(
209
+ text,
210
+ ra,
211
+ dec,
212
+ style,
213
+ hide_on_collision=False,
214
+ # hide_on_collision=self.hide_colliding_labels,
215
+ gid="constellations-label-name",
216
+ )
217
+ if label is not None:
218
+ self._constellation_labels.append(label)
219
+
220
+ @profile
221
+ @use_style(LineStyle, "constellation_borders")
222
+ def constellation_borders(self, style: LineStyle = None):
223
+ """Plots the constellation borders
224
+
225
+ Args:
226
+ style: Styling of the constellation borders. If None, then the plot's style (specified when creating the plot) will be used
227
+ """
228
+ extent = self._extent_mask()
229
+ results = condata.load_borders(extent=extent)
230
+ borders_df = results.to_pandas()
231
+
232
+ if borders_df.empty:
233
+ return
234
+
235
+ border_lines = []
236
+ geometries = [line.geometry for line in borders_df.itertuples()]
237
+
238
+ for ls in geometries:
239
+ if ls.length < 80:
240
+ ls = ls.segmentize(1)
241
+
242
+ xy = [c for c in ls.coords]
243
+
244
+ if self._coordinate_system == CoordinateSystem.RA_DEC:
245
+ border_lines.append(xy)
246
+
247
+ elif self._coordinate_system == CoordinateSystem.AZ_ALT:
248
+ coords = [self._prepare_coords(*p) for p in xy]
249
+ border_lines.append(coords)
250
+
251
+ else:
252
+ raise ValueError("Unrecognized coordinate system")
253
+
254
+ line_collection = LineCollection(
255
+ border_lines,
256
+ **style.matplot_line_collection_kwargs(self.scale),
257
+ transform=self._crs,
258
+ clip_on=True,
259
+ clip_path=self._background_clip_path,
260
+ gid="constellations-border",
261
+ )
262
+ self.ax.add_collection(line_collection)
263
+
264
+ def _constellation_labels_auto(self, style, labels, settings):
265
+ for constellation in self.objects.constellations:
266
+ constellation_line_stars = [
267
+ s
268
+ for s in self.objects.stars
269
+ if s.hip in CONSTELLATION_HIP_IDS[constellation.iau_id]
270
+ ]
271
+ if not constellation_line_stars:
272
+ continue
273
+
274
+ if is_wrapped_polygon(constellation.boundary):
275
+ starpoints = []
276
+ ra, dec = zip(*[(s.ra, s.dec) for s in constellation_line_stars])
277
+ new_ra = [r - 360 if r > 300 else r for r in ra]
278
+ starpoints = list(zip(new_ra, dec))
279
+
280
+ else:
281
+ ra, dec = zip(*[(s.ra, s.dec) for s in constellation_line_stars])
282
+ starpoints = list(zip(ra, dec))
283
+
284
+ points_line = MultiPoint(starpoints)
285
+ centroid = points_line.centroid
286
+ text = labels.get(constellation.iau_id)
287
+
288
+ self.text(
289
+ text,
290
+ centroid.x,
291
+ centroid.y,
292
+ style,
293
+ hide_on_collision=self.hide_colliding_labels,
294
+ area=constellation.boundary, # TODO : make this intersection with clip path
295
+ auto_adjust_settings=settings,
296
+ gid="constellations-label-name",
297
+ )
298
+
299
+ def _constellation_labels_static(self, style, labels):
300
+ for con in condata.iterator():
301
+ _, ra, dec = condata.get(con)
302
+ text = labels.get(con.lower())
303
+ self.text(
304
+ text,
305
+ ra,
306
+ dec,
307
+ style,
308
+ hide_on_collision=self.hide_colliding_labels,
309
+ gid="constellations-label-name",
310
+ )
311
+
312
+ @profile
313
+ @use_style(LabelStyle, "constellation_labels")
314
+ def constellation_labels(
315
+ self,
316
+ style: LabelStyle = None,
317
+ labels: dict[str, str] = CONSTELLATIONS_FULL_NAMES,
318
+ auto_adjust: bool = True,
319
+ auto_adjust_settings: dict = DEFAULT_AUTO_ADJUST_SETTINGS,
320
+ ):
321
+ """
322
+ Plots constellation labels.
323
+
324
+ It's good to plot these last because they're area-based labels (vs point-based, like for star names), and area-based labels have more freedom to move around. If you plot area-based labels first, then it would limit the available space for point-based labels.
325
+
326
+ Args:
327
+ style: Styling of the constellation labels. If None, then the plot's style (specified when creating the plot) will be used
328
+ labels: A dictionary where the keys are each constellation's 3-letter IAU abbreviation, and the values are how the constellation will be labeled on the plot.
329
+ auto_adjust: If True (the default), then labels will be automatically adjusted to avoid collisions with other labels and stars **Important: you must plot stars and constellations first for this to work**. This uses a fairly simple method: for each constellation it finds the centroid of all plotted constellation stars with lines and then generates random points in the constellation boundary starting at the centroid and then progressively increasing the distance from the centroid.
330
+ auto_adjust_settings: Optional settings for the auto adjustment algorithm.
331
+
332
+ TODO:
333
+ make this work without plotting constellations first
334
+
335
+ """
336
+
337
+ if auto_adjust:
338
+ settings = DEFAULT_AUTO_ADJUST_SETTINGS
339
+ settings.update(auto_adjust_settings)
340
+ self._constellation_labels_auto(style, labels, settings=settings)
341
+ else:
342
+ self._constellation_labels_static(style, labels)
starplot/plotters/dsos.py CHANGED
@@ -1,24 +1,22 @@
1
- from functools import cache
2
1
  from typing import Callable, Mapping
3
2
 
3
+ from ibis import _
4
+ import numpy as np
5
+
4
6
  from starplot.data.dsos import (
7
+ DSO_LABELS_DEFAULT,
8
+ DsoLabelMaker,
9
+ load,
10
+ )
11
+ from starplot.models.dso import (
12
+ DSO,
5
13
  DsoType,
14
+ from_tuple,
6
15
  ONGC_TYPE_MAP,
7
16
  DSO_LEGEND_LABELS,
8
- DSO_LABELS_DEFAULT,
9
- DsoLabelMaker,
10
- load_ongc,
11
17
  )
12
- from starplot.models.dso import DSO, from_tuple
13
18
  from starplot.styles import MarkerSymbolEnum
14
-
15
-
16
- def _where(*args, **kwargs):
17
- where = kwargs.pop("where", [])
18
-
19
- if mag := kwargs.pop("mag", None):
20
- where.append(DSO.magnitude.is_null() | (DSO.magnitude <= mag))
21
- return where
19
+ from starplot.profile import profile
22
20
 
23
21
 
24
22
  class DsoPlotterMixin:
@@ -29,40 +27,37 @@ class DsoPlotterMixin:
29
27
  coords.append(coords[0])
30
28
  self._polygon(coords, style.marker.to_polygon_style(), closed=False)
31
29
 
32
- def messier(self, *args, **kwargs):
30
+ def messier(self, **kwargs):
33
31
  """
34
32
  Plots Messier objects
35
33
 
36
34
  This is just a small wrapper around the `dsos()` function, so any `kwargs` will be passed through.
37
35
  """
38
- where = _where(**kwargs)
39
- where.append(DSO.m.is_not_null())
40
- kwargs.pop("where", None)
36
+ where = kwargs.pop("where", [])
37
+ where.append(_.m.notnull())
41
38
  self.dsos(where=where, **kwargs)
42
39
 
43
- def open_clusters(self, *args, **kwargs):
40
+ def open_clusters(self, **kwargs):
44
41
  """
45
42
  Plots open clusters
46
43
 
47
44
  This is just a small wrapper around the `dsos()` function, so any `kwargs` will be passed through.
48
45
  """
49
- where = _where(**kwargs)
50
- where.append(DSO.type == DsoType.OPEN_CLUSTER)
51
- kwargs.pop("where", None)
46
+ where = kwargs.pop("where", [])
47
+ where.append(_.type == DsoType.OPEN_CLUSTER)
52
48
  self.dsos(where=where, **kwargs)
53
49
 
54
- def globular_clusters(self, *args, **kwargs):
50
+ def globular_clusters(self, **kwargs):
55
51
  """
56
52
  Plots globular clusters
57
53
 
58
54
  This is just a small wrapper around the `dsos()` function, so any `kwargs` will be passed through.
59
55
  """
60
- where = _where(**kwargs)
61
- where.append(DSO.type == DsoType.GLOBULAR_CLUSTER)
62
- kwargs.pop("where", None)
56
+ where = kwargs.pop("where", [])
57
+ where.append(_.type == DsoType.GLOBULAR_CLUSTER)
63
58
  self.dsos(where=where, **kwargs)
64
59
 
65
- def galaxies(self, *args, **kwargs):
60
+ def galaxies(self, **kwargs):
66
61
  """
67
62
  Plots galaxy DSO types:
68
63
 
@@ -77,12 +72,11 @@ class DsoPlotterMixin:
77
72
  DsoType.GALAXY_PAIR,
78
73
  DsoType.GALAXY_TRIPLET,
79
74
  ]
80
- where = _where(**kwargs)
81
- where.append(DSO.type.is_in(galaxy_types))
82
- kwargs.pop("where", None)
75
+ where = kwargs.pop("where", [])
76
+ where.append(_.type.isin(galaxy_types))
83
77
  self.dsos(where=where, **kwargs)
84
78
 
85
- def nebula(self, *args, **kwargs):
79
+ def nebula(self, **kwargs):
86
80
  """
87
81
  Plots nebula DSO types:
88
82
 
@@ -101,50 +95,39 @@ class DsoPlotterMixin:
101
95
  DsoType.STAR_CLUSTER_NEBULA,
102
96
  DsoType.REFLECTION_NEBULA,
103
97
  ]
104
- where = _where(**kwargs)
105
- where.append(DSO.type.is_in(nebula_types))
106
- kwargs.pop("where", None)
98
+ where = kwargs.pop("where", [])
99
+ where.append(_.type.isin(nebula_types))
107
100
  self.dsos(where=where, **kwargs)
108
101
 
109
- @cache
110
- def _load_dsos(self):
111
- return load_ongc(bbox=self._extent_mask())
112
-
102
+ @profile
113
103
  def dsos(
114
104
  self,
115
- mag: float = 8.0,
105
+ where: list = None,
106
+ where_labels: list = None,
116
107
  true_size: bool = True,
117
108
  labels: Mapping[str, str] = DSO_LABELS_DEFAULT,
118
109
  legend_labels: Mapping[DsoType, str] = DSO_LEGEND_LABELS,
119
110
  alpha_fn: Callable[[DSO], float] = None,
120
111
  label_fn: Callable[[DSO], str] = None,
121
- where: list = None,
122
- where_labels: list = None,
123
112
  ):
124
113
  """
125
114
  Plots Deep Sky Objects (DSOs), from OpenNGC
126
115
 
127
116
  Args:
128
- mag: Limiting magnitude of DSOs to plot. For more control of what DSOs to plot, use the `where` kwarg. **Note:** if you pass `mag` and `where` then `mag` will be ignored
117
+ where: A list of expressions that determine which DSOs to plot. See [Selecting Objects](/reference-selecting-objects/) for details.
118
+ where_labels: A list of expressions that determine which DSOs are labeled on the plot. See [Selecting Objects](/reference-selecting-objects/) for details.
129
119
  true_size: If True, then each DSO will be plotted as its true apparent size in the sky (note: this increases plotting time). If False, then the style's marker size will be used. Also, keep in mind not all DSOs have a defined size (according to OpenNGC) -- so these will use the style's marker size.
130
120
  labels: A dictionary that maps DSO names (as specified in OpenNGC) to the label that'll be plotted for that object. By default, the DSO's name in OpenNGC will be used as the label. If you want to hide all labels, then set this arg to `None`.
131
121
  legend_labels: A dictionary that maps a `DsoType` to the legend label that'll be plotted for that type of DSO. If you want to hide all DSO legend labels, then set this arg to `None`.
132
122
  alpha_fn: Callable for calculating the alpha value (aka "opacity") of each DSO. If `None`, then the marker style's alpha will be used.
133
123
  label_fn: Callable for determining the label of each DSO. If `None`, then the names in the `labels` kwarg will be used.
134
- where: A list of expressions that determine which DSOs to plot. See [Selecting Objects](/reference-selecting-objects/) for details.
135
- where_labels: A list of expressions that determine which DSOs are labeled on the plot. See [Selecting Objects](/reference-selecting-objects/) for details.
136
124
  """
137
125
 
138
126
  # TODO: add kwarg styles
139
127
 
140
- self.logger.debug("Plotting DSOs...")
141
-
142
128
  where = where or []
143
129
  where_labels = where_labels or []
144
130
 
145
- if not where:
146
- where = [DSO.magnitude.is_null() | (DSO.magnitude <= mag)]
147
-
148
131
  if labels is None:
149
132
  labels = {}
150
133
  elif type(labels) != DsoLabelMaker:
@@ -155,35 +138,35 @@ class DsoPlotterMixin:
155
138
  else:
156
139
  legend_labels = {**DSO_LEGEND_LABELS, **legend_labels}
157
140
 
158
- nearby_dsos = self._load_dsos() # load_ongc(bbox=self._extent_mask())
159
- # dso_types = [ONGC_TYPE[dtype] for dtype in types]
160
- # nearby_dsos = nearby_dsos[nearby_dsos["type"].isin(dso_types)]
141
+ extent = self._extent_mask()
142
+ dso_results = load(extent=extent, filters=where)
143
+
144
+ dso_results_labeled = dso_results
145
+ for f in where_labels:
146
+ dso_results_labeled = dso_results_labeled.filter(f)
147
+
148
+ label_row_ids = dso_results_labeled.to_pandas()["rowid"].tolist()
149
+
150
+ results_df = dso_results.to_pandas()
151
+ results_df = results_df.replace({np.nan: None})
161
152
 
162
- for d in nearby_dsos.itertuples():
153
+ for d in results_df.itertuples():
163
154
  ra = d.ra_degrees
164
155
  dec = d.dec_degrees
165
156
  dso_type = ONGC_TYPE_MAP[d.type]
166
157
  style = self.style.get_dso_style(dso_type)
167
158
  maj_ax, min_ax, angle = d.maj_ax, d.min_ax, d.angle
168
159
  legend_label = legend_labels.get(dso_type)
169
- magnitude = d.mag_v or d.mag_b or None
170
- magnitude = float(magnitude) if magnitude else None
171
160
  _dso = from_tuple(d)
172
161
  label = labels.get(d.name) if label_fn is None else label_fn(_dso)
173
162
 
174
- if any(
175
- [
176
- style is None,
177
- not all([e.evaluate(_dso) for e in where]),
178
- # not self.in_bounds(ra / 15, dec),
179
- ]
180
- ):
163
+ if style is None:
181
164
  continue
182
165
 
183
166
  _alpha_fn = alpha_fn or (lambda d: style.marker.alpha)
184
167
  style.marker.alpha = _alpha_fn(_dso)
185
168
 
186
- if where_labels and not all([e.evaluate(_dso) for e in where_labels]):
169
+ if _dso._row_id not in label_row_ids:
187
170
  label = None
188
171
 
189
172
  if true_size and d.size_deg2 is not None:
@@ -206,7 +189,7 @@ class DsoPlotterMixin:
206
189
 
207
190
  if style.marker.symbol == MarkerSymbolEnum.SQUARE:
208
191
  self.rectangle(
209
- (ra / 15, dec),
192
+ (ra, dec),
210
193
  min_ax_degrees * 2,
211
194
  maj_ax_degrees * 2,
212
195
  style=poly_style,
@@ -214,7 +197,7 @@ class DsoPlotterMixin:
214
197
  )
215
198
  else:
216
199
  self.ellipse(
217
- (ra / 15, dec),
200
+ (ra, dec),
218
201
  min_ax_degrees * 2,
219
202
  maj_ax_degrees * 2,
220
203
  style=poly_style,
@@ -222,14 +205,12 @@ class DsoPlotterMixin:
222
205
  )
223
206
 
224
207
  if label:
225
- self.text(
226
- label, ra / 15, dec, style.label, gid=f"dso-{d.type}-label"
227
- )
208
+ self.text(label, ra, dec, style.label, gid=f"dso-{d.type}-label")
228
209
 
229
210
  else:
230
211
  # if no major axis, then just plot as a marker
231
212
  self.marker(
232
- ra=ra / 15,
213
+ ra=ra,
233
214
  dec=dec,
234
215
  style=style,
235
216
  label=label,