starplot 0.16.1__py2.py3-none-any.whl → 0.17.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 +28 -2
- starplot/base.py +42 -60
- starplot/config.py +41 -9
- starplot/data/bigsky.py +1 -1
- starplot/data/constellations.py +9 -681
- starplot/data/db.py +2 -2
- starplot/data/dsos.py +11 -28
- starplot/data/library/bigsky.0.4.0.stars.mag11.parquet +0 -0
- starplot/data/library/sky.db +0 -0
- starplot/data/stars.py +15 -433
- starplot/data/translations.py +161 -0
- starplot/geometry.py +52 -6
- starplot/horizon.py +18 -12
- starplot/map.py +1 -5
- starplot/mixins.py +283 -0
- starplot/models/__init__.py +19 -7
- starplot/models/base.py +1 -1
- starplot/models/comet.py +332 -0
- starplot/models/constellation.py +10 -0
- starplot/models/dso.py +24 -0
- starplot/{optics.py → models/optics.py} +4 -4
- starplot/models/satellite.py +158 -0
- starplot/models/star.py +10 -0
- starplot/optic.py +24 -13
- starplot/plotters/__init__.py +1 -0
- starplot/plotters/arrow.py +162 -0
- starplot/plotters/constellations.py +34 -56
- starplot/plotters/dsos.py +8 -14
- starplot/plotters/experimental.py +560 -8
- starplot/plotters/legend.py +5 -0
- starplot/plotters/stars.py +7 -16
- starplot/styles/base.py +20 -1
- starplot/styles/extensions.py +10 -1
- starplot/zenith.py +4 -1
- {starplot-0.16.1.dist-info → starplot-0.17.0.dist-info}/METADATA +20 -17
- {starplot-0.16.1.dist-info → starplot-0.17.0.dist-info}/RECORD +40 -36
- /starplot/{observer.py → models/observer.py} +0 -0
- {starplot-0.16.1.dist-info → starplot-0.17.0.dist-info}/WHEEL +0 -0
- {starplot-0.16.1.dist-info → starplot-0.17.0.dist-info}/entry_points.txt +0 -0
- {starplot-0.16.1.dist-info → starplot-0.17.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
LABELS = {
|
|
2
|
+
"en-us": {
|
|
3
|
+
"legend": "legend",
|
|
4
|
+
"star magnitude": "star magnitude",
|
|
5
|
+
"star": "star",
|
|
6
|
+
"deep sky object": "deep sky object",
|
|
7
|
+
"open cluster": "open cluster",
|
|
8
|
+
"globular cluster": "globular cluster",
|
|
9
|
+
"nebula": "nebula",
|
|
10
|
+
"galaxy": "galaxy",
|
|
11
|
+
"dark nebula": "dark nebula",
|
|
12
|
+
"association of stars": "association of stars",
|
|
13
|
+
"double star": "double star",
|
|
14
|
+
"emission nebula": "emission nebula",
|
|
15
|
+
"galaxy pair": "galaxy pair",
|
|
16
|
+
"galaxy triplet": "galaxy triplet",
|
|
17
|
+
"galaxy cluster": "galaxy cluster",
|
|
18
|
+
"group of galaxies": "group of galaxies",
|
|
19
|
+
"hii ionized region": "hii ionized region",
|
|
20
|
+
"nova star": "nova star",
|
|
21
|
+
"planetary nebula": "planetary nebula",
|
|
22
|
+
"reflection nebula": "reflection nebula",
|
|
23
|
+
"star cluster nebula": "star cluster nebula",
|
|
24
|
+
"supernova remnant": "supernova remnant",
|
|
25
|
+
"unknown": "unknown",
|
|
26
|
+
"planet": "planet",
|
|
27
|
+
"mercury": "mercury",
|
|
28
|
+
"venus": "venus",
|
|
29
|
+
"mars": "mars",
|
|
30
|
+
"jupiter": "jupiter",
|
|
31
|
+
"saturn": "saturn",
|
|
32
|
+
"uranus": "uranus",
|
|
33
|
+
"neptune": "neptune",
|
|
34
|
+
"pluto": "pluto",
|
|
35
|
+
"sun": "sun",
|
|
36
|
+
"moon": "moon",
|
|
37
|
+
"north": "north",
|
|
38
|
+
"east": "east",
|
|
39
|
+
"south": "south",
|
|
40
|
+
"west": "west",
|
|
41
|
+
"ecliptic": "ecliptic",
|
|
42
|
+
"celestial equator": "celestial equator",
|
|
43
|
+
"n": "n",
|
|
44
|
+
"e": "e",
|
|
45
|
+
"s": "s",
|
|
46
|
+
"w": "w",
|
|
47
|
+
"milky way": "milky way",
|
|
48
|
+
},
|
|
49
|
+
"fr": {
|
|
50
|
+
"legend": "légende",
|
|
51
|
+
"star magnitude": "magnitude des étoiles",
|
|
52
|
+
"star": "étoile",
|
|
53
|
+
"deep sky object": "objet du ciel profond",
|
|
54
|
+
"open cluster": "amas ouvert",
|
|
55
|
+
"globular cluster": "amas globulaire",
|
|
56
|
+
"nebula": "nébuleuse",
|
|
57
|
+
"galaxy": "galaxie",
|
|
58
|
+
"dark nebula": "nébuleuse obscure",
|
|
59
|
+
"association of stars": "amas d'étoiles",
|
|
60
|
+
"double star": "étoile double",
|
|
61
|
+
"emission nebula": "nébuleuse en émission",
|
|
62
|
+
"galaxy pair": "paire de galaxies",
|
|
63
|
+
"galaxy triplet": "triplet de galaxies",
|
|
64
|
+
"galaxy cluster": "amas de galaxies",
|
|
65
|
+
"group of galaxies": "groupes de galaxies",
|
|
66
|
+
"hii ionized region": "région d'hydrogène ionisé",
|
|
67
|
+
"nova star": "nova",
|
|
68
|
+
"planetary nebula": "nébuleuse planétaire",
|
|
69
|
+
"reflection nebula": "nébuleuse par réflexion",
|
|
70
|
+
"star cluster nebula": "nébuleuse d’amas d’étoiles",
|
|
71
|
+
"supernova remnant": "rémanent de supernova",
|
|
72
|
+
"unknown": "inconnu",
|
|
73
|
+
"planet": "planète",
|
|
74
|
+
"mercury": "mercure",
|
|
75
|
+
"venus": "venus",
|
|
76
|
+
"mars": "mars",
|
|
77
|
+
"jupiter": "jupiter",
|
|
78
|
+
"saturn": "saturne",
|
|
79
|
+
"uranus": "uranus",
|
|
80
|
+
"neptune": "neptune",
|
|
81
|
+
"pluto": "pluton",
|
|
82
|
+
"sun": "soleil",
|
|
83
|
+
"moon": "lune",
|
|
84
|
+
"north": "nord",
|
|
85
|
+
"east": "est",
|
|
86
|
+
"south": "sud",
|
|
87
|
+
"west": "ouest",
|
|
88
|
+
"ecliptic": "écliptique",
|
|
89
|
+
"celestial equator": "équateur céleste",
|
|
90
|
+
"n": "n",
|
|
91
|
+
"e": "e",
|
|
92
|
+
"s": "s",
|
|
93
|
+
"w": "o",
|
|
94
|
+
"milky way": "voie lactée",
|
|
95
|
+
},
|
|
96
|
+
"zh-cn": {
|
|
97
|
+
"legend": "图例",
|
|
98
|
+
"star magnitude": "星等",
|
|
99
|
+
"star": "恒星",
|
|
100
|
+
"deep sky object": "深空天体",
|
|
101
|
+
"open cluster": "疏散星团",
|
|
102
|
+
"globular cluster": "球状星团",
|
|
103
|
+
"nebula": "星云",
|
|
104
|
+
"galaxy": "星系",
|
|
105
|
+
"dark nebula": "暗星云",
|
|
106
|
+
"association of stars": "星协",
|
|
107
|
+
"double star": "双星",
|
|
108
|
+
"emission nebula": "发射星云",
|
|
109
|
+
"galaxy pair": "星系对",
|
|
110
|
+
"galaxy triplet": "三重星系",
|
|
111
|
+
"galaxy cluster": "星系团",
|
|
112
|
+
"group of galaxies": "星系群",
|
|
113
|
+
"hii ionized region": "hii电离氢区",
|
|
114
|
+
"nova star": "新星",
|
|
115
|
+
"planetary nebula": "行星状星云",
|
|
116
|
+
"reflection nebula": "反射星云",
|
|
117
|
+
"star cluster nebula": "星团星云",
|
|
118
|
+
"supernova remnant": "超新星遗迹",
|
|
119
|
+
"unknown": "未知天体",
|
|
120
|
+
"planet": "行星",
|
|
121
|
+
"mercury": "水星",
|
|
122
|
+
"venus": "金星",
|
|
123
|
+
"mars": "火星",
|
|
124
|
+
"jupiter": "木星",
|
|
125
|
+
"saturn": "土星",
|
|
126
|
+
"uranus": "天王星",
|
|
127
|
+
"neptune": "海王星",
|
|
128
|
+
"pluto": "冥王星",
|
|
129
|
+
"sun": "太阳",
|
|
130
|
+
"moon": "月球",
|
|
131
|
+
"north": "北",
|
|
132
|
+
"east": "东",
|
|
133
|
+
"south": "南",
|
|
134
|
+
"west": "西",
|
|
135
|
+
"ecliptic": "黄道",
|
|
136
|
+
"celestial equator": "天赤道",
|
|
137
|
+
"n": "北",
|
|
138
|
+
"e": "东",
|
|
139
|
+
"s": "南",
|
|
140
|
+
"w": "西",
|
|
141
|
+
"milky way": "银河",
|
|
142
|
+
},
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def language_name_column(language: str, column_prefix: str = "name") -> str:
|
|
147
|
+
language_name = language.replace("-", "_").lower()
|
|
148
|
+
|
|
149
|
+
return f"{column_prefix}_{language_name}"
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def translate(text: str, language: str) -> str:
|
|
153
|
+
if not text:
|
|
154
|
+
return text
|
|
155
|
+
|
|
156
|
+
translation = LABELS[language.lower()].get(text.lower())
|
|
157
|
+
|
|
158
|
+
if not translation:
|
|
159
|
+
return text
|
|
160
|
+
|
|
161
|
+
return translation.title()
|
starplot/geometry.py
CHANGED
|
@@ -5,7 +5,7 @@ from typing import Union
|
|
|
5
5
|
from shapely import transform
|
|
6
6
|
from shapely.geometry import Point, Polygon, MultiPolygon
|
|
7
7
|
|
|
8
|
-
from starplot import geod
|
|
8
|
+
from starplot import geod
|
|
9
9
|
|
|
10
10
|
GLOBAL_EXTENT = Polygon(
|
|
11
11
|
[
|
|
@@ -18,17 +18,18 @@ GLOBAL_EXTENT = Polygon(
|
|
|
18
18
|
)
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
def circle(center, diameter_degrees):
|
|
21
|
+
def circle(center, diameter_degrees, num_pts=100):
|
|
22
22
|
points = geod.ellipse(
|
|
23
23
|
center,
|
|
24
24
|
diameter_degrees,
|
|
25
25
|
diameter_degrees,
|
|
26
26
|
angle=0,
|
|
27
|
-
num_pts=
|
|
27
|
+
num_pts=num_pts,
|
|
28
28
|
)
|
|
29
|
-
points = [
|
|
30
|
-
|
|
31
|
-
]
|
|
29
|
+
# points = [
|
|
30
|
+
# (round(24 - utils.lon_to_ra(lon), 4), round(dec, 4)) for lon, dec in points
|
|
31
|
+
# ]
|
|
32
|
+
points = [(round(lon, 4), round(dec, 4)) for lon, dec in points]
|
|
32
33
|
return Polygon(points)
|
|
33
34
|
|
|
34
35
|
|
|
@@ -143,6 +144,51 @@ def split_polygon_at_zero(polygon: Polygon) -> list[Polygon]:
|
|
|
143
144
|
return [polygon]
|
|
144
145
|
|
|
145
146
|
|
|
147
|
+
def split_polygon_at_360(polygon: Polygon) -> list[Polygon]:
|
|
148
|
+
"""
|
|
149
|
+
Splits a polygon at 360 degrees
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
polygon: Polygon that possibly needs splitting
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
List of polygons
|
|
156
|
+
"""
|
|
157
|
+
ra, _ = [p for p in polygon.exterior.coords.xy]
|
|
158
|
+
|
|
159
|
+
if max(ra) > 360:
|
|
160
|
+
polygon_1 = polygon.intersection(
|
|
161
|
+
Polygon(
|
|
162
|
+
[
|
|
163
|
+
[0, -90],
|
|
164
|
+
[360, -90],
|
|
165
|
+
[360, 90],
|
|
166
|
+
[0, 90],
|
|
167
|
+
[0, -90],
|
|
168
|
+
]
|
|
169
|
+
)
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
polygon_2 = polygon.intersection(
|
|
173
|
+
Polygon(
|
|
174
|
+
[
|
|
175
|
+
[360, -90],
|
|
176
|
+
[720, -90],
|
|
177
|
+
[720, 90],
|
|
178
|
+
[360, 90],
|
|
179
|
+
[360, -90],
|
|
180
|
+
]
|
|
181
|
+
)
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
p2_ra, p2_dec = [p for p in polygon_2.exterior.coords.xy]
|
|
185
|
+
p2_new_ra = [ra - 360 for ra in p2_ra]
|
|
186
|
+
|
|
187
|
+
return [polygon_1, Polygon(list(zip(p2_new_ra, p2_dec)))]
|
|
188
|
+
|
|
189
|
+
return [polygon]
|
|
190
|
+
|
|
191
|
+
|
|
146
192
|
def random_point_in_polygon(
|
|
147
193
|
polygon: Polygon, max_iterations: int = 100, seed: int = None
|
|
148
194
|
) -> Point:
|
starplot/horizon.py
CHANGED
|
@@ -3,9 +3,6 @@ import math
|
|
|
3
3
|
from functools import cache
|
|
4
4
|
from typing import Callable
|
|
5
5
|
|
|
6
|
-
import pandas as pd
|
|
7
|
-
import geopandas as gpd
|
|
8
|
-
|
|
9
6
|
from cartopy import crs as ccrs
|
|
10
7
|
from matplotlib import pyplot as plt, patches
|
|
11
8
|
from matplotlib.ticker import FixedLocator, FuncFormatter
|
|
@@ -14,13 +11,14 @@ from shapely import Point, Polygon, MultiPolygon
|
|
|
14
11
|
from starplot.coordinates import CoordinateSystem
|
|
15
12
|
from starplot.base import BasePlot, DPI
|
|
16
13
|
from starplot.mixins import ExtentMaskMixin
|
|
17
|
-
from starplot.observer import Observer
|
|
14
|
+
from starplot.models.observer import Observer
|
|
18
15
|
from starplot.plotters import (
|
|
19
16
|
ConstellationPlotterMixin,
|
|
20
17
|
StarPlotterMixin,
|
|
21
18
|
DsoPlotterMixin,
|
|
22
19
|
MilkyWayPlotterMixin,
|
|
23
20
|
GradientBackgroundMixin,
|
|
21
|
+
LegendPlotterMixin,
|
|
24
22
|
)
|
|
25
23
|
from starplot.styles import (
|
|
26
24
|
PlotStyle,
|
|
@@ -30,8 +28,6 @@ from starplot.styles import (
|
|
|
30
28
|
GradientDirection,
|
|
31
29
|
)
|
|
32
30
|
|
|
33
|
-
pd.options.mode.chained_assignment = None # default='warn'
|
|
34
|
-
|
|
35
31
|
DEFAULT_HORIZON_STYLE = PlotStyle().extend(extensions.MAP)
|
|
36
32
|
|
|
37
33
|
DEFAULT_HORIZON_LABELS = {
|
|
@@ -49,11 +45,13 @@ DEFAULT_HORIZON_LABELS = {
|
|
|
49
45
|
class HorizonPlot(
|
|
50
46
|
BasePlot,
|
|
51
47
|
ExtentMaskMixin,
|
|
48
|
+
# HorizonExtentMaskMixin,
|
|
52
49
|
ConstellationPlotterMixin,
|
|
53
50
|
StarPlotterMixin,
|
|
54
51
|
DsoPlotterMixin,
|
|
55
52
|
MilkyWayPlotterMixin,
|
|
56
53
|
GradientBackgroundMixin,
|
|
54
|
+
LegendPlotterMixin,
|
|
57
55
|
):
|
|
58
56
|
"""Creates a new horizon plot.
|
|
59
57
|
|
|
@@ -122,6 +120,8 @@ class HorizonPlot(
|
|
|
122
120
|
self.logger.debug("Creating HorizonPlot...")
|
|
123
121
|
self.alt = altitude
|
|
124
122
|
self.az = azimuth
|
|
123
|
+
self._alt = altitude
|
|
124
|
+
self._az = azimuth
|
|
125
125
|
self.center_alt = sum(altitude) / 2
|
|
126
126
|
self.center_az = sum(azimuth) / 2
|
|
127
127
|
|
|
@@ -155,16 +155,18 @@ class HorizonPlot(
|
|
|
155
155
|
return pos_az.degrees, pos_alt.degrees
|
|
156
156
|
|
|
157
157
|
def _prepare_star_coords(self, df, limit_by_altaz=True):
|
|
158
|
+
# import geopandas as gpd
|
|
159
|
+
|
|
158
160
|
stars_apparent = self.observe(SkyfieldStar.from_dataframe(df)).apparent()
|
|
159
161
|
nearby_stars_alt, nearby_stars_az, _ = stars_apparent.altaz()
|
|
160
162
|
df["x"], df["y"] = (
|
|
161
163
|
nearby_stars_az.degrees,
|
|
162
164
|
nearby_stars_alt.degrees,
|
|
163
165
|
)
|
|
164
|
-
if limit_by_altaz:
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
166
|
+
# if limit_by_altaz:
|
|
167
|
+
# extent = self._extent_mask_altaz()
|
|
168
|
+
# df["_geometry_az_alt"] = gpd.points_from_xy(df.x, df.y)
|
|
169
|
+
# df = df[df["_geometry_az_alt"].intersects(extent)]
|
|
168
170
|
|
|
169
171
|
return df
|
|
170
172
|
|
|
@@ -373,6 +375,11 @@ class HorizonPlot(
|
|
|
373
375
|
label,
|
|
374
376
|
(x, patch_y + 0.027),
|
|
375
377
|
xycoords=self.ax.transAxes,
|
|
378
|
+
xytext=(
|
|
379
|
+
style.label.offset_x * self.scale,
|
|
380
|
+
style.label.offset_y * self.scale,
|
|
381
|
+
),
|
|
382
|
+
textcoords="offset points",
|
|
376
383
|
**style.label.matplot_kwargs(self.scale),
|
|
377
384
|
clip_on=False,
|
|
378
385
|
)
|
|
@@ -427,7 +434,6 @@ class HorizonPlot(
|
|
|
427
434
|
label_style_kwargs.pop("ha")
|
|
428
435
|
|
|
429
436
|
line_style_kwargs = style.line.matplot_kwargs()
|
|
430
|
-
|
|
431
437
|
gridlines = self.ax.gridlines(
|
|
432
438
|
draw_labels=show_labels,
|
|
433
439
|
x_inline=False,
|
|
@@ -492,7 +498,7 @@ class HorizonPlot(
|
|
|
492
498
|
"|",
|
|
493
499
|
(x, -0.011 * self.scale),
|
|
494
500
|
xycoords=self.ax.transAxes,
|
|
495
|
-
**
|
|
501
|
+
**style.label.matplot_kwargs(self.scale / 2),
|
|
496
502
|
)
|
|
497
503
|
|
|
498
504
|
@cache
|
starplot/map.py
CHANGED
|
@@ -14,7 +14,7 @@ from starplot.coordinates import CoordinateSystem
|
|
|
14
14
|
from starplot import geod
|
|
15
15
|
from starplot.base import BasePlot, DPI
|
|
16
16
|
from starplot.mixins import ExtentMaskMixin
|
|
17
|
-
from starplot.observer import Observer
|
|
17
|
+
from starplot.models.observer import Observer
|
|
18
18
|
from starplot.plotters import (
|
|
19
19
|
ConstellationPlotterMixin,
|
|
20
20
|
StarPlotterMixin,
|
|
@@ -459,10 +459,6 @@ class MapPlot(
|
|
|
459
459
|
self.logger.debug(f"Projection = {self.projection.__class__.__name__.upper()}")
|
|
460
460
|
|
|
461
461
|
self._fit_to_ax()
|
|
462
|
-
|
|
463
|
-
# if self.gradient_preset:
|
|
464
|
-
# self.apply_gradient_background(self.gradient_preset)
|
|
465
|
-
|
|
466
462
|
self._plot_background_clip_path()
|
|
467
463
|
|
|
468
464
|
def _ax_to_radec(self, x, y):
|
starplot/mixins.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from functools import cache
|
|
2
2
|
|
|
3
3
|
from shapely import Polygon, MultiPolygon
|
|
4
|
+
from starplot.profile import profile
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class ExtentMaskMixin:
|
|
@@ -56,6 +57,288 @@ class ExtentMaskMixin:
|
|
|
56
57
|
)
|
|
57
58
|
|
|
58
59
|
|
|
60
|
+
class HorizonExtentMaskMixin:
|
|
61
|
+
"""Experimental"""
|
|
62
|
+
|
|
63
|
+
@cache
|
|
64
|
+
def _extent_mask_original(self):
|
|
65
|
+
"""
|
|
66
|
+
Returns shapely geometry objects of extent (RA = 0...360)
|
|
67
|
+
|
|
68
|
+
If the extent crosses equinox, then a MultiPolygon will be returned
|
|
69
|
+
"""
|
|
70
|
+
if self.ra_max <= 360:
|
|
71
|
+
coords = [
|
|
72
|
+
[self.ra_min, self.dec_min],
|
|
73
|
+
[self.ra_max, self.dec_min],
|
|
74
|
+
[self.ra_max, self.dec_max],
|
|
75
|
+
[self.ra_min, self.dec_max],
|
|
76
|
+
[self.ra_min, self.dec_min],
|
|
77
|
+
]
|
|
78
|
+
return Polygon(coords)
|
|
79
|
+
|
|
80
|
+
else:
|
|
81
|
+
coords_1 = [
|
|
82
|
+
[self.ra_min, self.dec_min],
|
|
83
|
+
[360, self.dec_min],
|
|
84
|
+
[360, self.dec_max],
|
|
85
|
+
[self.ra_min, self.dec_max],
|
|
86
|
+
[self.ra_min, self.dec_min],
|
|
87
|
+
]
|
|
88
|
+
coords_2 = [
|
|
89
|
+
[0, self.dec_min],
|
|
90
|
+
[(self.ra_max - 360), self.dec_min],
|
|
91
|
+
[(self.ra_max - 360), self.dec_max],
|
|
92
|
+
[0, self.dec_max],
|
|
93
|
+
[0, self.dec_min],
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
return MultiPolygon(
|
|
97
|
+
[
|
|
98
|
+
Polygon(coords_1),
|
|
99
|
+
Polygon(coords_2),
|
|
100
|
+
]
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
@cache
|
|
104
|
+
def _extent_mask2(self):
|
|
105
|
+
locations = [
|
|
106
|
+
self.location.at(self.observer.timescale).from_altaz(
|
|
107
|
+
alt_degrees=self.alt[0], az_degrees=self._az[0]
|
|
108
|
+
), # lower left
|
|
109
|
+
self.location.at(self.observer.timescale).from_altaz(
|
|
110
|
+
alt_degrees=self.alt[0], az_degrees=self._az[1]
|
|
111
|
+
), # lower right
|
|
112
|
+
self.location.at(self.observer.timescale).from_altaz(
|
|
113
|
+
alt_degrees=self.alt[1], az_degrees=self._az[1]
|
|
114
|
+
), # upper right
|
|
115
|
+
self.location.at(self.observer.timescale).from_altaz(
|
|
116
|
+
alt_degrees=self.alt[1], az_degrees=self.center_az
|
|
117
|
+
), # top center
|
|
118
|
+
# self.location.at(self.observer.timescale).from_altaz(
|
|
119
|
+
# alt_degrees=self.center_alt, az_degrees=self.center_az
|
|
120
|
+
# ), # center
|
|
121
|
+
self.location.at(self.observer.timescale).from_altaz(
|
|
122
|
+
alt_degrees=self.alt[1], az_degrees=self._az[0]
|
|
123
|
+
), # upper left
|
|
124
|
+
self.location.at(self.observer.timescale).from_altaz(
|
|
125
|
+
alt_degrees=self.alt[0], az_degrees=self._az[0]
|
|
126
|
+
), # lower left
|
|
127
|
+
]
|
|
128
|
+
|
|
129
|
+
# self.ra_min = None
|
|
130
|
+
# self.ra_max = None
|
|
131
|
+
# self.dec_max = None
|
|
132
|
+
# self.dec_min = None
|
|
133
|
+
from pprint import pprint
|
|
134
|
+
from shapely import segmentize
|
|
135
|
+
|
|
136
|
+
self.location.at(self.observer.timescale).from_altaz(
|
|
137
|
+
alt_degrees=self.center_alt, az_degrees=self.center_az
|
|
138
|
+
) # center
|
|
139
|
+
print(self.alt)
|
|
140
|
+
print(self._az)
|
|
141
|
+
|
|
142
|
+
coords = []
|
|
143
|
+
for location in locations:
|
|
144
|
+
ra, dec, _ = location.radec()
|
|
145
|
+
ra = ra.hours * 15
|
|
146
|
+
if ra < 180:
|
|
147
|
+
ra += 360
|
|
148
|
+
dec = dec.degrees
|
|
149
|
+
coords.append([float(ra), float(dec)])
|
|
150
|
+
|
|
151
|
+
pprint(coords)
|
|
152
|
+
# coords = reversed(coords)
|
|
153
|
+
extent = Polygon(coords)
|
|
154
|
+
|
|
155
|
+
extent = segmentize(extent, max_segment_length=2)
|
|
156
|
+
|
|
157
|
+
self.polygon(style__fill_color="red", style__alpha=0.3, geometry=extent)
|
|
158
|
+
# print(extent)
|
|
159
|
+
|
|
160
|
+
return extent
|
|
161
|
+
|
|
162
|
+
@profile
|
|
163
|
+
@cache
|
|
164
|
+
def _extent_mask2(self):
|
|
165
|
+
"""generally working"""
|
|
166
|
+
coords = []
|
|
167
|
+
|
|
168
|
+
alt0, alt1 = self._alt
|
|
169
|
+
az0, az1 = self._az
|
|
170
|
+
|
|
171
|
+
for alt in range(0, 90, 5):
|
|
172
|
+
for az in range(az0 - 30, az1 + 30, 5):
|
|
173
|
+
ra, dec, _ = (
|
|
174
|
+
self.location.at(self.observer.timescale)
|
|
175
|
+
.from_altaz(alt_degrees=alt, az_degrees=az)
|
|
176
|
+
.radec()
|
|
177
|
+
)
|
|
178
|
+
ra = ra.hours * 15
|
|
179
|
+
if ra < 180:
|
|
180
|
+
ra += 360
|
|
181
|
+
dec = dec.degrees
|
|
182
|
+
coords.append([float(ra), float(dec)])
|
|
183
|
+
|
|
184
|
+
extent = Polygon(coords)
|
|
185
|
+
from shapely import segmentize
|
|
186
|
+
|
|
187
|
+
extent = segmentize(extent, max_segment_length=1)
|
|
188
|
+
|
|
189
|
+
self.polygon(style__fill_color="red", style__alpha=0.3, geometry=extent)
|
|
190
|
+
# print(extent)
|
|
191
|
+
|
|
192
|
+
return extent
|
|
193
|
+
|
|
194
|
+
@profile
|
|
195
|
+
@cache
|
|
196
|
+
def _extent_mask1(self):
|
|
197
|
+
from shapely import segmentize
|
|
198
|
+
|
|
199
|
+
mask_altaz = self._extent_mask_altaz()
|
|
200
|
+
|
|
201
|
+
altaz_polygons = []
|
|
202
|
+
|
|
203
|
+
if str(mask_altaz.geom_type) == "MultiPolygon":
|
|
204
|
+
altaz_polygons = [
|
|
205
|
+
segmentize(p, max_segment_length=5) for p in mask_altaz.geoms
|
|
206
|
+
]
|
|
207
|
+
else:
|
|
208
|
+
altaz_polygons = [segmentize(mask_altaz, max_segment_length=5)]
|
|
209
|
+
|
|
210
|
+
radec_polygons = []
|
|
211
|
+
|
|
212
|
+
for p in altaz_polygons:
|
|
213
|
+
coords = []
|
|
214
|
+
|
|
215
|
+
for az, alt in list(zip(*p.exterior.coords.xy)):
|
|
216
|
+
ra, dec, _ = (
|
|
217
|
+
self.location.at(self.observer.timescale)
|
|
218
|
+
.from_altaz(alt_degrees=alt, az_degrees=az)
|
|
219
|
+
.radec()
|
|
220
|
+
)
|
|
221
|
+
ra = ra.hours * 15
|
|
222
|
+
if ra < 180:
|
|
223
|
+
ra += 360
|
|
224
|
+
dec = dec.degrees
|
|
225
|
+
coords.append([float(ra), float(dec)])
|
|
226
|
+
|
|
227
|
+
radec_polygons.append(Polygon(coords))
|
|
228
|
+
|
|
229
|
+
mp = MultiPolygon(radec_polygons)
|
|
230
|
+
extent = mp.convex_hull
|
|
231
|
+
|
|
232
|
+
# extent = segmentize(extent, max_segment_length=1)
|
|
233
|
+
|
|
234
|
+
print(extent.area)
|
|
235
|
+
|
|
236
|
+
# self.polygon(
|
|
237
|
+
# style__fill_color="red",
|
|
238
|
+
# style__alpha=0.3,
|
|
239
|
+
# geometry=extent
|
|
240
|
+
# )
|
|
241
|
+
# print(extent)
|
|
242
|
+
|
|
243
|
+
return extent
|
|
244
|
+
|
|
245
|
+
def _axes_to_azalt(self, x: float, y: float) -> tuple[float, float]:
|
|
246
|
+
trans = self.ax.transAxes + self.ax.transData.inverted()
|
|
247
|
+
x_projected, y_projected = self.ax.transAxes.inverted().transform((x, y))
|
|
248
|
+
x_projected, y_projected = trans.transform((x, y)) # axes to data
|
|
249
|
+
az, alt = self._crs.transform_point(x_projected, y_projected, self._proj)
|
|
250
|
+
return float(az), float(alt)
|
|
251
|
+
|
|
252
|
+
@profile
|
|
253
|
+
@cache
|
|
254
|
+
def _extent_mask(self):
|
|
255
|
+
coords = []
|
|
256
|
+
azalt = []
|
|
257
|
+
|
|
258
|
+
az0, az1 = int(self.az[0]), int(self.az[1])
|
|
259
|
+
alt0, alt1 = int(self.alt[0]), int(self.alt[1])
|
|
260
|
+
|
|
261
|
+
for az in range(az0, az1, 5):
|
|
262
|
+
for alt in range(alt0, alt1, 5):
|
|
263
|
+
# ax = x / 100
|
|
264
|
+
# ay = y / 100
|
|
265
|
+
|
|
266
|
+
# az, alt = self._axes_to_azalt(ax, ay)
|
|
267
|
+
|
|
268
|
+
if az > 360:
|
|
269
|
+
az -= 360
|
|
270
|
+
|
|
271
|
+
azalt.append([az, alt])
|
|
272
|
+
ra, dec, _ = (
|
|
273
|
+
self.location.at(self.observer.timescale)
|
|
274
|
+
.from_altaz(alt_degrees=alt, az_degrees=az)
|
|
275
|
+
.radec()
|
|
276
|
+
)
|
|
277
|
+
ra = float(ra.hours * 15)
|
|
278
|
+
dec = float(dec.degrees)
|
|
279
|
+
|
|
280
|
+
if dec > 75:
|
|
281
|
+
dec = 90
|
|
282
|
+
|
|
283
|
+
if ra < 180:
|
|
284
|
+
ra += 360
|
|
285
|
+
coords.append([float(ra), float(dec)])
|
|
286
|
+
|
|
287
|
+
# if prev_ra is not None and abs(ra - prev_ra) > 180:
|
|
288
|
+
# current_polygon_coords += [current_polygon_coords[0]]
|
|
289
|
+
# polygon_coords.append(
|
|
290
|
+
# current_polygon_coords
|
|
291
|
+
# )
|
|
292
|
+
# current_polygon_coords = [[ra, dec]]
|
|
293
|
+
# else:
|
|
294
|
+
# current_polygon_coords.append([ra, dec])
|
|
295
|
+
|
|
296
|
+
# prev_ra = ra
|
|
297
|
+
|
|
298
|
+
# if current_polygon_coords:
|
|
299
|
+
# current_polygon_coords += [current_polygon_coords[0]]
|
|
300
|
+
# polygon_coords.append(current_polygon_coords)
|
|
301
|
+
# print(current_polygon_coords)
|
|
302
|
+
|
|
303
|
+
# print(len(polygon_coords))
|
|
304
|
+
from starplot.geometry import split_polygon_at_360
|
|
305
|
+
|
|
306
|
+
# polygons = split_polygon_at_zero(extent)
|
|
307
|
+
|
|
308
|
+
from shapely import convex_hull, MultiPoint
|
|
309
|
+
from pprint import pprint
|
|
310
|
+
|
|
311
|
+
# extent = MultiPolygon([Polygon(c) for c in polygon_coords])
|
|
312
|
+
# extent = Polygon(coords)
|
|
313
|
+
extent = convex_hull(MultiPoint(coords))
|
|
314
|
+
polygons = split_polygon_at_360(extent)
|
|
315
|
+
|
|
316
|
+
pprint(polygons)
|
|
317
|
+
|
|
318
|
+
# extent = extent.convex_hull
|
|
319
|
+
# from shapely import segmentize
|
|
320
|
+
# polygons = [segmentize(p, max_segment_length=1) for p in polygons]
|
|
321
|
+
mpoly = MultiPolygon(polygons)
|
|
322
|
+
|
|
323
|
+
for p in mpoly.geoms:
|
|
324
|
+
self.polygon(style__fill_color="red", style__alpha=0.3, geometry=p)
|
|
325
|
+
|
|
326
|
+
# print(extent)
|
|
327
|
+
|
|
328
|
+
return mpoly
|
|
329
|
+
|
|
330
|
+
def _is_global_extent(self):
|
|
331
|
+
"""Returns True if the plot's RA/DEC range is the entire celestial sphere"""
|
|
332
|
+
return all(
|
|
333
|
+
[
|
|
334
|
+
self.ra_min == 0,
|
|
335
|
+
self.ra_max == 360,
|
|
336
|
+
self.dec_min == -90,
|
|
337
|
+
self.dec_max == 90,
|
|
338
|
+
]
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
|
|
59
342
|
class CreateMapMixin:
|
|
60
343
|
def create_map(self, height_degrees: float, width_degrees: float, *args, **kwargs):
|
|
61
344
|
"""
|
starplot/models/__init__.py
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
from .
|
|
3
|
-
from .
|
|
4
|
-
from .
|
|
5
|
-
from .
|
|
6
|
-
from .
|
|
7
|
-
from .
|
|
1
|
+
# ruff: noqa: F401,F403
|
|
2
|
+
from .constellation import Constellation
|
|
3
|
+
from .comet import Comet
|
|
4
|
+
from .dso import DSO, DsoType
|
|
5
|
+
from .star import Star
|
|
6
|
+
from .planet import Planet
|
|
7
|
+
from .moon import Moon
|
|
8
|
+
from .sun import Sun
|
|
9
|
+
from .optics import (
|
|
10
|
+
Optic,
|
|
11
|
+
Scope,
|
|
12
|
+
Reflector,
|
|
13
|
+
Refractor,
|
|
14
|
+
Binoculars,
|
|
15
|
+
Camera,
|
|
16
|
+
)
|
|
17
|
+
from .objects import ObjectList
|
|
18
|
+
from .satellite import Satellite
|
|
19
|
+
from .observer import Observer
|