AWIPS Tips: Plotting Multiple Datasets from EDEX


Welcome back to AWIPS Tips!

Welcome back to AWIPS Tips! Today we’re going to take a look at another example of python-awips in use. If you aren’t familiar with python-awips, please check out some of our previous blog posts explaining some of the existing functionality. This blog entry will be focused on using multiple datasets from EDEX to plot regional surface observation data.

Many of our previous blog posts have included notebook examples that use the Cartopy.Feature package to draw state boundaries and coastlines. While this is one way to add those features, in this example we’re going to use the maps database in EDEX to draw our state outlines. One benefit of this, is having more of our data coming from the same source, and makes the notebook less dependent on more Python packages.

Since we’re working with three different data types from EDEX, this notebook has defined three separate data requests and data responses. This helps us keep track of all of our data, and allows us to manipulate each data request individually if we want to tweak and re-run portions of the notebook.

To request state boundary information from EDEX we use a data request and response like this:

# Define the maps request
maps_request = DataAccessLayer.newDataRequest('maps')
# filter for multiple states
maps_request.addIdentifier('table', 'mapdata.states')
maps_request.addIdentifier('geomField', 'the_geom')
maps_request.addIdentifier('inLocation', 'true')
maps_request.addIdentifier('locationField', 'state')
maps_response = DataAccessLayer.getGeometryData(maps_request)

Defining a maps request using the maps datatype is fairly straightforward. Two steps are necessary when accessing any of the map tables. First, we must define exactly which table we’re interested in, and that’s done using the table identifier with mapdata.states as the value. Second, the geometry column also must be defined and that’s done with the geomField identifier and the_geom value in this case.

The next few lines are specific to filtering on which states we’d like to retrieve data for. The identifiers inLocation and locationField as well as the setting of the LocationNames all work together to filter on the states we are interested in.

The call to set parameters defines exactly what information we want about each state. We retrieve our data response using the getGeometryData call from the DataAccessLayer.

At this point, we now have the name, geometry, latitude, and longitude for each of the following states: FL, GA, MS, AL, SC, and LA. This notebook is centered around Florida, so we create a new bounding box based on the Florida geometry:

if ob.getString('name') == "Florida":
     bounds = ob.getGeometry().bounds

We then add a bit of a buffer to give more context to the region and create an envelope to use in the future data requests:

# buffer our bounds by +/i degrees lat/lon

# Create envelope geometry
envelope = Polygon([(bbox[0],bbox[2]),(bbox[0],bbox[3]),
     (bbox[1], bbox[3]),(bbox[1],bbox[2]),

The METAR (obs datatype) and Synoptic (sfcobs datatype) data requests follow a very familiar pattern of using a time filter and geographic envelope to narrow the results (these two filters are used in most of our notebook examples). We define these filters first, so they can be used in both datatype requests. Re-using variables like this makes our code more efficient and faster to run, and it also guarantees consistency between the two requests, which is something that is not guaranteed if we define new filter objects for each request. We can see this “reusability” principle used again in the notebook when defining “shared” parameters the two datatypes have in common and are needed for plotting.

Similar to our METAR notebook example, we need to manipulate both the obs and sfcobs data responses to extract all necessary parameters for plotting. Because the two datatypes share so many similarities, we are able to write a function, extract_plotting_data(), which can be used by both datatypes.

Finally, now that we have all the necessary information, we can plot each of the individual datatypes and combine them for a final figure.

First, we start with the `maps` data which has the state outlines:

Regional plot using the EDEX maps database

Adding in the METAR data we get our next plot:

Regional plot of METAR data

We then view the synoptic data, individually to create this plot:

Regional plot of synoptic data

And finally, we reuse our original figure with to display all three data products:

Regional plot of METARS and synoptic data

We hope this notebook helped emphasize the importance of reusable code, between the re-use of shared variables, and the definition of functions containing logic that was used in many places. We hope you learned something new about python-awips. Please check back in two weeks for the next blog post with information about porting CAVE configurations in EDEX!

To view archived blogs, visit the AWIPS Tips blog tag, and get notified of the latest updates from the AWIPS team by signing up for the AWIPS mailing list. Questions or suggestions for the team on future topics? Let us know at


Hi, i'm interested in using your code to plot data for different regions. I'm specifically interested in plotting data for South America. Can you please provide some instructions on how to do this? I'm not sure how to change the code to plot data for different regions. Thanks.

Posted by Vitor Tenório on November 18, 2023 at 07:05 PM MST #

Hi Vitor, thank you for your question, and thank you for submitting an entry through our support email. I've responded via email. Thanks!

Posted by Shay on November 20, 2023 at 10:13 AM MST #

Post a Comment:
  • HTML Syntax: Allowed
News and information from the Unidata Program Center
News and information from the Unidata Program Center



Developers’ blog

Recent Entries:
Take a poll!

What if we had an ongoing user poll in here?

Browse By Topic
Browse by Topic
« June 2024