.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/cartopy.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_examples_cartopy.py: ================================ Standalone Cartopy Functionality ================================ This sample script illustrates how to leverage Tropycal's standalone Cartopy functionality alongside its existing data structures to make custom plots and analyses. .. GENERATED FROM PYTHON SOURCE LINES 7-14 .. code-block:: default import datetime as dt from tropycal import tracks, utils import cartopy.crs as ccrs import cartopy.feature as cfeature import matplotlib.pyplot as plt .. GENERATED FROM PYTHON SOURCE LINES 15-23 Reading In HURTDAT2 Dataset --------------------------- Let's start with the HURDAT2 dataset by loading it into memory. By default, this reads in the HURDAT dataset from the National Hurricane Center (NHC) website, unless you specify a local file path using either ``atlantic_url`` for the North Atlantic basin on ``pacific_url`` for the East & Central Pacific basin. HURDAT data is not available for the current year. To include the latest data up through today, the "include_btk" flag needs to be set to True, which reads in preliminary best track data from the NHC website. For this example, we'll set this to False. Let's create an instance of a TrackDataset object, which will store the North Atlantic HURDAT2 dataset in memory. Once we have this we can use its methods for various types of analyses. .. GENERATED FROM PYTHON SOURCE LINES 23-26 .. code-block:: default basin = tracks.TrackDataset(basin='north_atlantic',include_btk=False) .. rst-class:: sphx-glr-script-out .. code-block:: none --> Starting to read in HURDAT2 data --> Completed reading in HURDAT2 data (24.38 seconds) .. GENERATED FROM PYTHON SOURCE LINES 27-32 Reading in storm data --------------------- Individual storms can be retrieved from the dataset by calling the ``get_storm()`` function, which returns an instance of a Storm object. This can be done by either entering a tuple containing the storm name and year, or by the standard tropical cyclone ID (e.g., "AL012019"). Let's retrieve an instance of Hurricane Michael from 2018: .. GENERATED FROM PYTHON SOURCE LINES 32-35 .. code-block:: default storm = basin.get_storm(('michael',2018)) .. GENERATED FROM PYTHON SOURCE LINES 36-37 We now have a Storm object, containing information about its track and intensity data, as well as various methods for subsetting and analyzing it. .. GENERATED FROM PYTHON SOURCE LINES 37-40 .. code-block:: default print(storm) .. rst-class:: sphx-glr-script-out .. code-block:: none Storm Summary: Maximum Wind: 140 knots Minimum Pressure: 919 hPa Start Time: 0600 UTC 07 October 2018 End Time: 1800 UTC 11 October 2018 Variables: time (datetime) [2018-10-06 18:00:00 .... 2018-10-15 18:00:00] extra_obs (int64) [0 .... 0] special (str) [ .... ] type (str) [LO .... EX] lat (float64) [17.8 .... 41.2] lon (float64) [-86.6 .... -10.0] vmax (int64) [25 .... 35] mslp (int64) [1006 .... 1001] wmo_basin (str) [north_atlantic .... north_atlantic] More Information: id: AL142018 operational_id: AL142018 name: MICHAEL year: 2018 season: 2018 basin: north_atlantic source_info: NHC Hurricane Database source: hurdat ace: 12.5 realtime: False invest: False subset: False .. GENERATED FROM PYTHON SOURCE LINES 41-45 Basic Cartopy plot ------------------ Let's make a basic Cartopy map focused over the Gulf of Mexico, with geographic boundaries denoted and land filled in light gray. We'll add Cartopy utility to this plot in later steps. .. GENERATED FROM PYTHON SOURCE LINES 45-64 .. code-block:: default # Create a PlateCarree Cartopy projection proj = ccrs.PlateCarree() # Create an instance of figure and axes fig = plt.figure(figsize=(9,6),dpi=200) ax = plt.axes(projection=proj) # Plot coastlines and political boundaries ax.add_feature(cfeature.STATES.with_scale('50m'), linewidths=0.5, linestyle='solid', edgecolor='k') ax.add_feature(cfeature.BORDERS.with_scale('50m'), linewidths=1.0, linestyle='solid', edgecolor='k') ax.add_feature(cfeature.COASTLINE.with_scale('50m'), linewidths=1.0, linestyle='solid', edgecolor='k') # Fill in continents in light gray ax.add_feature(cfeature.LAND.with_scale('50m'), facecolor='#EEEEEE', edgecolor='face') # Zoom in over the Gulf Coast ax.set_extent([-100,-70,18,37]) .. image-sg:: /examples/images/sphx_glr_cartopy_001.png :alt: cartopy :srcset: /examples/images/sphx_glr_cartopy_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 65-75 Applying Tropycal standalone Cartopy utility -------------------------------------------- In order to apply Tropycal's standalone Cartopy plotting utility to an existing matplotlib axes with a Cartopy projection appended to it, simply use the function ``ax = utils.add_tropycal(ax)``, which appends the following functions to a Cartopy axes: - ``ax.plot_storm()`` - Plot a Storm object on an existing axes - ``ax.plot_two()`` - Plot a Tropical Weather Outlook (TWO) on an existing axes - ``ax.plot_cone()`` - Plot a Tropycal generated cone of uncertainty on an existing axes The next few sections will walk through examples for these functions. .. GENERATED FROM PYTHON SOURCE LINES 77-83 Plotting Storm objects ---------------------- Let's go back to the Storm object for Hurricane Michael that we previously retrieved. Let's make a simple plot of it using ``plot_storm()``. This function behaaves identically to matplotlib's standard ``ax.plot()`` function, except that instead of longitude and latitude coordinates (i.e., x and y), we provide the Storm object. Before we make any new plots, let's define a function to plot boundaries so we don't have to repeatedly type the same lines each time: .. GENERATED FROM PYTHON SOURCE LINES 83-98 .. code-block:: default def plot_boundaries(ax): """This function plots geographic and political boundaries on the provided axes.""" # Plot coastlines and political boundaries ax.add_feature(cfeature.STATES.with_scale('50m'), linewidths=0.5, linestyle='solid', edgecolor='k') ax.add_feature(cfeature.BORDERS.with_scale('50m'), linewidths=1.0, linestyle='solid', edgecolor='k') ax.add_feature(cfeature.COASTLINE.with_scale('50m'), linewidths=1.0, linestyle='solid', edgecolor='k') # Fill in continents in light gray ax.add_feature(cfeature.LAND.with_scale('50m'), facecolor='#EEEEEE', edgecolor='face') # Return axes instance return ax .. GENERATED FROM PYTHON SOURCE LINES 99-100 Now let's make another plot of the Gulf of Mexico, with Hurricane Michael's track colored in a solid black line, and individual observations plotted in blue dots: .. GENERATED FROM PYTHON SOURCE LINES 100-121 .. code-block:: default # Create an instance of figure and axes fig = plt.figure(figsize=(9,6),dpi=200) ax = plt.axes(projection=proj) # We already defined "proj" earlier, so no need to redefine it ax = plot_boundaries(ax) # Append Tropycal functionality to this axes ax = utils.add_tropycal(ax) # Plot Hurricane Michael's track line ax.plot_storm(storm, color='k', linewidth=1.5) # Plot storm dots in blue ax.plot_storm(storm, 'o', ms=8, mfc='blue', mec='none') # Zoom in over the Gulf Coast ax.set_extent([-100,-70,18,37]) # Add title ax.set_title("Hurricane Michael (2018) Track") .. image-sg:: /examples/images/sphx_glr_cartopy_002.png :alt: Hurricane Michael (2018) Track :srcset: /examples/images/sphx_glr_cartopy_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Text(0.5, 1.0, 'Hurricane Michael (2018) Track') .. GENERATED FROM PYTHON SOURCE LINES 122-123 Let's say we want to plot the portion where Michael was a hurricane in a different color, and where it was a non-tropical cyclone in a dashed black line. We can use subsetted Storm objects to accomplish this: .. GENERATED FROM PYTHON SOURCE LINES 123-185 .. code-block:: default # Create an instance of figure and axes fig = plt.figure(figsize=(9,6),dpi=200) ax = plt.axes(projection=proj) ax = plot_boundaries(ax) # Append Tropycal functionality to this axes ax = utils.add_tropycal(ax) # Plot Hurricane Michael's track line ax.plot_storm(storm, color='k', linewidth=1.5) # ------------------------------------------------------------------ # Find all segments where Michael was a hurricane def find_hurricane_segments(storm): # Create empty list to store data data = [] # Loop over all times for i, i_time in enumerate(storm.time): if i == 0: continue # Find where hurricane segment began if storm.vmax[i] >= 64 and storm.vmax[i-1] < 64: data.append([i_time]) # Find where hurricane segment ended elif storm.vmax[i] < 64 and storm.vmax[i-1] >= 64: data[-1].append(storm.time[i-1]) #Return output return data segments = find_hurricane_segments(storm) # Subset the storm for each segment it was a hurricane, and plot a red line for segment in segments: # Subset storm object storm_subset = storm.sel(time=(segment[0],segment[1])) # Plot segment in red ax.plot_storm(storm_subset, color='r', linewidth=2.0) # ------------------------------------------------------------------ # Subset storm to the portion where it was a tropical cyclone storm_tc = storm.sel(stormtype=['SD','SS','TD','TS','HU']) # Plot storm dots only where Michael was a tropical cyclone ax.plot_storm(storm_tc, 'o', ms=8, mfc='blue', mec='none') # ------------------------------------------------------------------ # Zoom in over the Gulf Coast ax.set_extent([-100,-70,18,37]) # Add title ax.set_title("Hurricane Michael (2018) Track") .. image-sg:: /examples/images/sphx_glr_cartopy_003.png :alt: Hurricane Michael (2018) Track :srcset: /examples/images/sphx_glr_cartopy_003.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Text(0.5, 1.0, 'Hurricane Michael (2018) Track') .. GENERATED FROM PYTHON SOURCE LINES 186-190 Plotting Tropical Weather Outlooks ---------------------------------- We can also use Tropycal's standalone plotting functionality to plot Tropical Weather Outlooks (TWOs) on an existing axes. First, let's retrieve a TWO from a past date (e.g., 0600 UTC 19 June 2023): .. GENERATED FROM PYTHON SOURCE LINES 190-195 .. code-block:: default requested_time = dt.datetime(2023,6,19,6) two = utils.get_two_archive(time = requested_time) .. GENERATED FROM PYTHON SOURCE LINES 196-197 Now we can plot this TWO on the axes with a North Atlantic projection. For this example we'll use the default configuration, but the documentation offers more information on how to vary transparency, linewidth and zorder on the plot. .. GENERATED FROM PYTHON SOURCE LINES 197-215 .. code-block:: default # Create an instance of figure and axes fig = plt.figure(figsize=(9,6),dpi=200) ax = plt.axes(projection=proj) # We already defined "proj" earlier, so no need to redefine it ax = plot_boundaries(ax) # Append Tropycal functionality to this axes ax = utils.add_tropycal(ax) # Plot TWO on this axes ax.plot_two(two) # Zoom in over the North Atlantic basin ax.set_extent([-100,-10,0,50]) # Add title ax.set_title(f"{requested_time.strftime('%H%M UTC %d %b %Y')} NHC Tropical Weather Outlook") .. image-sg:: /examples/images/sphx_glr_cartopy_004.png :alt: 0600 UTC 19 Jun 2023 NHC Tropical Weather Outlook :srcset: /examples/images/sphx_glr_cartopy_004.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Possible issue encountered when converting Shape #0 to GeoJSON: Shapefile format requires that polygons contain at least one exterior ring, but the Shape was entirely made up of interior holes (defined by counter-clockwise orientation in the shapefile format). The rings were still included but were encoded as GeoJSON exterior rings instead of holes. Possible issue encountered when converting Shape #0 to GeoJSON: Shapefile format requires that polygons contain at least one exterior ring, but the Shape was entirely made up of interior holes (defined by counter-clockwise orientation in the shapefile format). The rings were still included but were encoded as GeoJSON exterior rings instead of holes. Text(0.5, 1.0, '0600 UTC 19 Jun 2023 NHC Tropical Weather Outlook') .. GENERATED FROM PYTHON SOURCE LINES 216-220 Plotting Cone of Uncertainty ---------------------------- We can use this functionality to plot a cone of uncertainty generated from ``utils.generate_nhc_cone()``. Let's generate a cone of uncertainty for Hurricane Ian from 2022: .. GENERATED FROM PYTHON SOURCE LINES 220-235 .. code-block:: default # Retrieve Hurricane Ian storm = basin.get_storm(('ian',2022)) # Retrieve desired forecast requested_time = dt.datetime(2022, 9, 27, 0) #Create cone dict using default settings cone = utils.generate_nhc_cone( forecast = storm.get_nhc_forecast_dict(requested_time), basin = 'north_atlantic', cone_days = 5, return_xarray = True, ) .. GENERATED FROM PYTHON SOURCE LINES 236-237 We can now plot its track leading up to the requested time, and its cone of uncertainty and associated center line: .. GENERATED FROM PYTHON SOURCE LINES 237-267 .. code-block:: default # Create an instance of figure and axes fig = plt.figure(figsize=(9,6),dpi=200) ax = plt.axes(projection=proj) # We already defined "proj" earlier, so no need to redefine it ax = plot_boundaries(ax) # Append Tropycal functionality to this axes ax = utils.add_tropycal(ax) # Plot observed storm track up to the requested time storm_subset = storm.sel(time=(storm.time[0],requested_time)) ax.plot_storm(storm_subset, color='k', linestyle='dotted') # Plot Hurricane Ian's forecast ax.plot_cone(cone = cone, fillcolor = 'red', alpha = 0.3, plot_center_line = True, center_linecolor = 'blue', center_linestyle = 'dashed') # Plot dot over Ian's location at this time ax.plot(storm_subset.lon[-1], storm_subset.lat[-1], 'o', mfc='k', mec='none', ms=12, transform=ccrs.PlateCarree()) # Zoom in over the Gulf Coast ax.set_extent([-100,-70,18,37]) # Add title ax.set_title("Hurricane Ian (2022) NHC Forecast Cone", loc='left', fontsize=12) ax.set_title(f"Forecast Issued: {requested_time.strftime('%H%M UTC %d %b %Y')}", loc='right', fontsize=10) .. image-sg:: /examples/images/sphx_glr_cartopy_005.png :alt: Hurricane Ian (2022) NHC Forecast Cone, Forecast Issued: 0000 UTC 27 Sep 2022 :srcset: /examples/images/sphx_glr_cartopy_005.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Text(1.0, 1.0, 'Forecast Issued: 0000 UTC 27 Sep 2022') .. rst-class:: sphx-glr-timing **Total running time of the script:** ( 1 minutes 6.787 seconds) .. _sphx_glr_download_examples_cartopy.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: cartopy.py ` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: cartopy.ipynb ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_