-
In GEMPAK, if I have jagged contours (which can happen on relatively coarse grids especially), I would use the
Is there a way to overcome these issues and plot smooth contours? |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 6 replies
-
This example is what @kgoebber put together for that. It might make sense to turn this into an example in the metpy docs... |
Beta Was this translation helpful? Give feedback.
-
I've got on my to do list to add a trait that can be set to do smoothing. I was planning on implementing the nine point smoother for the declarative syntax (and allow the number of passes to be input), but could be persuaded to use one of the other (e.g., gaussian). I also have an example of smoothing a parameter, then adding it to an xarray dataset that will work as a substitute until we get that code in the declarative framework: https://github.com/kgoebber/valpo_courses/blob/master/wxtech/notebooks/metpy_calculations_wind_speed.ipynb |
Beta Was this translation helpful? Give feedback.
-
Okay, so here is what I've got... A couple of things. There is an easier way to get the data you want without all of the excess code. The structure of the data is uniform and really only requires knowledge of the date to change which dataset you are accessing, then the reading can be done with the OPeNDaP link directly. I use your Then I use the methods available on the dataset to pull the vertical level and desired plot time and converting to Celsius using MetPy's unit aware capabilities. Doing so keeps the attributes coming along with your variables (they are lost when doing simple calculations like subtracting 273.15), which then allows @jthielen function to work better. Note: I did have to add one piece to the xarray_zoom function to bring along the metpy_crs variable, but just added that attribute after the work of figuring out the new x and y coords from the zoomed in aspect. You'll also be able to see how I played a little with the figure size and then the arguments in the pc.save() call to get rid of excess white space. from datetime import datetime
import metpy.calc as mpcalc
from metpy.plots.declarative import ContourPlot, MapPanel, PanelContainer
from metpy.units import units
from scipy.ndimage import zoom as scipy_zoom
import numpy as np
import xarray as xr
def xarray_zoom(
input, zoom, output=None, order=3, mode='constant', cval=0.0, prefilter=True, *,
grid_mode=False,
):
# Zoom data
zoomed_data = scipy_zoom(
input.data, zoom, output=output, order=order, mode=mode, cval=cval,
prefilter=prefilter, grid_mode=grid_mode
)
# Zoom dimension coordinates
if not np.iterable(zoom):
zoom = tuple(zoom for _ in input.dims)
zoomed_dim_coords = {}
for dim_name, dim_zoom in zip(input.dims, zoom):
if dim_name in input.coords:
zoomed_dim_coords[dim_name] = scipy_zoom(
input[dim_name].data, dim_zoom, order=order, mode=mode, cval=cval,
prefilter=prefilter, grid_mode=grid_mode
)
zoomed_dim_coords['metpy_crs'] = input.metpy_crs
# Reconstruct (ignoring non-dimension coordinates)
return xr.DataArray(
zoomed_data, dims=input.dims, coords=zoomed_dim_coords, attrs=input.attrs
)
init_time = datetime(2021, 9, 23, 12)
nam = xr.open_dataset('https://thredds.ucar.edu/thredds/dodsC/grib/NCEP/NAM/'
f'CONUS_80km/NAM_CONUS_80km_{init_time:%Y%m%d}_{init_time:%H}00.grib1').metpy.parse_cf()
plot_time = datetime(2021, 9, 24, 0)
tmpc = nam['Temperature_isobaric'].metpy.sel(vertical=850*units.hPa, time=plot_time).metpy.convert_units('degC')
tmpc_gauss = mpcalc.smooth_gaussian(tmpc, 8)
tmpc_9pt = mpcalc.smooth_n_point(tmpc, 9)
tmpc_zoom = xarray_zoom(tmpc, 10)
raw = ContourPlot()
raw.data = tmpc
raw.contours = list(range(0,20))
raw.linecolor = 'green'
raw.clabels = True
gauss = ContourPlot()
gauss.data = tmpc_gauss
gauss.contours = list(range(0,20))
gauss.linecolor = 'green'
gauss.clabels = True
ninept = ContourPlot()
ninept.data = tmpc_9pt
ninept.contours = list(range(0,20))
ninept.linecolor = 'green'
ninept.clabels = True
zoom = ContourPlot()
zoom.data = tmpc_zoom
zoom.contours = list(range(0,20))
zoom.linecolor = 'green'
zoom.clabels = True
mp1 = MapPanel()
mp1.layout = (2, 2, 1)
mp1.area = [-87, -78, 40.5, 45]
mp1.projection = 'lcc'
mp1.layers = ['states', 'coastline', 'borders']
mp1.title = 'Raw Data'
mp1.plots = [raw]
mp2 = MapPanel()
mp2.layout = (2, 2, 2)
mp2.area = [-87, -78, 40.5, 45]
mp2.projection = 'lcc'
mp2.layers = ['states', 'coastline', 'borders']
mp2.title = 'Gaussian Filter'
mp2.plots = [gauss]
mp3 = MapPanel()
mp3.layout = (2, 2, 3)
mp3.area = [-87, -78, 40.5, 45]
mp3.projection = 'lcc'
mp3.layers = ['states', 'coastline', 'borders']
mp3.title = '9-pt Smoother'
mp3.plots = [ninept]
mp4 = MapPanel()
mp4.layout = (2, 2, 4)
mp4.area = [-87, -78, 40.5, 45]
mp4.projection = 'lcc'
mp4.layers = ['states', 'coastline', 'borders']
mp4.title = 'Scipy Zoom'
mp4.plots = [zoom]
pc = PanelContainer()
pc.size = (15,12)
pc.panels = [mp1, mp2, mp3, mp4]
pc.show()
pc.save('test_zoom.png', dpi=150, bbox_inches='tight') |
Beta Was this translation helpful? Give feedback.
Okay, so here is what I've got...
A couple of things. There is an easier way to get the data you want without all of the excess code. The structure of the data is uniform and really only requires knowledge of the date to change which dataset you are accessing, then the reading can be done with the OPeNDaP link directly. I use your
init_date
variable and common formatting aspects for dates with Python f-strings.Then I use the methods available on the dataset to pull the vertical level and desired plot time and converting to Celsius using MetPy's unit aware capabilities. Doing so keeps the attributes coming along with your variables (they are lost when doing simple calculations like subtra…