Skip to content

Commit 2e050b3

Browse files
move plotting function to TCTtracks and add basic test
1 parent 8fc1037 commit 2e050b3

File tree

3 files changed

+171
-190
lines changed

3 files changed

+171
-190
lines changed

climada/hazard/plot.py

Lines changed: 0 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -178,136 +178,6 @@ def plot_intensity(
178178

179179
raise ValueError("Provide one event id or one centroid id.")
180180

181-
@staticmethod
182-
def plot_track_density(
183-
hist: np.ndarray,
184-
axis=None,
185-
projection=ccrs.Mollweide(),
186-
add_features: dict = None,
187-
title: str = None,
188-
figsize=(12, 6),
189-
div_cmap=False,
190-
cbar=True,
191-
cbar_kwargs: dict = {
192-
"orientation": "horizontal",
193-
"pad": 0.05,
194-
"shrink": 0.8,
195-
"label": "n° tracks per 1° x 1° grid cell",
196-
},
197-
**kwargs,
198-
):
199-
"""
200-
Plot the track density of tropical cyclone tracks on a customizable world map.
201-
202-
Parameters:
203-
----------
204-
hist: np.ndarray
205-
2D histogram of track density.
206-
axis: GeoAxes, optional
207-
Existing Cartopy axis.
208-
projection: cartopy.crs, optional
209-
Projection for the map.
210-
add_features: dict
211-
Dictionary of map features to add. Keys can be 'land', 'coastline', 'borders', and
212-
'lakes'. Values are Booleans indicating whether to include each feature.
213-
title: str
214-
Title of the plot.
215-
figsize: tuple
216-
Figure size when creating a new figure.
217-
div_cmap: bool, default = False
218-
If True, the colormap will be centered to 0.
219-
cbar: bool, Default = True
220-
If True, the color bar is added
221-
cbar_kwargs: dict
222-
dictionary containing keyword arguments passed to cbar
223-
kwargs:
224-
Additional keyword arguments passed to `ax.contourf`.
225-
226-
Returns:
227-
-------
228-
axis: GeoAxes
229-
The plot axis.
230-
231-
232-
Example:
233-
--------
234-
>>> axis = plot_track_density(
235-
... hist=hist,
236-
... cmap='Spectral_r',
237-
... cbar_kwargs={'shrink': 0.8,
238-
'label': 'Cyclone Density [n° tracks / km²]',
239-
'pad': 0.1},
240-
... add_features={
241-
... 'land': True,
242-
... 'coastline': True,
243-
... 'borders': False,
244-
... 'lakes': False
245-
... },
246-
... title='My Tropical Cyclone Track Density Map',
247-
... figsize=(10, 5),
248-
... levels=20
249-
... )
250-
251-
"""
252-
253-
# Default features
254-
default_features = {
255-
"land": True,
256-
"coastline": True,
257-
"borders": False,
258-
"lakes": False,
259-
}
260-
add_features = add_features or default_features
261-
262-
# Sample data
263-
lon = np.linspace(-180, 180, hist.shape[1])
264-
lat = np.linspace(-90, 90, hist.shape[0])
265-
266-
# Create figure and axis if not provided
267-
if axis is None:
268-
_, axis = plt.subplots(
269-
figsize=figsize, subplot_kw={"projection": projection}
270-
)
271-
272-
# Add requested features
273-
if add_features.get("land", False):
274-
land = cfeature.NaturalEarthFeature(
275-
category="physical",
276-
name="land",
277-
scale="50m",
278-
facecolor="lightgrey",
279-
alpha=0.6,
280-
)
281-
axis.add_feature(land)
282-
if add_features.get("coastline", False):
283-
axis.add_feature(cfeature.COASTLINE, linewidth=0.5)
284-
if add_features.get("borders", False):
285-
axis.add_feature(cfeature.BORDERS, linestyle=":")
286-
if add_features.get("lakes", False):
287-
axis.add_feature(cfeature.LAKES, alpha=0.4, edgecolor="black")
288-
289-
if div_cmap:
290-
norm = mcolors.TwoSlopeNorm(
291-
vmin=np.nanmin(hist), vcenter=0, vmax=np.nanmax(hist)
292-
)
293-
kwargs["norm"] = norm
294-
295-
# contourf = axis.contourf(lon, lat, hist, transform=ccrs.PlateCarree(), **kwargs)
296-
contourf = axis.imshow(
297-
hist,
298-
extent=[lon.min(), lon.max(), lat.min(), lat.max()],
299-
transform=ccrs.PlateCarree(),
300-
origin="lower",
301-
**kwargs,
302-
)
303-
304-
if cbar:
305-
plt.colorbar(contourf, ax=axis, **cbar_kwargs)
306-
if title:
307-
axis.set_title(title, fontsize=16)
308-
309-
return axis
310-
311181
def plot_fraction(self, event=None, centr=None, smooth=True, axis=None, **kwargs):
312182
"""Plot fraction values for a selected event or centroid.
313183

climada/hazard/tc_tracks.py

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,11 @@
3434

3535
# additional libraries
3636
import cartopy.crs as ccrs
37+
import cartopy.feature as cfeature
3738
import cftime
3839
import geopandas as gpd
3940
import matplotlib.cm as cm_mp
41+
import matplotlib.colors as mcolors
4042
import matplotlib.pyplot as plt
4143
import netCDF4 as nc
4244
import numpy as np
@@ -2248,6 +2250,134 @@ def _compute_genesis_density(
22482250
return hist_count
22492251

22502252

2253+
def plot_track_density(
2254+
hist: np.ndarray,
2255+
axis=None,
2256+
projection=ccrs.Mollweide(),
2257+
add_features: dict = None,
2258+
title: str = None,
2259+
figsize=(12, 6),
2260+
div_cmap=False,
2261+
cbar=True,
2262+
cbar_kwargs: dict = {
2263+
"orientation": "horizontal",
2264+
"pad": 0.05,
2265+
"shrink": 0.8,
2266+
"label": "n° tracks per 1° x 1° grid cell",
2267+
},
2268+
**kwargs,
2269+
):
2270+
"""
2271+
Plot the track density of tropical cyclone tracks on a customizable world map.
2272+
2273+
Parameters:
2274+
----------
2275+
hist: np.ndarray
2276+
2D histogram of track density.
2277+
axis: GeoAxes, optional
2278+
Existing Cartopy axis.
2279+
projection: cartopy.crs, optional
2280+
Projection for the map.
2281+
add_features: dict
2282+
Dictionary of map features to add. Keys can be 'land', 'coastline', 'borders', and
2283+
'lakes'. Values are Booleans indicating whether to include each feature.
2284+
title: str
2285+
Title of the plot.
2286+
figsize: tuple
2287+
Figure size when creating a new figure.
2288+
div_cmap: bool, default = False
2289+
If True, the colormap will be centered to 0.
2290+
cbar: bool, Default = True
2291+
If True, the color bar is added
2292+
cbar_kwargs: dict
2293+
dictionary containing keyword arguments passed to cbar
2294+
kwargs:
2295+
Additional keyword arguments passed to `ax.contourf`.
2296+
2297+
Returns:
2298+
-------
2299+
axis: GeoAxes
2300+
The plot axis.
2301+
2302+
2303+
Example:
2304+
--------
2305+
>>> axis = plot_track_density(
2306+
... hist=hist,
2307+
... cmap='Spectral_r',
2308+
... cbar_kwargs={'shrink': 0.8,
2309+
'label': 'Cyclone Density [n° tracks / km²]',
2310+
'pad': 0.1},
2311+
... add_features={
2312+
... 'land': True,
2313+
... 'coastline': True,
2314+
... 'borders': False,
2315+
... 'lakes': False
2316+
... },
2317+
... title='My Tropical Cyclone Track Density Map',
2318+
... figsize=(10, 5),
2319+
... levels=20
2320+
... )
2321+
2322+
"""
2323+
2324+
# Default features
2325+
default_features = {
2326+
"land": True,
2327+
"coastline": True,
2328+
"borders": False,
2329+
"lakes": False,
2330+
}
2331+
add_features = add_features or default_features
2332+
2333+
# Sample data
2334+
lon = np.linspace(-180, 180, hist.shape[1])
2335+
lat = np.linspace(-90, 90, hist.shape[0])
2336+
2337+
# Create figure and axis if not provided
2338+
if axis is None:
2339+
_, axis = plt.subplots(figsize=figsize, subplot_kw={"projection": projection})
2340+
2341+
# Add requested features
2342+
if add_features.get("land", False):
2343+
land = cfeature.NaturalEarthFeature(
2344+
category="physical",
2345+
name="land",
2346+
scale="50m",
2347+
facecolor="lightgrey",
2348+
alpha=0.6,
2349+
)
2350+
axis.add_feature(land)
2351+
if add_features.get("coastline", False):
2352+
axis.add_feature(cfeature.COASTLINE, linewidth=0.5)
2353+
if add_features.get("borders", False):
2354+
axis.add_feature(cfeature.BORDERS, linestyle=":")
2355+
if add_features.get("lakes", False):
2356+
axis.add_feature(cfeature.LAKES, alpha=0.4, edgecolor="black")
2357+
2358+
if div_cmap:
2359+
norm = mcolors.TwoSlopeNorm(
2360+
vmin=np.nanmin(hist), vcenter=0, vmax=np.nanmax(hist)
2361+
)
2362+
kwargs["norm"] = norm
2363+
2364+
# contourf = axis.contourf(lon, lat, hist, transform=ccrs.PlateCarree(), **kwargs)
2365+
contourf = axis.imshow(
2366+
hist,
2367+
extent=[lon.min(), lon.max(), lat.min(), lat.max()],
2368+
transform=ccrs.PlateCarree(),
2369+
origin="lower",
2370+
**kwargs,
2371+
)
2372+
2373+
if cbar:
2374+
plt.colorbar(contourf, ax=axis, **cbar_kwargs)
2375+
if title:
2376+
axis.set_title(title, fontsize=16)
2377+
2378+
return axis
2379+
2380+
22512381
def _raise_if_legacy_or_unknown_hdf5_format(file_name):
22522382
"""Raise an exception if the HDF5 format of the file is not supported
22532383

0 commit comments

Comments
 (0)