starplot 0.20.5__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 +59 -0
- starplot/callables.py +176 -0
- starplot/cli.py +29 -0
- starplot/config.py +80 -0
- starplot/coordinates.py +7 -0
- starplot/data/__init__.py +22 -0
- starplot/data/catalogs.py +356 -0
- starplot/data/constellations.py +71 -0
- starplot/data/db.py +33 -0
- starplot/data/dsos.py +85 -0
- starplot/data/ecliptic.py +201 -0
- starplot/data/library/constellation_names.parquet +0 -0
- starplot/data/library/dso_names.parquet +0 -0
- starplot/data/library/readme.md +1 -0
- starplot/data/library/star_designations.parquet +0 -0
- starplot/data/stars.py +79 -0
- starplot/data/translations.py +408 -0
- starplot/data/utils.py +35 -0
- starplot/geometry.py +319 -0
- starplot/mixins.py +360 -0
- starplot/models/__init__.py +21 -0
- starplot/models/base.py +77 -0
- starplot/models/comet.py +302 -0
- starplot/models/constellation.py +151 -0
- starplot/models/dso.py +317 -0
- starplot/models/milky_way.py +30 -0
- starplot/models/moon.py +130 -0
- starplot/models/objects.py +29 -0
- starplot/models/observer.py +125 -0
- starplot/models/optics.py +342 -0
- starplot/models/planet.py +137 -0
- starplot/models/satellite.py +138 -0
- starplot/models/star.py +253 -0
- starplot/models/sun.py +62 -0
- starplot/plots/__init__.py +7 -0
- starplot/plots/base.py +1023 -0
- starplot/plots/galaxy.py +372 -0
- starplot/plots/horizon.py +543 -0
- starplot/plots/map.py +515 -0
- starplot/plots/optic.py +469 -0
- starplot/plots/zenith.py +217 -0
- starplot/plotters/__init__.py +9 -0
- starplot/plotters/arrow.py +174 -0
- starplot/plotters/constellations.py +298 -0
- starplot/plotters/debug.py +21 -0
- starplot/plotters/dsos.py +294 -0
- starplot/plotters/experimental.py +722 -0
- starplot/plotters/gradients.py +153 -0
- starplot/plotters/legend.py +253 -0
- starplot/plotters/milkyway.py +51 -0
- starplot/plotters/stars.py +319 -0
- starplot/plotters/text.py +802 -0
- starplot/profile.py +16 -0
- starplot/projections.py +184 -0
- starplot/styles/__init__.py +6 -0
- starplot/styles/base.py +1344 -0
- starplot/styles/ext/antique.yml +175 -0
- starplot/styles/ext/blue_dark.yml +163 -0
- starplot/styles/ext/blue_gold.yml +147 -0
- starplot/styles/ext/blue_light.yml +123 -0
- starplot/styles/ext/blue_medium.yml +142 -0
- starplot/styles/ext/blue_night.yml +185 -0
- starplot/styles/ext/cb_wong.yml +124 -0
- starplot/styles/ext/color_print.yml +111 -0
- starplot/styles/ext/gradient_presets.yml +158 -0
- starplot/styles/ext/grayscale.yml +94 -0
- starplot/styles/ext/grayscale_dark.yml +136 -0
- starplot/styles/ext/map.yml +12 -0
- starplot/styles/ext/nord.yml +158 -0
- starplot/styles/ext/optic.yml +20 -0
- starplot/styles/ext/publication.yml +8 -0
- starplot/styles/extensions.py +129 -0
- starplot/styles/fonts-library/gfs-didot/DESCRIPTION.en_us.html +9 -0
- starplot/styles/fonts-library/gfs-didot/GFSDidot-Regular.ttf +0 -0
- starplot/styles/fonts-library/gfs-didot/METADATA.pb +16 -0
- starplot/styles/fonts-library/gfs-didot/OFL.txt +94 -0
- starplot/styles/fonts-library/inter/Inter-Bold.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-BoldItalic.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-ExtraBold.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-ExtraLight.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-ExtraLightItalic.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-Italic.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-Light.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-LightItalic.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-Regular.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-SemiBold.ttf +0 -0
- starplot/styles/fonts-library/inter/Inter-SemiBoldItalic.ttf +0 -0
- starplot/styles/fonts-library/inter/LICENSE.txt +92 -0
- starplot/styles/fonts.py +15 -0
- starplot/styles/helpers.py +93 -0
- starplot/styles/markers.py +308 -0
- starplot/utils.py +169 -0
- starplot/warnings.py +21 -0
- starplot-0.20.5.dist-info/METADATA +146 -0
- starplot-0.20.5.dist-info/RECORD +98 -0
- starplot-0.20.5.dist-info/WHEEL +4 -0
- starplot-0.20.5.dist-info/entry_points.txt +3 -0
- starplot-0.20.5.dist-info/licenses/LICENSE +21 -0
starplot/plots/galaxy.py
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
from functools import cache
|
|
2
|
+
from typing import Callable
|
|
3
|
+
|
|
4
|
+
import pandas as pd
|
|
5
|
+
import numpy as np
|
|
6
|
+
import astropy.units as u
|
|
7
|
+
from astropy.coordinates import SkyCoord
|
|
8
|
+
from cartopy import crs as ccrs
|
|
9
|
+
from matplotlib import pyplot as plt, patches
|
|
10
|
+
from matplotlib.ticker import FixedLocator, FuncFormatter
|
|
11
|
+
from skyfield.api import Star as SkyfieldStar
|
|
12
|
+
from skyfield.framelib import galactic_frame
|
|
13
|
+
|
|
14
|
+
from starplot.coordinates import CoordinateSystem
|
|
15
|
+
from starplot.plots.base import BasePlot, DPI
|
|
16
|
+
from starplot.mixins import ExtentMaskMixin
|
|
17
|
+
from starplot.models.observer import Observer
|
|
18
|
+
from starplot.plotters import (
|
|
19
|
+
ConstellationPlotterMixin,
|
|
20
|
+
StarPlotterMixin,
|
|
21
|
+
DsoPlotterMixin,
|
|
22
|
+
MilkyWayPlotterMixin,
|
|
23
|
+
GradientBackgroundMixin,
|
|
24
|
+
LegendPlotterMixin,
|
|
25
|
+
ArrowPlotterMixin,
|
|
26
|
+
)
|
|
27
|
+
from starplot.plotters.text import CollisionHandler
|
|
28
|
+
from starplot.styles import (
|
|
29
|
+
PlotStyle,
|
|
30
|
+
extensions,
|
|
31
|
+
use_style,
|
|
32
|
+
PathStyle,
|
|
33
|
+
GradientDirection,
|
|
34
|
+
)
|
|
35
|
+
from starplot.profile import profile
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class GalaxyPlot(
|
|
39
|
+
BasePlot,
|
|
40
|
+
ExtentMaskMixin,
|
|
41
|
+
ConstellationPlotterMixin,
|
|
42
|
+
StarPlotterMixin,
|
|
43
|
+
DsoPlotterMixin,
|
|
44
|
+
MilkyWayPlotterMixin,
|
|
45
|
+
LegendPlotterMixin,
|
|
46
|
+
GradientBackgroundMixin,
|
|
47
|
+
ArrowPlotterMixin,
|
|
48
|
+
):
|
|
49
|
+
"""Creates a new galaxy plot.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
center_lon: Central galactic longitude of the Mollweide projection
|
|
53
|
+
observer: Observer instance which specifies a time and place. Defaults to an observer at epoch J2000
|
|
54
|
+
ephemeris: Ephemeris to use for calculating planet positions (see [Skyfield's documentation](https://rhodesmill.org/skyfield/planets.html) for details)
|
|
55
|
+
style: Styling for the plot (colors, sizes, fonts, etc). If `None`, it defaults to `PlotStyle()` with the MAP extension
|
|
56
|
+
resolution: Size (in pixels) of largest dimension of the map
|
|
57
|
+
point_label_handler: Default [CollisionHandler][starplot.CollisionHandler] for point labels.
|
|
58
|
+
area_label_handler: Default [CollisionHandler][starplot.CollisionHandler] for area labels.
|
|
59
|
+
path_label_handler: Default [CollisionHandler][starplot.CollisionHandler] for path labels.
|
|
60
|
+
scale: Scaling factor that will be applied to all relevant sizes in styles (e.g. font size, marker size, line widths, etc). For example, if you want to make everything 2x bigger, then set scale to 2.
|
|
61
|
+
autoscale: If True, then the scale will be automatically set based on resolution
|
|
62
|
+
suppress_warnings: If True (the default), then all warnings will be suppressed
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
GalaxyPlot: A new instance of a GalaxyPlot
|
|
66
|
+
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
_coordinate_system = CoordinateSystem.RA_DEC
|
|
70
|
+
_gradient_direction = GradientDirection.MOLLWEIDE
|
|
71
|
+
|
|
72
|
+
def __init__(
|
|
73
|
+
self,
|
|
74
|
+
center_lon: float = 0,
|
|
75
|
+
observer: Observer = None,
|
|
76
|
+
ephemeris: str = "de421.bsp",
|
|
77
|
+
style: PlotStyle = None,
|
|
78
|
+
resolution: int = 4096,
|
|
79
|
+
point_label_handler: CollisionHandler = None,
|
|
80
|
+
area_label_handler: CollisionHandler = None,
|
|
81
|
+
path_label_handler: CollisionHandler = None,
|
|
82
|
+
scale: float = 1.0,
|
|
83
|
+
autoscale: bool = False,
|
|
84
|
+
suppress_warnings: bool = True,
|
|
85
|
+
*args,
|
|
86
|
+
**kwargs,
|
|
87
|
+
) -> "GalaxyPlot":
|
|
88
|
+
observer = observer or Observer.at_epoch(2000)
|
|
89
|
+
style = style or PlotStyle().extend(extensions.MAP)
|
|
90
|
+
|
|
91
|
+
super().__init__(
|
|
92
|
+
observer,
|
|
93
|
+
ephemeris,
|
|
94
|
+
style,
|
|
95
|
+
resolution,
|
|
96
|
+
point_label_handler=point_label_handler,
|
|
97
|
+
area_label_handler=area_label_handler,
|
|
98
|
+
path_label_handler=path_label_handler,
|
|
99
|
+
scale=scale,
|
|
100
|
+
autoscale=autoscale,
|
|
101
|
+
suppress_warnings=suppress_warnings,
|
|
102
|
+
*args,
|
|
103
|
+
**kwargs,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
self.center_lon = center_lon
|
|
107
|
+
self.logger.debug("Creating GalaxyPlot...")
|
|
108
|
+
self._geodetic = ccrs.Geodetic()
|
|
109
|
+
self._plate_carree = ccrs.PlateCarree()
|
|
110
|
+
|
|
111
|
+
self._crs = ccrs.CRS(
|
|
112
|
+
proj4_params=[
|
|
113
|
+
("proj", "latlong"),
|
|
114
|
+
("axis", "wnu"), # invert
|
|
115
|
+
("a", "6378137"),
|
|
116
|
+
],
|
|
117
|
+
globe=ccrs.Globe(ellipse="sphere", flattening=0),
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
self._init_plot()
|
|
121
|
+
self._calc_position()
|
|
122
|
+
|
|
123
|
+
def _prepare_coords(self, ra, dec) -> (float, float):
|
|
124
|
+
"""Converts RA/DEC to galactic coordinates (degrees)"""
|
|
125
|
+
if ra > 360:
|
|
126
|
+
ra -= 360
|
|
127
|
+
if ra < 0:
|
|
128
|
+
ra += 360
|
|
129
|
+
point = SkyfieldStar(ra_hours=ra / 15, dec_degrees=dec)
|
|
130
|
+
lat, lon, _ = self.observe(point).frame_latlon(galactic_frame)
|
|
131
|
+
|
|
132
|
+
return lon.degrees, lat.degrees
|
|
133
|
+
|
|
134
|
+
def _prepare_coords_many(
|
|
135
|
+
self, coordinates: list, epoch_year: float = 2000
|
|
136
|
+
) -> (float, float):
|
|
137
|
+
"""Converts RA/DEC to AZ/ALT"""
|
|
138
|
+
df = pd.DataFrame(coordinates, columns=["ra", "dec"])
|
|
139
|
+
df["ra_hours"], df["dec_degrees"] = (df.ra / 15, df.dec)
|
|
140
|
+
df["epoch_year"] = epoch_year
|
|
141
|
+
|
|
142
|
+
sf_star = SkyfieldStar.from_dataframe(df)
|
|
143
|
+
position = self.observe(sf_star)
|
|
144
|
+
lat, lon, _ = position.frame_latlon(galactic_frame)
|
|
145
|
+
df["x"], df["y"] = (lon.degrees, lat.degrees)
|
|
146
|
+
|
|
147
|
+
return list(zip(df["x"], df["y"]))
|
|
148
|
+
|
|
149
|
+
def _prepare_star_coords(self, df, limit_by_altaz=True):
|
|
150
|
+
stars_position = self.observe(SkyfieldStar.from_dataframe(df))
|
|
151
|
+
lat, lon, _ = stars_position.frame_latlon(galactic_frame)
|
|
152
|
+
df["x"], df["y"] = (lon.degrees, lat.degrees)
|
|
153
|
+
return df
|
|
154
|
+
|
|
155
|
+
def _plot_kwargs(self) -> dict:
|
|
156
|
+
return dict(transform=self._crs)
|
|
157
|
+
|
|
158
|
+
@cache
|
|
159
|
+
def in_bounds(self, ra, dec) -> bool:
|
|
160
|
+
"""Determine if a coordinate is within the bounds of the plot.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
ra: Right ascension, in hours (0...24)
|
|
164
|
+
dec: Declination, in degrees (-90...90)
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
True if the coordinate is in bounds, otherwise False
|
|
168
|
+
"""
|
|
169
|
+
lon, lat = self._prepare_coords(ra, dec)
|
|
170
|
+
return self.in_bounds_lonlat(lon, lat)
|
|
171
|
+
|
|
172
|
+
def in_bounds_lonlat(self, lon, lat) -> bool:
|
|
173
|
+
"""Determine if a galactic coordinate is within the bounds of the plot.
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
lon: Galactic longitude in degrees (0...360)
|
|
177
|
+
lat: Galactic latitude in degrees (-90...90)
|
|
178
|
+
|
|
179
|
+
Returns:
|
|
180
|
+
True if the coordinate is in bounds, otherwise False
|
|
181
|
+
"""
|
|
182
|
+
x, y = self._proj.transform_point(lon, lat, self._crs)
|
|
183
|
+
data_to_axes = self.ax.transData + self.ax.transAxes.inverted()
|
|
184
|
+
x_axes, y_axes = data_to_axes.transform((x, y))
|
|
185
|
+
return 0 <= x_axes <= 1 and 0 <= y_axes <= 1
|
|
186
|
+
|
|
187
|
+
def _in_bounds_xy(self, x: float, y: float) -> bool:
|
|
188
|
+
return self.in_bounds_lonlat(x, y)
|
|
189
|
+
|
|
190
|
+
def _polygon(self, points, style, **kwargs):
|
|
191
|
+
super()._polygon(points, style, transform=self._crs, **kwargs)
|
|
192
|
+
|
|
193
|
+
def _calc_position(self):
|
|
194
|
+
self.location = self.ephemeris["earth"]
|
|
195
|
+
self.observe = self.location.at(self.observer.timescale).observe
|
|
196
|
+
|
|
197
|
+
self.ra_min = 0
|
|
198
|
+
self.ra_max = 360
|
|
199
|
+
self.dec_min = -90
|
|
200
|
+
self.dec_max = 90
|
|
201
|
+
|
|
202
|
+
self.logger.debug(
|
|
203
|
+
f"Extent = RA ({self.ra_min:.2f}, {self.ra_max:.2f}) DEC ({self.dec_min:.2f}, {self.dec_max:.2f})"
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
@profile
|
|
207
|
+
@use_style(PathStyle, "galactic_equator")
|
|
208
|
+
def galactic_equator(
|
|
209
|
+
self,
|
|
210
|
+
style: PathStyle = None,
|
|
211
|
+
label: str = "GALACTIC EQUATOR",
|
|
212
|
+
num_labels: int = 1,
|
|
213
|
+
collision_handler: CollisionHandler = None,
|
|
214
|
+
):
|
|
215
|
+
"""
|
|
216
|
+
Plots the galactic equator
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
style: Styling of the galactic equator. If None, then the plot's style will be used
|
|
220
|
+
label: How the galactic equator will be labeled on the plot
|
|
221
|
+
num_labels: Max number of labels to plot along the line
|
|
222
|
+
collision_handler: An instance of [CollisionHandler][starplot.CollisionHandler] that describes what to do on label collisions with other labels, markers, etc. If `None`, then the plot's `path_label_handler` will be used.
|
|
223
|
+
"""
|
|
224
|
+
lons = np.array([ra for ra in range(0, 361)]) # galactic longitudes
|
|
225
|
+
lats = np.array([0] * 361) # galactic latitudes
|
|
226
|
+
|
|
227
|
+
coords = SkyCoord(l=lons * u.deg, b=lats * u.deg, frame="galactic")
|
|
228
|
+
coords_eq = coords.icrs
|
|
229
|
+
|
|
230
|
+
ra_values = coords_eq.ra.degree
|
|
231
|
+
dec_values = coords_eq.dec.degree
|
|
232
|
+
|
|
233
|
+
radec = list(zip(ra_values, dec_values))
|
|
234
|
+
|
|
235
|
+
self.line(
|
|
236
|
+
label=label,
|
|
237
|
+
num_labels=num_labels,
|
|
238
|
+
collision_handler=collision_handler,
|
|
239
|
+
style=style,
|
|
240
|
+
coordinates=radec,
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
@use_style(PathStyle, "gridlines")
|
|
244
|
+
def gridlines(
|
|
245
|
+
self,
|
|
246
|
+
style: PathStyle = None,
|
|
247
|
+
show_labels: list = ["left", "right", "bottom"],
|
|
248
|
+
lon_locations: list[float] = None,
|
|
249
|
+
lat_locations: list[float] = None,
|
|
250
|
+
lon_formatter_fn: Callable[[float], str] = None,
|
|
251
|
+
lat_formatter_fn: Callable[[float], str] = None,
|
|
252
|
+
inline: bool = True,
|
|
253
|
+
):
|
|
254
|
+
"""
|
|
255
|
+
Plots gridlines
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
style: Styling of the gridlines. If None, then the plot's style (specified when creating the plot) will be used
|
|
259
|
+
show_labels: List of locations where labels should be shown (options: "left", "right", "top", "bottom")
|
|
260
|
+
az_locations: List of azimuth locations for the gridlines (in degrees, 0...360). Defaults to every 15 degrees
|
|
261
|
+
alt_locations: List of altitude locations for the gridlines (in degrees, -90...90). Defaults to every 10 degrees.
|
|
262
|
+
az_formatter_fn: Callable for creating labels of azimuth gridlines
|
|
263
|
+
alt_formatter_fn: Callable for creating labels of altitude gridlines
|
|
264
|
+
divider_line: If True, then a divider line will be plotted below the azimuth labels on the bottom of the plot (this is helpful when also plotting the horizon)
|
|
265
|
+
show_ticks: If True, then tick marks will be plotted on the horizon path for every `tick_step` degree that is not also a degree label
|
|
266
|
+
tick_step: Step size for tick marks
|
|
267
|
+
"""
|
|
268
|
+
lon_formatter_fn_default = lambda lon: f"{round(lon)}\u00b0 " # noqa: E731
|
|
269
|
+
lat_formatter_fn_default = lambda lat: f"{round(lat)}\u00b0 " # noqa: E731
|
|
270
|
+
|
|
271
|
+
lon_formatter_fn = lon_formatter_fn or lon_formatter_fn_default
|
|
272
|
+
lat_formatter_fn = lat_formatter_fn or lat_formatter_fn_default
|
|
273
|
+
|
|
274
|
+
def lon_formatter(x, pos) -> str:
|
|
275
|
+
if x < 0:
|
|
276
|
+
x += 360
|
|
277
|
+
return lon_formatter_fn(x)
|
|
278
|
+
|
|
279
|
+
def lat_formatter(x, pos) -> str:
|
|
280
|
+
return lat_formatter_fn(x)
|
|
281
|
+
|
|
282
|
+
x_locations = (
|
|
283
|
+
lon_locations
|
|
284
|
+
if lon_locations is not None
|
|
285
|
+
else [x for x in range(0, 360, 15)]
|
|
286
|
+
)
|
|
287
|
+
x_locations = [x - 180 for x in x_locations]
|
|
288
|
+
y_locations = (
|
|
289
|
+
lat_locations
|
|
290
|
+
if lat_locations is not None
|
|
291
|
+
else [y for y in range(-90, 90, 10)]
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
label_style_kwargs = style.label.matplot_kwargs(self.scale)
|
|
295
|
+
label_style_kwargs.pop("va")
|
|
296
|
+
label_style_kwargs.pop("ha")
|
|
297
|
+
|
|
298
|
+
line_style_kwargs = style.line.matplot_kwargs(self.scale)
|
|
299
|
+
gridlines = self.ax.gridlines(
|
|
300
|
+
draw_labels=show_labels,
|
|
301
|
+
x_inline=inline,
|
|
302
|
+
y_inline=inline,
|
|
303
|
+
rotate_labels=False,
|
|
304
|
+
# xpadding=12,
|
|
305
|
+
# ypadding=12,
|
|
306
|
+
gid="gridlines",
|
|
307
|
+
xlocs=FixedLocator(x_locations),
|
|
308
|
+
xformatter=FuncFormatter(lon_formatter),
|
|
309
|
+
xlabel_style=label_style_kwargs,
|
|
310
|
+
ylocs=FixedLocator(y_locations),
|
|
311
|
+
ylabel_style=label_style_kwargs,
|
|
312
|
+
yformatter=FuncFormatter(lat_formatter),
|
|
313
|
+
**line_style_kwargs,
|
|
314
|
+
)
|
|
315
|
+
gridlines.set_zorder(style.line.zorder)
|
|
316
|
+
|
|
317
|
+
@cache
|
|
318
|
+
def _to_ax(self, az: float, alt: float) -> tuple[float, float]:
|
|
319
|
+
"""Converts az/alt to axes coordinates"""
|
|
320
|
+
x, y = self._proj.transform_point(az, alt, self._crs)
|
|
321
|
+
data_to_axes = self.ax.transData + self.ax.transAxes.inverted()
|
|
322
|
+
x_axes, y_axes = data_to_axes.transform((x, y))
|
|
323
|
+
return x_axes, y_axes
|
|
324
|
+
|
|
325
|
+
@cache
|
|
326
|
+
def _ax_to_azalt(self, x: float, y: float) -> tuple[float, float]:
|
|
327
|
+
trans = self.ax.transAxes + self.ax.transData.inverted()
|
|
328
|
+
x_projected, y_projected = trans.transform((x, y)) # axes to data
|
|
329
|
+
az, alt = self._crs.transform_point(x_projected, y_projected, self._proj)
|
|
330
|
+
return float(az), float(alt)
|
|
331
|
+
|
|
332
|
+
def _plot_background_clip_path(self):
|
|
333
|
+
if self.style.has_gradient_background():
|
|
334
|
+
background_color = "#ffffff00"
|
|
335
|
+
self._plot_gradient_background(self.style.background_color)
|
|
336
|
+
else:
|
|
337
|
+
background_color = self.style.background_color.as_hex()
|
|
338
|
+
|
|
339
|
+
self._background_clip_path = patches.Rectangle(
|
|
340
|
+
(0, 0),
|
|
341
|
+
width=1,
|
|
342
|
+
height=1,
|
|
343
|
+
facecolor=background_color,
|
|
344
|
+
linewidth=0,
|
|
345
|
+
fill=True,
|
|
346
|
+
zorder=-3_000,
|
|
347
|
+
transform=self.ax.transAxes,
|
|
348
|
+
)
|
|
349
|
+
self.ax.set_facecolor(background_color)
|
|
350
|
+
|
|
351
|
+
self.ax.add_patch(self._background_clip_path)
|
|
352
|
+
self._update_clip_path_polygon()
|
|
353
|
+
|
|
354
|
+
def _init_plot(self):
|
|
355
|
+
self._proj = ccrs.Mollweide(central_longitude=self.center_lon)
|
|
356
|
+
self._proj.threshold = 100
|
|
357
|
+
self.fig = plt.figure(
|
|
358
|
+
figsize=(self.figure_size, self.figure_size),
|
|
359
|
+
facecolor=self.style.figure_background_color.as_hex(),
|
|
360
|
+
dpi=DPI,
|
|
361
|
+
)
|
|
362
|
+
self.ax = self.fig.add_subplot(1, 1, 1, projection=self._proj)
|
|
363
|
+
self.fig.subplots_adjust(left=0, right=1, top=1, bottom=0)
|
|
364
|
+
|
|
365
|
+
self.ax.xaxis.set_visible(False)
|
|
366
|
+
self.ax.yaxis.set_visible(False)
|
|
367
|
+
self.ax.axis("off")
|
|
368
|
+
|
|
369
|
+
self.ax.set_global()
|
|
370
|
+
|
|
371
|
+
self._fit_to_ax()
|
|
372
|
+
self._plot_background_clip_path()
|