xarray with MetPy Tutorial
xarray is a powerful Python package that provides
N-dimensional labeled arrays and datasets following the Common Data Model. MetPy’s suite of
meteorological calculations are designed to integrate with xarray DataArrays as one of its two
primary data models (the other being Pint Quantities). MetPy also provides DataArray and
Dataset accessors (collections of methods and properties attached to the .metpy
property)
for coordinate/CRS and unit operations.
Full information on MetPy’s accessors is available in the appropriate section of the
reference guide , otherwise, continue on in this
tutorial for a demonstration of the three main components of MetPy’s integration with xarray
(coordinates/coordinate reference systems, units, and calculations), as well as instructive
examples for both CF-compliant and non-compliant datasets.
First, some general imports…
import numpy as np
import xarray as xr
# Any import of metpy will activate the accessors
import metpy.calc as mpcalc
from metpy.cbook import get_test_data
from metpy.units import units
…and opening some sample data to work with.
# Open the netCDF file as a xarray Dataset
data = xr . open_dataset ( get_test_data ( 'irma_gfs_example.nc' , False ))
# View a summary of the Dataset
data
<xarray.Dataset> Size: 67MB
Dimensions: (time1: 9, latitude: 81,
isobaric3: 31, isobaric1: 21,
longitude: 131)
Coordinates:
* time1 (time1) datetime64[ns] 72B 2017-09-0...
reftime datetime64[ns] 8B ...
* latitude (latitude) float32 324B 50.0 ... 10.0
* isobaric3 (isobaric3) float64 248B 100.0 ... 1...
* isobaric1 (isobaric1) float64 168B 1e+04 ... 1...
* longitude (longitude) float32 524B 250.0 ... 3...
Data variables:
Vertical_velocity_pressure_isobaric (time1, isobaric1, latitude, longitude) float32 8MB ...
Relative_humidity_isobaric (time1, isobaric3, latitude, longitude) float32 12MB ...
Temperature_isobaric (time1, isobaric3, latitude, longitude) float32 12MB ...
u-component_of_wind_isobaric (time1, isobaric3, latitude, longitude) float32 12MB ...
v-component_of_wind_isobaric (time1, isobaric3, latitude, longitude) float32 12MB ...
Geopotential_height_isobaric (time1, isobaric3, latitude, longitude) float32 12MB ...
LatLon_361X720-0p25S-180p00E int32 4B ...
Attributes: (12/13)
Originating_or_generating_Center: ...
Originating_or_generating_Subcenter: ...
GRIB_table_version: ...
Type_of_generating_process: ...
Analysis_or_forecast_generating_process_identifier_defined_by_originating...
Conventions: ...
... ...
featureType: ...
History: ...
geospatial_lat_min: ...
geospatial_lat_max: ...
geospatial_lon_min: ...
geospatial_lon_max: ... Dimensions: time1 : 9latitude : 81isobaric3 : 31isobaric1 : 21longitude : 131
Coordinates: (6)
time1
(time1)
datetime64[ns]
2017-09-05T12:00:00 ... 2017-09-...
standard_name : time long_name : time udunits : Hour since 2017-09-05T12:00:00Z array(['2017-09-05T12:00:00.000000000', '2017-09-05T15:00:00.000000000',
'2017-09-05T18:00:00.000000000', '2017-09-05T21:00:00.000000000',
'2017-09-06T00:00:00.000000000', '2017-09-06T03:00:00.000000000',
'2017-09-06T06:00:00.000000000', '2017-09-06T09:00:00.000000000',
'2017-09-06T12:00:00.000000000'], dtype='datetime64[ns]') reftime
()
datetime64[ns]
...
standard_name : forecast_reference_time long_name : GRIB reference time [1 values with dtype=datetime64[ns]] latitude
(latitude)
float32
50.0 49.5 49.0 ... 11.0 10.5 10.0
units : degrees_north standard_name : latitude array([50. , 49.5, 49. , 48.5, 48. , 47.5, 47. , 46.5, 46. , 45.5, 45. , 44.5,
44. , 43.5, 43. , 42.5, 42. , 41.5, 41. , 40.5, 40. , 39.5, 39. , 38.5,
38. , 37.5, 37. , 36.5, 36. , 35.5, 35. , 34.5, 34. , 33.5, 33. , 32.5,
32. , 31.5, 31. , 30.5, 30. , 29.5, 29. , 28.5, 28. , 27.5, 27. , 26.5,
26. , 25.5, 25. , 24.5, 24. , 23.5, 23. , 22.5, 22. , 21.5, 21. , 20.5,
20. , 19.5, 19. , 18.5, 18. , 17.5, 17. , 16.5, 16. , 15.5, 15. , 14.5,
14. , 13.5, 13. , 12.5, 12. , 11.5, 11. , 10.5, 10. ], dtype=float32) isobaric3
(isobaric3)
float64
100.0 200.0 ... 9.75e+04 1e+05
array([ 100., 200., 300., 500., 700., 1000., 2000., 3000.,
5000., 7000., 10000., 15000., 20000., 25000., 30000., 35000.,
40000., 45000., 50000., 55000., 60000., 65000., 70000., 75000.,
80000., 85000., 90000., 92500., 95000., 97500., 100000.]) isobaric1
(isobaric1)
float64
1e+04 1.5e+04 ... 9.75e+04 1e+05
array([ 10000., 15000., 20000., 25000., 30000., 35000., 40000., 45000.,
50000., 55000., 60000., 65000., 70000., 75000., 80000., 85000.,
90000., 92500., 95000., 97500., 100000.]) longitude
(longitude)
float32
250.0 250.5 251.0 ... 314.5 315.0
units : degrees_east standard_name : longitude array([250. , 250.5, 251. , 251.5, 252. , 252.5, 253. , 253.5, 254. , 254.5,
255. , 255.5, 256. , 256.5, 257. , 257.5, 258. , 258.5, 259. , 259.5,
260. , 260.5, 261. , 261.5, 262. , 262.5, 263. , 263.5, 264. , 264.5,
265. , 265.5, 266. , 266.5, 267. , 267.5, 268. , 268.5, 269. , 269.5,
270. , 270.5, 271. , 271.5, 272. , 272.5, 273. , 273.5, 274. , 274.5,
275. , 275.5, 276. , 276.5, 277. , 277.5, 278. , 278.5, 279. , 279.5,
280. , 280.5, 281. , 281.5, 282. , 282.5, 283. , 283.5, 284. , 284.5,
285. , 285.5, 286. , 286.5, 287. , 287.5, 288. , 288.5, 289. , 289.5,
290. , 290.5, 291. , 291.5, 292. , 292.5, 293. , 293.5, 294. , 294.5,
295. , 295.5, 296. , 296.5, 297. , 297.5, 298. , 298.5, 299. , 299.5,
300. , 300.5, 301. , 301.5, 302. , 302.5, 303. , 303.5, 304. , 304.5,
305. , 305.5, 306. , 306.5, 307. , 307.5, 308. , 308.5, 309. , 309.5,
310. , 310.5, 311. , 311.5, 312. , 312.5, 313. , 313.5, 314. , 314.5,
315. ], dtype=float32) Data variables: (7)
Vertical_velocity_pressure_isobaric
(time1, isobaric1, latitude, longitude)
float32
...
long_name : Vertical velocity (pressure) @ Isobaric surface units : Pa/s Grib_Variable_Id : VAR_0-2-8_L100 Grib2_Parameter : [0 2 8] Grib2_Parameter_Discipline : Meteorological products Grib2_Parameter_Category : Momentum Grib2_Parameter_Name : Vertical velocity (pressure) Grib2_Level_Type : 100 Grib2_Level_Desc : Isobaric surface Grib2_Generating_Process_Type : Forecast grid_mapping : LatLon_361X720-0p25S-180p00E [2005479 values with dtype=float32] Relative_humidity_isobaric
(time1, isobaric3, latitude, longitude)
float32
...
long_name : Relative humidity @ Isobaric surface units : % Grib_Variable_Id : VAR_0-1-1_L100 Grib2_Parameter : [0 1 1] Grib2_Parameter_Discipline : Meteorological products Grib2_Parameter_Category : Moisture Grib2_Parameter_Name : Relative humidity Grib2_Level_Type : 100 Grib2_Level_Desc : Isobaric surface Grib2_Generating_Process_Type : Forecast grid_mapping : LatLon_361X720-0p25S-180p00E [2960469 values with dtype=float32] Temperature_isobaric
(time1, isobaric3, latitude, longitude)
float32
...
long_name : Temperature @ Isobaric surface units : K Grib_Variable_Id : VAR_0-0-0_L100 Grib2_Parameter : [0 0 0] Grib2_Parameter_Discipline : Meteorological products Grib2_Parameter_Category : Temperature Grib2_Parameter_Name : Temperature Grib2_Level_Type : 100 Grib2_Level_Desc : Isobaric surface Grib2_Generating_Process_Type : Forecast grid_mapping : LatLon_361X720-0p25S-180p00E [2960469 values with dtype=float32] u-component_of_wind_isobaric
(time1, isobaric3, latitude, longitude)
float32
...
long_name : u-component of wind @ Isobaric surface units : m/s Grib_Variable_Id : VAR_0-2-2_L100 Grib2_Parameter : [0 2 2] Grib2_Parameter_Discipline : Meteorological products Grib2_Parameter_Category : Momentum Grib2_Parameter_Name : u-component of wind Grib2_Level_Type : 100 Grib2_Level_Desc : Isobaric surface Grib2_Generating_Process_Type : Forecast grid_mapping : LatLon_361X720-0p25S-180p00E [2960469 values with dtype=float32] v-component_of_wind_isobaric
(time1, isobaric3, latitude, longitude)
float32
...
long_name : v-component of wind @ Isobaric surface units : m/s Grib_Variable_Id : VAR_0-2-3_L100 Grib2_Parameter : [0 2 3] Grib2_Parameter_Discipline : Meteorological products Grib2_Parameter_Category : Momentum Grib2_Parameter_Name : v-component of wind Grib2_Level_Type : 100 Grib2_Level_Desc : Isobaric surface Grib2_Generating_Process_Type : Forecast grid_mapping : LatLon_361X720-0p25S-180p00E [2960469 values with dtype=float32] Geopotential_height_isobaric
(time1, isobaric3, latitude, longitude)
float32
...
long_name : Geopotential height @ Isobaric surface units : gpm Grib_Variable_Id : VAR_0-3-5_L100 Grib2_Parameter : [0 3 5] Grib2_Parameter_Discipline : Meteorological products Grib2_Parameter_Category : Mass Grib2_Parameter_Name : Geopotential height Grib2_Level_Type : 100 Grib2_Level_Desc : Isobaric surface Grib2_Generating_Process_Type : Forecast grid_mapping : LatLon_361X720-0p25S-180p00E [2960469 values with dtype=float32] LatLon_361X720-0p25S-180p00E
()
int32
...
grid_mapping_name : latitude_longitude earth_radius : 6371229.0 [1 values with dtype=int32] Indexes: (5)
PandasIndex
PandasIndex(DatetimeIndex(['2017-09-05 12:00:00', '2017-09-05 15:00:00',
'2017-09-05 18:00:00', '2017-09-05 21:00:00',
'2017-09-06 00:00:00', '2017-09-06 03:00:00',
'2017-09-06 06:00:00', '2017-09-06 09:00:00',
'2017-09-06 12:00:00'],
dtype='datetime64[ns]', name='time1', freq=None)) PandasIndex
PandasIndex(Index([50.0, 49.5, 49.0, 48.5, 48.0, 47.5, 47.0, 46.5, 46.0, 45.5, 45.0, 44.5,
44.0, 43.5, 43.0, 42.5, 42.0, 41.5, 41.0, 40.5, 40.0, 39.5, 39.0, 38.5,
38.0, 37.5, 37.0, 36.5, 36.0, 35.5, 35.0, 34.5, 34.0, 33.5, 33.0, 32.5,
32.0, 31.5, 31.0, 30.5, 30.0, 29.5, 29.0, 28.5, 28.0, 27.5, 27.0, 26.5,
26.0, 25.5, 25.0, 24.5, 24.0, 23.5, 23.0, 22.5, 22.0, 21.5, 21.0, 20.5,
20.0, 19.5, 19.0, 18.5, 18.0, 17.5, 17.0, 16.5, 16.0, 15.5, 15.0, 14.5,
14.0, 13.5, 13.0, 12.5, 12.0, 11.5, 11.0, 10.5, 10.0],
dtype='float32', name='latitude')) PandasIndex
PandasIndex(Index([ 100.0, 200.0, 300.0, 500.0, 700.0, 1000.0, 2000.0,
3000.0, 5000.0, 7000.0, 10000.0, 15000.0, 20000.0, 25000.0,
30000.0, 35000.0, 40000.0, 45000.0, 50000.0, 55000.0, 60000.0,
65000.0, 70000.0, 75000.0, 80000.0, 85000.0, 90000.0, 92500.0,
95000.0, 97500.0, 100000.0],
dtype='float64', name='isobaric3')) PandasIndex
PandasIndex(Index([ 10000.0, 15000.0, 20000.0, 25000.0, 30000.0, 35000.0, 40000.0,
45000.0, 50000.0, 55000.0, 60000.0, 65000.0, 70000.0, 75000.0,
80000.0, 85000.0, 90000.0, 92500.0, 95000.0, 97500.0, 100000.0],
dtype='float64', name='isobaric1')) PandasIndex
PandasIndex(Index([250.0, 250.5, 251.0, 251.5, 252.0, 252.5, 253.0, 253.5, 254.0, 254.5,
...
310.5, 311.0, 311.5, 312.0, 312.5, 313.0, 313.5, 314.0, 314.5, 315.0],
dtype='float32', name='longitude', length=131)) Attributes: (13)
Originating_or_generating_Center : US National Weather Service, National Centres for Environmental Prediction (NCEP) Originating_or_generating_Subcenter : 0 GRIB_table_version : 2,1 Type_of_generating_process : Forecast Analysis_or_forecast_generating_process_identifier_defined_by_originating_centre : Analysis from GFS (Global Forecast System) Conventions : CF-1.6 history : Read using CDM IOSP GribCollection v3 featureType : GRID History : Translated to CF-1.0 Conventions by Netcdf-Java CDM (CFGridCoverageWriter2)
Original Dataset = GFS_Global_0p5deg_20170905_1200.grib2#SRC; Translation Date = 2018-06-22T16:20:50.317Z geospatial_lat_min : 9.75 geospatial_lat_max : 50.25 geospatial_lon_min : -110.25 geospatial_lon_max : -44.75
While xarray can handle a wide variety of n-dimensional data (essentially anything that can
be stored in a netCDF file), a common use case is working with gridded model output. Such
model data can be obtained from a THREDDS Data Server using the siphon package , but here we’ve used an example subset of GFS data
from Hurricane Irma (September 5th, 2017) included in MetPy’s test suite. Generally,
a local file (or remote file via OPeNDAP) can be opened with xr.open_dataset("path")
.
Going back to the above object, this Dataset
consists of dimensions and their
associated coordinates , which in turn make up the axes along which the data variables
are defined. The dataset also has a dictionary-like collection of attributes . What happens
if we look at just a single data variable?
<xarray.DataArray 'Temperature_isobaric' (time1: 9, isobaric3: 31,
latitude: 81, longitude: 131)> Size: 12MB
[2960469 values with dtype=float32]
Coordinates:
* time1 (time1) datetime64[ns] 72B 2017-09-05T12:00:00 ... 2017-09-06T...
reftime datetime64[ns] 8B ...
* latitude (latitude) float32 324B 50.0 49.5 49.0 48.5 ... 11.0 10.5 10.0
* isobaric3 (isobaric3) float64 248B 100.0 200.0 300.0 ... 9.75e+04 1e+05
* longitude (longitude) float32 524B 250.0 250.5 251.0 ... 314.0 314.5 315.0
Attributes:
long_name: Temperature @ Isobaric surface
units: K
Grib_Variable_Id: VAR_0-0-0_L100
Grib2_Parameter: [0 0 0]
Grib2_Parameter_Discipline: Meteorological products
Grib2_Parameter_Category: Temperature
Grib2_Parameter_Name: Temperature
Grib2_Level_Type: 100
Grib2_Level_Desc: Isobaric surface
Grib2_Generating_Process_Type: Forecast
grid_mapping: LatLon_361X720-0p25S-180p00E Coordinates: (5)
time1
(time1)
datetime64[ns]
2017-09-05T12:00:00 ... 2017-09-...
standard_name : time long_name : time udunits : Hour since 2017-09-05T12:00:00Z array(['2017-09-05T12:00:00.000000000', '2017-09-05T15:00:00.000000000',
'2017-09-05T18:00:00.000000000', '2017-09-05T21:00:00.000000000',
'2017-09-06T00:00:00.000000000', '2017-09-06T03:00:00.000000000',
'2017-09-06T06:00:00.000000000', '2017-09-06T09:00:00.000000000',
'2017-09-06T12:00:00.000000000'], dtype='datetime64[ns]') reftime
()
datetime64[ns]
...
standard_name : forecast_reference_time long_name : GRIB reference time [1 values with dtype=datetime64[ns]] latitude
(latitude)
float32
50.0 49.5 49.0 ... 11.0 10.5 10.0
units : degrees_north standard_name : latitude array([50. , 49.5, 49. , 48.5, 48. , 47.5, 47. , 46.5, 46. , 45.5, 45. , 44.5,
44. , 43.5, 43. , 42.5, 42. , 41.5, 41. , 40.5, 40. , 39.5, 39. , 38.5,
38. , 37.5, 37. , 36.5, 36. , 35.5, 35. , 34.5, 34. , 33.5, 33. , 32.5,
32. , 31.5, 31. , 30.5, 30. , 29.5, 29. , 28.5, 28. , 27.5, 27. , 26.5,
26. , 25.5, 25. , 24.5, 24. , 23.5, 23. , 22.5, 22. , 21.5, 21. , 20.5,
20. , 19.5, 19. , 18.5, 18. , 17.5, 17. , 16.5, 16. , 15.5, 15. , 14.5,
14. , 13.5, 13. , 12.5, 12. , 11.5, 11. , 10.5, 10. ], dtype=float32) isobaric3
(isobaric3)
float64
100.0 200.0 ... 9.75e+04 1e+05
array([ 100., 200., 300., 500., 700., 1000., 2000., 3000.,
5000., 7000., 10000., 15000., 20000., 25000., 30000., 35000.,
40000., 45000., 50000., 55000., 60000., 65000., 70000., 75000.,
80000., 85000., 90000., 92500., 95000., 97500., 100000.]) longitude
(longitude)
float32
250.0 250.5 251.0 ... 314.5 315.0
units : degrees_east standard_name : longitude array([250. , 250.5, 251. , 251.5, 252. , 252.5, 253. , 253.5, 254. , 254.5,
255. , 255.5, 256. , 256.5, 257. , 257.5, 258. , 258.5, 259. , 259.5,
260. , 260.5, 261. , 261.5, 262. , 262.5, 263. , 263.5, 264. , 264.5,
265. , 265.5, 266. , 266.5, 267. , 267.5, 268. , 268.5, 269. , 269.5,
270. , 270.5, 271. , 271.5, 272. , 272.5, 273. , 273.5, 274. , 274.5,
275. , 275.5, 276. , 276.5, 277. , 277.5, 278. , 278.5, 279. , 279.5,
280. , 280.5, 281. , 281.5, 282. , 282.5, 283. , 283.5, 284. , 284.5,
285. , 285.5, 286. , 286.5, 287. , 287.5, 288. , 288.5, 289. , 289.5,
290. , 290.5, 291. , 291.5, 292. , 292.5, 293. , 293.5, 294. , 294.5,
295. , 295.5, 296. , 296.5, 297. , 297.5, 298. , 298.5, 299. , 299.5,
300. , 300.5, 301. , 301.5, 302. , 302.5, 303. , 303.5, 304. , 304.5,
305. , 305.5, 306. , 306.5, 307. , 307.5, 308. , 308.5, 309. , 309.5,
310. , 310.5, 311. , 311.5, 312. , 312.5, 313. , 313.5, 314. , 314.5,
315. ], dtype=float32) Indexes: (4)
PandasIndex
PandasIndex(DatetimeIndex(['2017-09-05 12:00:00', '2017-09-05 15:00:00',
'2017-09-05 18:00:00', '2017-09-05 21:00:00',
'2017-09-06 00:00:00', '2017-09-06 03:00:00',
'2017-09-06 06:00:00', '2017-09-06 09:00:00',
'2017-09-06 12:00:00'],
dtype='datetime64[ns]', name='time1', freq=None)) PandasIndex
PandasIndex(Index([50.0, 49.5, 49.0, 48.5, 48.0, 47.5, 47.0, 46.5, 46.0, 45.5, 45.0, 44.5,
44.0, 43.5, 43.0, 42.5, 42.0, 41.5, 41.0, 40.5, 40.0, 39.5, 39.0, 38.5,
38.0, 37.5, 37.0, 36.5, 36.0, 35.5, 35.0, 34.5, 34.0, 33.5, 33.0, 32.5,
32.0, 31.5, 31.0, 30.5, 30.0, 29.5, 29.0, 28.5, 28.0, 27.5, 27.0, 26.5,
26.0, 25.5, 25.0, 24.5, 24.0, 23.5, 23.0, 22.5, 22.0, 21.5, 21.0, 20.5,
20.0, 19.5, 19.0, 18.5, 18.0, 17.5, 17.0, 16.5, 16.0, 15.5, 15.0, 14.5,
14.0, 13.5, 13.0, 12.5, 12.0, 11.5, 11.0, 10.5, 10.0],
dtype='float32', name='latitude')) PandasIndex
PandasIndex(Index([ 100.0, 200.0, 300.0, 500.0, 700.0, 1000.0, 2000.0,
3000.0, 5000.0, 7000.0, 10000.0, 15000.0, 20000.0, 25000.0,
30000.0, 35000.0, 40000.0, 45000.0, 50000.0, 55000.0, 60000.0,
65000.0, 70000.0, 75000.0, 80000.0, 85000.0, 90000.0, 92500.0,
95000.0, 97500.0, 100000.0],
dtype='float64', name='isobaric3')) PandasIndex
PandasIndex(Index([250.0, 250.5, 251.0, 251.5, 252.0, 252.5, 253.0, 253.5, 254.0, 254.5,
...
310.5, 311.0, 311.5, 312.0, 312.5, 313.0, 313.5, 314.0, 314.5, 315.0],
dtype='float32', name='longitude', length=131)) Attributes: (11)
long_name : Temperature @ Isobaric surface units : K Grib_Variable_Id : VAR_0-0-0_L100 Grib2_Parameter : [0 0 0] Grib2_Parameter_Discipline : Meteorological products Grib2_Parameter_Category : Temperature Grib2_Parameter_Name : Temperature Grib2_Level_Type : 100 Grib2_Level_Desc : Isobaric surface Grib2_Generating_Process_Type : Forecast grid_mapping : LatLon_361X720-0p25S-180p00E
This is a DataArray
, which stores just a single data variable with its associated
coordinates and attributes. These individual DataArray
s are the kinds of objects that
MetPy’s calculations take as input (more on that in Calculations section below).
If you are more interested in learning about xarray’s terminology and data structures, see
the terminology section of xarray’s
documentation.
Coordinates and Coordinate Reference Systems
MetPy’s first set of helpers comes with identifying coordinate types . In a given dataset,
coordinates can have a variety of different names and yet refer to the same type (such as
“isobaric1” and “isobaric3” both referring to vertical isobaric coordinates). Following
CF conventions, as well as using some fall-back regular expressions, MetPy can
systematically identify coordinates of the following types:
time
vertical
latitude
y
longitude
x
When identifying a single coordinate, it is best to use the property directly associated
with that type
<xarray.DataArray 'time1' (time1: 9)> Size: 72B
array(['2017-09-05T12:00:00.000000000', '2017-09-05T15:00:00.000000000',
'2017-09-05T18:00:00.000000000', '2017-09-05T21:00:00.000000000',
'2017-09-06T00:00:00.000000000', '2017-09-06T03:00:00.000000000',
'2017-09-06T06:00:00.000000000', '2017-09-06T09:00:00.000000000',
'2017-09-06T12:00:00.000000000'], dtype='datetime64[ns]')
Coordinates:
* time1 (time1) datetime64[ns] 72B 2017-09-05T12:00:00 ... 2017-09-06T12...
reftime datetime64[ns] 8B ...
Attributes:
standard_name: time
long_name: time
udunits: Hour since 2017-09-05T12:00:00Z
_metpy_axis: time Coordinates: (2)
Indexes: (1)
PandasIndex
PandasIndex(DatetimeIndex(['2017-09-05 12:00:00', '2017-09-05 15:00:00',
'2017-09-05 18:00:00', '2017-09-05 21:00:00',
'2017-09-06 00:00:00', '2017-09-06 03:00:00',
'2017-09-06 06:00:00', '2017-09-06 09:00:00',
'2017-09-06 12:00:00'],
dtype='datetime64[ns]', name='time1', freq=None)) Attributes: (4)
standard_name : time long_name : time udunits : Hour since 2017-09-05T12:00:00Z _metpy_axis : time
When accessing multiple coordinate types simultaneously, you can use the .coordinates()
method to yield a generator for the respective coordinates
These coordinate type aliases can also be used in MetPy’s wrapped .sel
and .loc
for indexing and selecting on DataArray
s. For example, to access 500 hPa heights at
1800Z,
heights = data [ 'Geopotential_height_isobaric' ] . metpy . sel (
time = '2017-09-05 18:00' ,
vertical = 50000.
)
(Notice how we specified 50000 here without units…we’ll go over a better alternative in
the next section on units.)
One point of warning: xarray’s selection and indexing only works if these coordinates are
dimension coordinates , meaning that they are 1D and share the name of their associated
dimension. In practice, this means that you can’t index a dataset that has 2D latitude and
longitude coordinates by latitudes and longitudes, instead, you must index by the 1D y and x
dimension coordinates. (What if these coordinates are missing, you may ask? See the final
subsection on .assign_y_x
for more details.)
Beyond just the coordinates themselves, a common need for both calculations with and plots
of geospatial data is knowing the coordinate reference system (CRS) on which the horizontal
spatial coordinates are defined. MetPy follows the CF Conventions
for its CRS definitions, which it then caches on the metpy_crs
coordinate in order for
it to persist through calculations and other array operations. There are two ways to do so
in MetPy:
First, if your dataset is already conforming to the CF Conventions, it will have a grid
mapping variable that is associated with the other data variables by the grid_mapping
attribute. This is automatically parsed via the .parse_cf()
method:
# Parse full dataset
data_parsed = data . metpy . parse_cf ()
# Parse subset of dataset
data_subset = data . metpy . parse_cf ([
'u-component_of_wind_isobaric' ,
'v-component_of_wind_isobaric' ,
'Vertical_velocity_pressure_isobaric'
])
# Parse single variable
relative_humidity = data . metpy . parse_cf ( 'Relative_humidity_isobaric' )
If your dataset doesn’t have a CF-conforming grid mapping variable, you can manually specify
the CRS using the .assign_crs()
method:
temperature = data [ 'Temperature_isobaric' ] . metpy . assign_crs (
grid_mapping_name = 'latitude_longitude' ,
earth_radius = 6371229.0
)
temperature
<xarray.DataArray 'Temperature_isobaric' (time1: 9, isobaric3: 31,
latitude: 81, longitude: 131)> Size: 12MB
[2960469 values with dtype=float32]
Coordinates:
* time1 (time1) datetime64[ns] 72B 2017-09-05T12:00:00 ... 2017-09-06T...
reftime datetime64[ns] 8B ...
* latitude (latitude) float32 324B 50.0 49.5 49.0 48.5 ... 11.0 10.5 10.0
* isobaric3 (isobaric3) float64 248B 100.0 200.0 300.0 ... 9.75e+04 1e+05
* longitude (longitude) float32 524B 250.0 250.5 251.0 ... 314.0 314.5 315.0
metpy_crs object 8B Projection: latitude_longitude
Attributes:
long_name: Temperature @ Isobaric surface
units: K
Grib_Variable_Id: VAR_0-0-0_L100
Grib2_Parameter: [0 0 0]
Grib2_Parameter_Discipline: Meteorological products
Grib2_Parameter_Category: Temperature
Grib2_Parameter_Name: Temperature
Grib2_Level_Type: 100
Grib2_Level_Desc: Isobaric surface
Grib2_Generating_Process_Type: Forecast
grid_mapping: LatLon_361X720-0p25S-180p00E Coordinates: (6)
time1
(time1)
datetime64[ns]
2017-09-05T12:00:00 ... 2017-09-...
standard_name : time long_name : time udunits : Hour since 2017-09-05T12:00:00Z _metpy_axis : time array(['2017-09-05T12:00:00.000000000', '2017-09-05T15:00:00.000000000',
'2017-09-05T18:00:00.000000000', '2017-09-05T21:00:00.000000000',
'2017-09-06T00:00:00.000000000', '2017-09-06T03:00:00.000000000',
'2017-09-06T06:00:00.000000000', '2017-09-06T09:00:00.000000000',
'2017-09-06T12:00:00.000000000'], dtype='datetime64[ns]') reftime
()
datetime64[ns]
...
standard_name : forecast_reference_time long_name : GRIB reference time [1 values with dtype=datetime64[ns]] latitude
(latitude)
float32
50.0 49.5 49.0 ... 11.0 10.5 10.0
units : degrees_north standard_name : latitude _metpy_axis : y,latitude array([50. , 49.5, 49. , 48.5, 48. , 47.5, 47. , 46.5, 46. , 45.5, 45. , 44.5,
44. , 43.5, 43. , 42.5, 42. , 41.5, 41. , 40.5, 40. , 39.5, 39. , 38.5,
38. , 37.5, 37. , 36.5, 36. , 35.5, 35. , 34.5, 34. , 33.5, 33. , 32.5,
32. , 31.5, 31. , 30.5, 30. , 29.5, 29. , 28.5, 28. , 27.5, 27. , 26.5,
26. , 25.5, 25. , 24.5, 24. , 23.5, 23. , 22.5, 22. , 21.5, 21. , 20.5,
20. , 19.5, 19. , 18.5, 18. , 17.5, 17. , 16.5, 16. , 15.5, 15. , 14.5,
14. , 13.5, 13. , 12.5, 12. , 11.5, 11. , 10.5, 10. ], dtype=float32) isobaric3
(isobaric3)
float64
100.0 200.0 ... 9.75e+04 1e+05
units : Pa positive : down _metpy_axis : vertical array([ 100., 200., 300., 500., 700., 1000., 2000., 3000.,
5000., 7000., 10000., 15000., 20000., 25000., 30000., 35000.,
40000., 45000., 50000., 55000., 60000., 65000., 70000., 75000.,
80000., 85000., 90000., 92500., 95000., 97500., 100000.]) longitude
(longitude)
float32
250.0 250.5 251.0 ... 314.5 315.0
units : degrees_east standard_name : longitude _metpy_axis : x,longitude array([250. , 250.5, 251. , 251.5, 252. , 252.5, 253. , 253.5, 254. , 254.5,
255. , 255.5, 256. , 256.5, 257. , 257.5, 258. , 258.5, 259. , 259.5,
260. , 260.5, 261. , 261.5, 262. , 262.5, 263. , 263.5, 264. , 264.5,
265. , 265.5, 266. , 266.5, 267. , 267.5, 268. , 268.5, 269. , 269.5,
270. , 270.5, 271. , 271.5, 272. , 272.5, 273. , 273.5, 274. , 274.5,
275. , 275.5, 276. , 276.5, 277. , 277.5, 278. , 278.5, 279. , 279.5,
280. , 280.5, 281. , 281.5, 282. , 282.5, 283. , 283.5, 284. , 284.5,
285. , 285.5, 286. , 286.5, 287. , 287.5, 288. , 288.5, 289. , 289.5,
290. , 290.5, 291. , 291.5, 292. , 292.5, 293. , 293.5, 294. , 294.5,
295. , 295.5, 296. , 296.5, 297. , 297.5, 298. , 298.5, 299. , 299.5,
300. , 300.5, 301. , 301.5, 302. , 302.5, 303. , 303.5, 304. , 304.5,
305. , 305.5, 306. , 306.5, 307. , 307.5, 308. , 308.5, 309. , 309.5,
310. , 310.5, 311. , 311.5, 312. , 312.5, 313. , 313.5, 314. , 314.5,
315. ], dtype=float32) metpy_crs
()
object
Projection: latitude_longitude
array(<metpy.plots.mapping.CFProjection object at 0x7f7408107070>,
dtype=object) Indexes: (4)
PandasIndex
PandasIndex(DatetimeIndex(['2017-09-05 12:00:00', '2017-09-05 15:00:00',
'2017-09-05 18:00:00', '2017-09-05 21:00:00',
'2017-09-06 00:00:00', '2017-09-06 03:00:00',
'2017-09-06 06:00:00', '2017-09-06 09:00:00',
'2017-09-06 12:00:00'],
dtype='datetime64[ns]', name='time1', freq=None)) PandasIndex
PandasIndex(Index([50.0, 49.5, 49.0, 48.5, 48.0, 47.5, 47.0, 46.5, 46.0, 45.5, 45.0, 44.5,
44.0, 43.5, 43.0, 42.5, 42.0, 41.5, 41.0, 40.5, 40.0, 39.5, 39.0, 38.5,
38.0, 37.5, 37.0, 36.5, 36.0, 35.5, 35.0, 34.5, 34.0, 33.5, 33.0, 32.5,
32.0, 31.5, 31.0, 30.5, 30.0, 29.5, 29.0, 28.5, 28.0, 27.5, 27.0, 26.5,
26.0, 25.5, 25.0, 24.5, 24.0, 23.5, 23.0, 22.5, 22.0, 21.5, 21.0, 20.5,
20.0, 19.5, 19.0, 18.5, 18.0, 17.5, 17.0, 16.5, 16.0, 15.5, 15.0, 14.5,
14.0, 13.5, 13.0, 12.5, 12.0, 11.5, 11.0, 10.5, 10.0],
dtype='float32', name='latitude')) PandasIndex
PandasIndex(Index([ 100.0, 200.0, 300.0, 500.0, 700.0, 1000.0, 2000.0,
3000.0, 5000.0, 7000.0, 10000.0, 15000.0, 20000.0, 25000.0,
30000.0, 35000.0, 40000.0, 45000.0, 50000.0, 55000.0, 60000.0,
65000.0, 70000.0, 75000.0, 80000.0, 85000.0, 90000.0, 92500.0,
95000.0, 97500.0, 100000.0],
dtype='float64', name='isobaric3')) PandasIndex
PandasIndex(Index([250.0, 250.5, 251.0, 251.5, 252.0, 252.5, 253.0, 253.5, 254.0, 254.5,
...
310.5, 311.0, 311.5, 312.0, 312.5, 313.0, 313.5, 314.0, 314.5, 315.0],
dtype='float32', name='longitude', length=131)) Attributes: (11)
long_name : Temperature @ Isobaric surface units : K Grib_Variable_Id : VAR_0-0-0_L100 Grib2_Parameter : [0 0 0] Grib2_Parameter_Discipline : Meteorological products Grib2_Parameter_Category : Temperature Grib2_Parameter_Name : Temperature Grib2_Level_Type : 100 Grib2_Level_Desc : Isobaric surface Grib2_Generating_Process_Type : Forecast grid_mapping : LatLon_361X720-0p25S-180p00E
Notice the newly added metpy_crs
non-dimension coordinate. Now how can we use this in
practice? For individual DataArrays
s, we can access the cartopy and pyproj objects
corresponding to this CRS:
2024-11-22T21:30:11.683408
image/svg+xml
Matplotlib v3.9.2, https://matplotlib.org/
<cartopy.crs.PlateCarree object at 0x7f741811d3b0>
# pyproj CRS, useful for projection transformations and forward/backward azimuth and great
# circle calculations
temperature . metpy . pyproj_crs
<Geographic 2D CRS: {"$schema": "https://proj.org/schemas/v0.2/projjso ...>
Name: undefined
Axis Info [ellipsoidal]:
- lon[east]: Longitude (degree)
- lat[north]: Latitude (degree)
Area of Use:
- undefined
Datum: undefined
- Ellipsoid: undefined
- Prime Meridian: Greenwich
Finally, there are times when a certain horizontal coordinate type is missing from your
dataset, and you need the other, that is, you have latitude/longitude and need y/x, or visa
versa. This is where the .assign_y_x
and .assign_latitude_longitude
methods come in
handy. Our current GFS sample won’t work to demonstrate this (since, on its
latitude-longitude grid, y is latitude and x is longitude), so for more information, take
a look at the Non-Compliant Dataset Example below, or view the accessor documentation.
Units
Since unit-aware calculations are a major part of the MetPy library, unit support is a major
part of MetPy’s xarray integration!
One very important point of consideration is that xarray data variables (in both
Dataset
s and DataArray
s) can store both unit-aware and unit-naive array types.
Unit-naive array types will be used by default in xarray, so we need to convert to a
unit-aware type if we want to use xarray operations while preserving unit correctness. MetPy
provides the .quantify()
method for this (named since we are turning the data stored
inside the xarray object into a Pint Quantity
object)
<xarray.DataArray 'Geopotential_height_isobaric' (latitude: 81, longitude: 131)> Size: 42kB
<Quantity([[5883.3564 5879.3164 5875.3564 ... 5769.3965 5769.996 5770.436 ]
[5885.476 5882.2363 5877.6763 ... 5783.916 5784.516 5785.1963]
[5888.8765 5885.1562 5880.916 ... 5798.476 5799.076 5799.7163]
...
[5892.516 5892.2363 5891.996 ... 5881.556 5881.436 5880.596 ]
[5891.8364 5891.596 5891.7163 ... 5880.2764 5880.3564 5879.916 ]
[5891.3564 5891.596 5891.3564 ... 5879.8765 5879.596 5878.996 ]], 'meter')>
Coordinates:
time1 datetime64[ns] 8B 2017-09-05T18:00:00
reftime datetime64[ns] 8B ...
* latitude (latitude) float32 324B 50.0 49.5 49.0 48.5 ... 11.0 10.5 10.0
isobaric3 float64 8B 5e+04
* longitude (longitude) float32 524B 250.0 250.5 251.0 ... 314.0 314.5 315.0
Attributes:
long_name: Geopotential height @ Isobaric surface
Grib_Variable_Id: VAR_0-3-5_L100
Grib2_Parameter: [0 3 5]
Grib2_Parameter_Discipline: Meteorological products
Grib2_Parameter_Category: Mass
Grib2_Parameter_Name: Geopotential height
Grib2_Level_Type: 100
Grib2_Level_Desc: Isobaric surface
Grib2_Generating_Process_Type: Forecast
grid_mapping: LatLon_361X720-0p25S-180p00E Coordinates: (5)
Indexes: (2)
PandasIndex
PandasIndex(Index([50.0, 49.5, 49.0, 48.5, 48.0, 47.5, 47.0, 46.5, 46.0, 45.5, 45.0, 44.5,
44.0, 43.5, 43.0, 42.5, 42.0, 41.5, 41.0, 40.5, 40.0, 39.5, 39.0, 38.5,
38.0, 37.5, 37.0, 36.5, 36.0, 35.5, 35.0, 34.5, 34.0, 33.5, 33.0, 32.5,
32.0, 31.5, 31.0, 30.5, 30.0, 29.5, 29.0, 28.5, 28.0, 27.5, 27.0, 26.5,
26.0, 25.5, 25.0, 24.5, 24.0, 23.5, 23.0, 22.5, 22.0, 21.5, 21.0, 20.5,
20.0, 19.5, 19.0, 18.5, 18.0, 17.5, 17.0, 16.5, 16.0, 15.5, 15.0, 14.5,
14.0, 13.5, 13.0, 12.5, 12.0, 11.5, 11.0, 10.5, 10.0],
dtype='float32', name='latitude')) PandasIndex
PandasIndex(Index([250.0, 250.5, 251.0, 251.5, 252.0, 252.5, 253.0, 253.5, 254.0, 254.5,
...
310.5, 311.0, 311.5, 312.0, 312.5, 313.0, 313.5, 314.0, 314.5, 315.0],
dtype='float32', name='longitude', length=131)) Attributes: (10)
long_name : Geopotential height @ Isobaric surface Grib_Variable_Id : VAR_0-3-5_L100 Grib2_Parameter : [0 3 5] Grib2_Parameter_Discipline : Meteorological products Grib2_Parameter_Category : Mass Grib2_Parameter_Name : Geopotential height Grib2_Level_Type : 100 Grib2_Level_Desc : Isobaric surface Grib2_Generating_Process_Type : Forecast grid_mapping : LatLon_361X720-0p25S-180p00E
Notice how the units are now represented in the data itself, rather than as a text
attribute. Now, even if we perform some kind of xarray operation (such as taking the zonal
mean), the units are preserved
<xarray.DataArray 'Geopotential_height_isobaric' (latitude: 81)> Size: 324B
<Quantity([5636.367 5644.392 5652.7705 5661.369 5669.813 5678.5083 5687.433
5696.517 5705.927 5715.6123 5725.702 5736.1387 5746.884 5757.718
5768.566 5779.2812 5789.8193 5799.801 5809.502 5818.7715 5827.7744
5836.921 5846.3857 5855.668 5864.2397 5871.804 5878.769 5885.058
5890.129 5894.0293 5897.146 5899.633 5901.674 5903.2773 5904.41
5905.27 5905.897 5906.592 5907.0083 5907.0806 5907.031 5906.871
5906.777 5906.4556 5906.121 5905.798 5905.6826 5905.5986 5905.4097
5905.1245 5904.773 5904.43 5903.954 5903.378 5902.532 5901.714
5900.865 5900.0933 5899.336 5898.4673 5897.44 5896.233 5895.057
5893.633 5891.532 5888.15 5883.094 5884.8022 5887.923 5889.0054
5889.114 5888.8887 5888.685 5888.146 5887.567 5887.0317 5886.299
5885.4214 5884.515 5883.694 5883.072 ], 'meter')>
Coordinates:
time1 datetime64[ns] 8B 2017-09-05T18:00:00
reftime datetime64[ns] 8B ...
* latitude (latitude) float32 324B 50.0 49.5 49.0 48.5 ... 11.0 10.5 10.0
isobaric3 float64 8B 5e+04 Coordinates: (4)
Indexes: (1)
PandasIndex
PandasIndex(Index([50.0, 49.5, 49.0, 48.5, 48.0, 47.5, 47.0, 46.5, 46.0, 45.5, 45.0, 44.5,
44.0, 43.5, 43.0, 42.5, 42.0, 41.5, 41.0, 40.5, 40.0, 39.5, 39.0, 38.5,
38.0, 37.5, 37.0, 36.5, 36.0, 35.5, 35.0, 34.5, 34.0, 33.5, 33.0, 32.5,
32.0, 31.5, 31.0, 30.5, 30.0, 29.5, 29.0, 28.5, 28.0, 27.5, 27.0, 26.5,
26.0, 25.5, 25.0, 24.5, 24.0, 23.5, 23.0, 22.5, 22.0, 21.5, 21.0, 20.5,
20.0, 19.5, 19.0, 18.5, 18.0, 17.5, 17.0, 16.5, 16.0, 15.5, 15.0, 14.5,
14.0, 13.5, 13.0, 12.5, 12.0, 11.5, 11.0, 10.5, 10.0],
dtype='float32', name='latitude')) Attributes: (0)
However, this “quantification” is not without its consequences. By default, xarray loads its
data lazily to conserve memory usage. Unless your data is chunked into a Dask array (using
the chunks
argument), this .quantify()
method will load data into memory, which
could slow your script or even cause your process to run out of memory. And so, we recommend
subsetting your data before quantifying it.
Also, these Pint Quantity
data objects are not properly handled by xarray when writing
to disk. And so, if you want to safely export your data, you will need to undo the
quantification with the .dequantify()
method, which converts your data back to a
unit-naive array with the unit as a text attribute
<xarray.DataArray 'Geopotential_height_isobaric' (latitude: 81)> Size: 324B
array([5636.367 , 5644.392 , 5652.7705, 5661.369 , 5669.813 , 5678.5083,
5687.433 , 5696.517 , 5705.927 , 5715.6123, 5725.702 , 5736.1387,
5746.884 , 5757.718 , 5768.566 , 5779.2812, 5789.8193, 5799.801 ,
5809.502 , 5818.7715, 5827.7744, 5836.921 , 5846.3857, 5855.668 ,
5864.2397, 5871.804 , 5878.769 , 5885.058 , 5890.129 , 5894.0293,
5897.146 , 5899.633 , 5901.674 , 5903.2773, 5904.41 , 5905.27 ,
5905.897 , 5906.592 , 5907.0083, 5907.0806, 5907.031 , 5906.871 ,
5906.777 , 5906.4556, 5906.121 , 5905.798 , 5905.6826, 5905.5986,
5905.4097, 5905.1245, 5904.773 , 5904.43 , 5903.954 , 5903.378 ,
5902.532 , 5901.714 , 5900.865 , 5900.0933, 5899.336 , 5898.4673,
5897.44 , 5896.233 , 5895.057 , 5893.633 , 5891.532 , 5888.15 ,
5883.094 , 5884.8022, 5887.923 , 5889.0054, 5889.114 , 5888.8887,
5888.685 , 5888.146 , 5887.567 , 5887.0317, 5886.299 , 5885.4214,
5884.515 , 5883.694 , 5883.072 ], dtype=float32)
Coordinates:
time1 datetime64[ns] 8B 2017-09-05T18:00:00
reftime datetime64[ns] 8B ...
* latitude (latitude) float32 324B 50.0 49.5 49.0 48.5 ... 11.0 10.5 10.0
isobaric3 float64 8B 5e+04
Attributes:
units: meter 5.636e+03 5.644e+03 5.653e+03 ... 5.885e+03 5.884e+03 5.883e+03
array([5636.367 , 5644.392 , 5652.7705, 5661.369 , 5669.813 , 5678.5083,
5687.433 , 5696.517 , 5705.927 , 5715.6123, 5725.702 , 5736.1387,
5746.884 , 5757.718 , 5768.566 , 5779.2812, 5789.8193, 5799.801 ,
5809.502 , 5818.7715, 5827.7744, 5836.921 , 5846.3857, 5855.668 ,
5864.2397, 5871.804 , 5878.769 , 5885.058 , 5890.129 , 5894.0293,
5897.146 , 5899.633 , 5901.674 , 5903.2773, 5904.41 , 5905.27 ,
5905.897 , 5906.592 , 5907.0083, 5907.0806, 5907.031 , 5906.871 ,
5906.777 , 5906.4556, 5906.121 , 5905.798 , 5905.6826, 5905.5986,
5905.4097, 5905.1245, 5904.773 , 5904.43 , 5903.954 , 5903.378 ,
5902.532 , 5901.714 , 5900.865 , 5900.0933, 5899.336 , 5898.4673,
5897.44 , 5896.233 , 5895.057 , 5893.633 , 5891.532 , 5888.15 ,
5883.094 , 5884.8022, 5887.923 , 5889.0054, 5889.114 , 5888.8887,
5888.685 , 5888.146 , 5887.567 , 5887.0317, 5886.299 , 5885.4214,
5884.515 , 5883.694 , 5883.072 ], dtype=float32) Coordinates: (4)
Indexes: (1)
PandasIndex
PandasIndex(Index([50.0, 49.5, 49.0, 48.5, 48.0, 47.5, 47.0, 46.5, 46.0, 45.5, 45.0, 44.5,
44.0, 43.5, 43.0, 42.5, 42.0, 41.5, 41.0, 40.5, 40.0, 39.5, 39.0, 38.5,
38.0, 37.5, 37.0, 36.5, 36.0, 35.5, 35.0, 34.5, 34.0, 33.5, 33.0, 32.5,
32.0, 31.5, 31.0, 30.5, 30.0, 29.5, 29.0, 28.5, 28.0, 27.5, 27.0, 26.5,
26.0, 25.5, 25.0, 24.5, 24.0, 23.5, 23.0, 22.5, 22.0, 21.5, 21.0, 20.5,
20.0, 19.5, 19.0, 18.5, 18.0, 17.5, 17.0, 16.5, 16.0, 15.5, 15.0, 14.5,
14.0, 13.5, 13.0, 12.5, 12.0, 11.5, 11.0, 10.5, 10.0],
dtype='float32', name='latitude')) Attributes: (1)
Other useful unit integration features include:
Unit-based selection/indexing:
<xarray.DataArray 'Geopotential_height_isobaric' (time1: 9, longitude: 131)> Size: 5kB
[1179 values with dtype=float32]
Coordinates:
* time1 (time1) datetime64[ns] 72B 2017-09-05T12:00:00 ... 2017-09-06T...
reftime datetime64[ns] 8B ...
latitude float32 4B 45.0
isobaric3 float64 8B 3e+04
* longitude (longitude) float32 524B 250.0 250.5 251.0 ... 314.0 314.5 315.0
Attributes:
long_name: Geopotential height @ Isobaric surface
units: gpm
Grib_Variable_Id: VAR_0-3-5_L100
Grib2_Parameter: [0 3 5]
Grib2_Parameter_Discipline: Meteorological products
Grib2_Parameter_Category: Mass
Grib2_Parameter_Name: Geopotential height
Grib2_Level_Type: 100
Grib2_Level_Desc: Isobaric surface
Grib2_Generating_Process_Type: Forecast
grid_mapping: LatLon_361X720-0p25S-180p00E Coordinates: (5)
Indexes: (2)
PandasIndex
PandasIndex(DatetimeIndex(['2017-09-05 12:00:00', '2017-09-05 15:00:00',
'2017-09-05 18:00:00', '2017-09-05 21:00:00',
'2017-09-06 00:00:00', '2017-09-06 03:00:00',
'2017-09-06 06:00:00', '2017-09-06 09:00:00',
'2017-09-06 12:00:00'],
dtype='datetime64[ns]', name='time1', freq=None)) PandasIndex
PandasIndex(Index([250.0, 250.5, 251.0, 251.5, 252.0, 252.5, 253.0, 253.5, 254.0, 254.5,
...
310.5, 311.0, 311.5, 312.0, 312.5, 313.0, 313.5, 314.0, 314.5, 315.0],
dtype='float32', name='longitude', length=131)) Attributes: (11)
long_name : Geopotential height @ Isobaric surface units : gpm Grib_Variable_Id : VAR_0-3-5_L100 Grib2_Parameter : [0 3 5] Grib2_Parameter_Discipline : Meteorological products Grib2_Parameter_Category : Mass Grib2_Parameter_Name : Geopotential height Grib2_Level_Type : 100 Grib2_Level_Desc : Isobaric surface Grib2_Generating_Process_Type : Forecast grid_mapping : LatLon_361X720-0p25S-180p00E
Unit conversion:
<xarray.DataArray 'Temperature_isobaric' (isobaric3: 31, latitude: 81,
longitude: 131)> Size: 1MB
<Quantity([[[-15.149994 -15.149994 -15.25 ... -14.949982 -14.949982 -14.850006]
[-15.25 -15.25 -15.350006 ... -14.949982 -14.949982 -14.949982]
[-15.350006 -15.350006 -15.350006 ... -15.049988 -15.049988 -15.049988]
...
[-12.350006 -12.350006 -12.350006 ... -15.149994 -15.049988 -14.949982]
[-12.149994 -12.149994 -12.149994 ... -15.049988 -15.049988 -14.949982]
[-11.949982 -11.949982 -11.949982 ... -15.049988 -14.949982 -14.850006]]
[[-16.649994 -16.649994 -16.649994 ... -17.549988 -17.549988 -17.649994]
[-16.75 -16.75 -16.850006 ... -17.649994 -17.649994 -17.649994]
[-16.949982 -16.949982 -16.949982 ... -17.75 -17.75 -17.75 ]
...
[-14.049988 -14.049988 -14.049988 ... -12.049988 -11.75 -11.549988]
[-13.949982 -13.949982 -13.949982 ... -12.049988 -11.75 -11.549988]
[-13.75 -13.850006 -13.850006 ... -12.049988 -11.75 -11.549988]]
[[-21.75 -21.75 -21.75 ... -22.649994 -22.649994 -22.649994]
[-21.949997 -21.84999 -21.84999 ... -22.75 -22.75 -22.75 ]
[-22.049988 -22.049988 -22.049988 ... -22.84999 -22.84999 -22.949997]
...
...
...
[ 22.149994 22.149994 22.149994 ... 22.550018 22.649994 22.75 ]
[ 22.050018 22.050018 21.950012 ... 22.550018 22.149994 22.350006]
[ 21.950012 21.75 22.149994 ... 22.550018 22.450012 22.050018]]
[[ 15.649994 15.149994 14.649994 ... 11.950012 11.850006 11.75 ]
[ 15.149994 15.149994 15.050018 ... 11.950012 11.649994 11.450012]
[ 15.050018 14.850006 15.050018 ... 11.850006 11.75 11.649994]
...
[ 24.149994 24.25 24.149994 ... 24.649994 24.649994 24.850006]
[ 23.950012 23.950012 23.850006 ... 24.649994 24.25 24.450012]
[ 23.850006 23.649994 23.75 ... 24.649994 24.25 24.050018]]
[[ 17.050018 16.550018 16.050018 ... 13.450012 13.450012 13.550018]
[ 16.550018 16.550018 16.450012 ... 13.350006 13.050018 12.950012]
[ 16.450012 16.25 16.450012 ... 13.050018 12.850006 12.850006]
...
[ 26.350006 26.350006 26.25 ... 26.75 26.850006 26.950012]
[ 26.050018 26.050018 25.950012 ... 26.75 26.350006 26.550018]
[ 26.050018 25.75 25.649994 ... 26.75 26.350006 26.149994]]], 'degree_Celsius')>
Coordinates:
time1 datetime64[ns] 8B 2017-09-05T12:00:00
reftime datetime64[ns] 8B ...
* latitude (latitude) float32 324B 50.0 49.5 49.0 48.5 ... 11.0 10.5 10.0
* isobaric3 (isobaric3) float64 248B 100.0 200.0 300.0 ... 9.75e+04 1e+05
* longitude (longitude) float32 524B 250.0 250.5 251.0 ... 314.0 314.5 315.0
metpy_crs object 8B Projection: latitude_longitude
Attributes:
long_name: Temperature @ Isobaric surface
Grib_Variable_Id: VAR_0-0-0_L100
Grib2_Parameter: [0 0 0]
Grib2_Parameter_Discipline: Meteorological products
Grib2_Parameter_Category: Temperature
Grib2_Parameter_Name: Temperature
Grib2_Level_Type: 100
Grib2_Level_Desc: Isobaric surface
Grib2_Generating_Process_Type: Forecast
grid_mapping: LatLon_361X720-0p25S-180p00E Coordinates: (6)
time1
()
datetime64[ns]
2017-09-05T12:00:00
standard_name : time long_name : time udunits : Hour since 2017-09-05T12:00:00Z _metpy_axis : time array('2017-09-05T12:00:00.000000000', dtype='datetime64[ns]') reftime
()
datetime64[ns]
...
standard_name : forecast_reference_time long_name : GRIB reference time [1 values with dtype=datetime64[ns]] latitude
(latitude)
float32
50.0 49.5 49.0 ... 11.0 10.5 10.0
units : degrees_north standard_name : latitude _metpy_axis : y,latitude array([50. , 49.5, 49. , 48.5, 48. , 47.5, 47. , 46.5, 46. , 45.5, 45. , 44.5,
44. , 43.5, 43. , 42.5, 42. , 41.5, 41. , 40.5, 40. , 39.5, 39. , 38.5,
38. , 37.5, 37. , 36.5, 36. , 35.5, 35. , 34.5, 34. , 33.5, 33. , 32.5,
32. , 31.5, 31. , 30.5, 30. , 29.5, 29. , 28.5, 28. , 27.5, 27. , 26.5,
26. , 25.5, 25. , 24.5, 24. , 23.5, 23. , 22.5, 22. , 21.5, 21. , 20.5,
20. , 19.5, 19. , 18.5, 18. , 17.5, 17. , 16.5, 16. , 15.5, 15. , 14.5,
14. , 13.5, 13. , 12.5, 12. , 11.5, 11. , 10.5, 10. ], dtype=float32) isobaric3
(isobaric3)
float64
100.0 200.0 ... 9.75e+04 1e+05
units : Pa positive : down _metpy_axis : vertical array([ 100., 200., 300., 500., 700., 1000., 2000., 3000.,
5000., 7000., 10000., 15000., 20000., 25000., 30000., 35000.,
40000., 45000., 50000., 55000., 60000., 65000., 70000., 75000.,
80000., 85000., 90000., 92500., 95000., 97500., 100000.]) longitude
(longitude)
float32
250.0 250.5 251.0 ... 314.5 315.0
units : degrees_east standard_name : longitude _metpy_axis : x,longitude array([250. , 250.5, 251. , 251.5, 252. , 252.5, 253. , 253.5, 254. , 254.5,
255. , 255.5, 256. , 256.5, 257. , 257.5, 258. , 258.5, 259. , 259.5,
260. , 260.5, 261. , 261.5, 262. , 262.5, 263. , 263.5, 264. , 264.5,
265. , 265.5, 266. , 266.5, 267. , 267.5, 268. , 268.5, 269. , 269.5,
270. , 270.5, 271. , 271.5, 272. , 272.5, 273. , 273.5, 274. , 274.5,
275. , 275.5, 276. , 276.5, 277. , 277.5, 278. , 278.5, 279. , 279.5,
280. , 280.5, 281. , 281.5, 282. , 282.5, 283. , 283.5, 284. , 284.5,
285. , 285.5, 286. , 286.5, 287. , 287.5, 288. , 288.5, 289. , 289.5,
290. , 290.5, 291. , 291.5, 292. , 292.5, 293. , 293.5, 294. , 294.5,
295. , 295.5, 296. , 296.5, 297. , 297.5, 298. , 298.5, 299. , 299.5,
300. , 300.5, 301. , 301.5, 302. , 302.5, 303. , 303.5, 304. , 304.5,
305. , 305.5, 306. , 306.5, 307. , 307.5, 308. , 308.5, 309. , 309.5,
310. , 310.5, 311. , 311.5, 312. , 312.5, 313. , 313.5, 314. , 314.5,
315. ], dtype=float32) metpy_crs
()
object
Projection: latitude_longitude
array(<metpy.plots.mapping.CFProjection object at 0x7f74081ecb90>,
dtype=object) Indexes: (3)
PandasIndex
PandasIndex(Index([50.0, 49.5, 49.0, 48.5, 48.0, 47.5, 47.0, 46.5, 46.0, 45.5, 45.0, 44.5,
44.0, 43.5, 43.0, 42.5, 42.0, 41.5, 41.0, 40.5, 40.0, 39.5, 39.0, 38.5,
38.0, 37.5, 37.0, 36.5, 36.0, 35.5, 35.0, 34.5, 34.0, 33.5, 33.0, 32.5,
32.0, 31.5, 31.0, 30.5, 30.0, 29.5, 29.0, 28.5, 28.0, 27.5, 27.0, 26.5,
26.0, 25.5, 25.0, 24.5, 24.0, 23.5, 23.0, 22.5, 22.0, 21.5, 21.0, 20.5,
20.0, 19.5, 19.0, 18.5, 18.0, 17.5, 17.0, 16.5, 16.0, 15.5, 15.0, 14.5,
14.0, 13.5, 13.0, 12.5, 12.0, 11.5, 11.0, 10.5, 10.0],
dtype='float32', name='latitude')) PandasIndex
PandasIndex(Index([ 100.0, 200.0, 300.0, 500.0, 700.0, 1000.0, 2000.0,
3000.0, 5000.0, 7000.0, 10000.0, 15000.0, 20000.0, 25000.0,
30000.0, 35000.0, 40000.0, 45000.0, 50000.0, 55000.0, 60000.0,
65000.0, 70000.0, 75000.0, 80000.0, 85000.0, 90000.0, 92500.0,
95000.0, 97500.0, 100000.0],
dtype='float64', name='isobaric3')) PandasIndex
PandasIndex(Index([250.0, 250.5, 251.0, 251.5, 252.0, 252.5, 253.0, 253.5, 254.0, 254.5,
...
310.5, 311.0, 311.5, 312.0, 312.5, 313.0, 313.5, 314.0, 314.5, 315.0],
dtype='float32', name='longitude', length=131)) Attributes: (10)
long_name : Temperature @ Isobaric surface Grib_Variable_Id : VAR_0-0-0_L100 Grib2_Parameter : [0 0 0] Grib2_Parameter_Discipline : Meteorological products Grib2_Parameter_Category : Temperature Grib2_Parameter_Name : Temperature Grib2_Level_Type : 100 Grib2_Level_Desc : Isobaric surface Grib2_Generating_Process_Type : Forecast grid_mapping : LatLon_361X720-0p25S-180p00E
To base unit conversion:
<xarray.DataArray 'Temperature_isobaric' (isobaric3: 31, latitude: 81,
longitude: 131)> Size: 1MB
<Quantity([[[258. 258. 257.9 ... 258.2 258.2 258.3]
[257.9 257.9 257.8 ... 258.2 258.2 258.2]
[257.8 257.8 257.8 ... 258.1 258.1 258.1]
...
[260.8 260.8 260.8 ... 258. 258.1 258.2]
[261. 261. 261. ... 258.1 258.1 258.2]
[261.2 261.2 261.2 ... 258.1 258.2 258.3]]
[[256.5 256.5 256.5 ... 255.6 255.6 255.5]
[256.4 256.4 256.3 ... 255.5 255.5 255.5]
[256.2 256.2 256.2 ... 255.4 255.4 255.4]
...
[259.1 259.1 259.1 ... 261.1 261.4 261.6]
[259.2 259.2 259.2 ... 261.1 261.4 261.6]
[259.4 259.3 259.3 ... 261.1 261.4 261.6]]
[[251.4 251.4 251.4 ... 250.5 250.5 250.5]
[251.2 251.3 251.3 ... 250.4 250.4 250.4]
[251.1 251.1 251.1 ... 250.3 250.3 250.2]
...
...
...
[295.3 295.3 295.3 ... 295.7 295.8 295.9]
[295.2 295.2 295.1 ... 295.7 295.3 295.5]
[295.1 294.9 295.3 ... 295.7 295.6 295.2]]
[[288.8 288.3 287.8 ... 285.1 285. 284.9]
[288.3 288.3 288.2 ... 285.1 284.8 284.6]
[288.2 288. 288.2 ... 285. 284.9 284.8]
...
[297.3 297.4 297.3 ... 297.8 297.8 298. ]
[297.1 297.1 297. ... 297.8 297.4 297.6]
[297. 296.8 296.9 ... 297.8 297.4 297.2]]
[[290.2 289.7 289.2 ... 286.6 286.6 286.7]
[289.7 289.7 289.6 ... 286.5 286.2 286.1]
[289.6 289.4 289.6 ... 286.2 286. 286. ]
...
[299.5 299.5 299.4 ... 299.9 300. 300.1]
[299.2 299.2 299.1 ... 299.9 299.5 299.7]
[299.2 298.9 298.8 ... 299.9 299.5 299.3]]], 'kelvin')>
Coordinates:
time1 datetime64[ns] 8B 2017-09-05T12:00:00
reftime datetime64[ns] 8B ...
* latitude (latitude) float32 324B 50.0 49.5 49.0 48.5 ... 11.0 10.5 10.0
* isobaric3 (isobaric3) float64 248B 100.0 200.0 300.0 ... 9.75e+04 1e+05
* longitude (longitude) float32 524B 250.0 250.5 251.0 ... 314.0 314.5 315.0
metpy_crs object 8B Projection: latitude_longitude
Attributes:
long_name: Temperature @ Isobaric surface
Grib_Variable_Id: VAR_0-0-0_L100
Grib2_Parameter: [0 0 0]
Grib2_Parameter_Discipline: Meteorological products
Grib2_Parameter_Category: Temperature
Grib2_Parameter_Name: Temperature
Grib2_Level_Type: 100
Grib2_Level_Desc: Isobaric surface
Grib2_Generating_Process_Type: Forecast
grid_mapping: LatLon_361X720-0p25S-180p00E Coordinates: (6)
time1
()
datetime64[ns]
2017-09-05T12:00:00
standard_name : time long_name : time udunits : Hour since 2017-09-05T12:00:00Z _metpy_axis : time array('2017-09-05T12:00:00.000000000', dtype='datetime64[ns]') reftime
()
datetime64[ns]
...
standard_name : forecast_reference_time long_name : GRIB reference time [1 values with dtype=datetime64[ns]] latitude
(latitude)
float32
50.0 49.5 49.0 ... 11.0 10.5 10.0
units : degrees_north standard_name : latitude _metpy_axis : y,latitude array([50. , 49.5, 49. , 48.5, 48. , 47.5, 47. , 46.5, 46. , 45.5, 45. , 44.5,
44. , 43.5, 43. , 42.5, 42. , 41.5, 41. , 40.5, 40. , 39.5, 39. , 38.5,
38. , 37.5, 37. , 36.5, 36. , 35.5, 35. , 34.5, 34. , 33.5, 33. , 32.5,
32. , 31.5, 31. , 30.5, 30. , 29.5, 29. , 28.5, 28. , 27.5, 27. , 26.5,
26. , 25.5, 25. , 24.5, 24. , 23.5, 23. , 22.5, 22. , 21.5, 21. , 20.5,
20. , 19.5, 19. , 18.5, 18. , 17.5, 17. , 16.5, 16. , 15.5, 15. , 14.5,
14. , 13.5, 13. , 12.5, 12. , 11.5, 11. , 10.5, 10. ], dtype=float32) isobaric3
(isobaric3)
float64
100.0 200.0 ... 9.75e+04 1e+05
units : Pa positive : down _metpy_axis : vertical array([ 100., 200., 300., 500., 700., 1000., 2000., 3000.,
5000., 7000., 10000., 15000., 20000., 25000., 30000., 35000.,
40000., 45000., 50000., 55000., 60000., 65000., 70000., 75000.,
80000., 85000., 90000., 92500., 95000., 97500., 100000.]) longitude
(longitude)
float32
250.0 250.5 251.0 ... 314.5 315.0
units : degrees_east standard_name : longitude _metpy_axis : x,longitude array([250. , 250.5, 251. , 251.5, 252. , 252.5, 253. , 253.5, 254. , 254.5,
255. , 255.5, 256. , 256.5, 257. , 257.5, 258. , 258.5, 259. , 259.5,
260. , 260.5, 261. , 261.5, 262. , 262.5, 263. , 263.5, 264. , 264.5,
265. , 265.5, 266. , 266.5, 267. , 267.5, 268. , 268.5, 269. , 269.5,
270. , 270.5, 271. , 271.5, 272. , 272.5, 273. , 273.5, 274. , 274.5,
275. , 275.5, 276. , 276.5, 277. , 277.5, 278. , 278.5, 279. , 279.5,
280. , 280.5, 281. , 281.5, 282. , 282.5, 283. , 283.5, 284. , 284.5,
285. , 285.5, 286. , 286.5, 287. , 287.5, 288. , 288.5, 289. , 289.5,
290. , 290.5, 291. , 291.5, 292. , 292.5, 293. , 293.5, 294. , 294.5,
295. , 295.5, 296. , 296.5, 297. , 297.5, 298. , 298.5, 299. , 299.5,
300. , 300.5, 301. , 301.5, 302. , 302.5, 303. , 303.5, 304. , 304.5,
305. , 305.5, 306. , 306.5, 307. , 307.5, 308. , 308.5, 309. , 309.5,
310. , 310.5, 311. , 311.5, 312. , 312.5, 313. , 313.5, 314. , 314.5,
315. ], dtype=float32) metpy_crs
()
object
Projection: latitude_longitude
array(<metpy.plots.mapping.CFProjection object at 0x7f74081ed4f0>,
dtype=object) Indexes: (3)
PandasIndex
PandasIndex(Index([50.0, 49.5, 49.0, 48.5, 48.0, 47.5, 47.0, 46.5, 46.0, 45.5, 45.0, 44.5,
44.0, 43.5, 43.0, 42.5, 42.0, 41.5, 41.0, 40.5, 40.0, 39.5, 39.0, 38.5,
38.0, 37.5, 37.0, 36.5, 36.0, 35.5, 35.0, 34.5, 34.0, 33.5, 33.0, 32.5,
32.0, 31.5, 31.0, 30.5, 30.0, 29.5, 29.0, 28.5, 28.0, 27.5, 27.0, 26.5,
26.0, 25.5, 25.0, 24.5, 24.0, 23.5, 23.0, 22.5, 22.0, 21.5, 21.0, 20.5,
20.0, 19.5, 19.0, 18.5, 18.0, 17.5, 17.0, 16.5, 16.0, 15.5, 15.0, 14.5,
14.0, 13.5, 13.0, 12.5, 12.0, 11.5, 11.0, 10.5, 10.0],
dtype='float32', name='latitude')) PandasIndex
PandasIndex(Index([ 100.0, 200.0, 300.0, 500.0, 700.0, 1000.0, 2000.0,
3000.0, 5000.0, 7000.0, 10000.0, 15000.0, 20000.0, 25000.0,
30000.0, 35000.0, 40000.0, 45000.0, 50000.0, 55000.0, 60000.0,
65000.0, 70000.0, 75000.0, 80000.0, 85000.0, 90000.0, 92500.0,
95000.0, 97500.0, 100000.0],
dtype='float64', name='isobaric3')) PandasIndex
PandasIndex(Index([250.0, 250.5, 251.0, 251.5, 252.0, 252.5, 253.0, 253.5, 254.0, 254.5,
...
310.5, 311.0, 311.5, 312.0, 312.5, 313.0, 313.5, 314.0, 314.5, 315.0],
dtype='float32', name='longitude', length=131)) Attributes: (10)
long_name : Temperature @ Isobaric surface Grib_Variable_Id : VAR_0-0-0_L100 Grib2_Parameter : [0 0 0] Grib2_Parameter_Discipline : Meteorological products Grib2_Parameter_Category : Temperature Grib2_Parameter_Name : Temperature Grib2_Level_Type : 100 Grib2_Level_Desc : Isobaric surface Grib2_Generating_Process_Type : Forecast grid_mapping : LatLon_361X720-0p25S-180p00E
Unit conversion for coordinates:
<xarray.DataArray 'isobaric3' ()> Size: 8B
array(500.)
Coordinates:
time1 datetime64[ns] 8B 2017-09-05T18:00:00
reftime datetime64[ns] 8B ...
isobaric3 float64 8B 500.0
Attributes:
units: hPa
positive: down
_metpy_axis: vertical
Accessing just the underlying unit array:
Magnitude [[5883.3564453125 5879.31640625 5875.3564453125 ... 5769.396484375 5769.99609375 5770.43603515625] [5885.47607421875 5882.236328125 5877.67626953125 ... 5783.916015625 5784.51611328125 5785.1962890625] [5888.87646484375 5885.15625 5880.916015625 ... 5798.47607421875 5799.076171875 5799.71630859375] ... [5892.51611328125 5892.236328125 5891.99609375 ... 5881.55615234375 5881.43603515625 5880.59619140625] [5891.83642578125 5891.59619140625 5891.71630859375 ... 5880.2763671875 5880.3564453125 5879.916015625] [5891.3564453125 5891.59619140625 5891.3564453125 ... 5879.87646484375 5879.59619140625 5878.99609375]] Units meter
Accessing just the underlying units:
meter
Calculations
MetPy’s xarray integration extends to its calculation suite as well. Most grid-capable
calculations (such as thermodynamics, kinematics, and smoothers) fully support xarray
DataArray
s by accepting them as inputs, returning them as outputs, and automatically
using the attached coordinate data/metadata to determine grid arguments
<xarray.DataArray (latitude: 81, longitude: 131)> Size: 85kB
<Quantity([[ 2.33535886 4.60981877 2.93625413 ... 22.89067952 22.89183583
23.49234567]
[ 4.38966801 4.64400083 4.42111986 ... 23.12487204 23.12526033
23.28446103]
[ 5.54483395 4.9994661 5.35235118 ... 22.97939121 22.94731075
22.75482798]
...
[-3.42134235 -3.29600145 -3.16911313 ... -7.60556204 -6.84423212
-4.56488464]
[-3.84801887 -2.12410641 -2.1224862 ... -5.57355154 -6.1049832
-5.30945593]
[-2.64743317 2.22914893 -2.78516091 ... 0.27885616 -4.18284239
-7.24175843]], 'meter / second')>
Coordinates:
time1 datetime64[ns] 8B 2017-09-05T18:00:00
reftime datetime64[ns] 8B 2017-09-05T12:00:00
* latitude (latitude) float32 324B 50.0 49.5 49.0 48.5 ... 11.0 10.5 10.0
* longitude (longitude) float32 524B 250.0 250.5 251.0 ... 314.0 314.5 315.0
metpy_crs object 8B Projection: latitude_longitude
isobaric3 float64 8B 5e+04 Coordinates: (6)
time1
()
datetime64[ns]
2017-09-05T18:00:00
standard_name : time long_name : time udunits : Hour since 2017-09-05T12:00:00Z _metpy_axis : time array('2017-09-05T18:00:00.000000000', dtype='datetime64[ns]') reftime
()
datetime64[ns]
2017-09-05T12:00:00
standard_name : forecast_reference_time long_name : GRIB reference time array('2017-09-05T12:00:00.000000000', dtype='datetime64[ns]') latitude
(latitude)
float32
50.0 49.5 49.0 ... 11.0 10.5 10.0
units : degrees_north standard_name : latitude _metpy_axis : y,latitude array([50. , 49.5, 49. , 48.5, 48. , 47.5, 47. , 46.5, 46. , 45.5, 45. , 44.5,
44. , 43.5, 43. , 42.5, 42. , 41.5, 41. , 40.5, 40. , 39.5, 39. , 38.5,
38. , 37.5, 37. , 36.5, 36. , 35.5, 35. , 34.5, 34. , 33.5, 33. , 32.5,
32. , 31.5, 31. , 30.5, 30. , 29.5, 29. , 28.5, 28. , 27.5, 27. , 26.5,
26. , 25.5, 25. , 24.5, 24. , 23.5, 23. , 22.5, 22. , 21.5, 21. , 20.5,
20. , 19.5, 19. , 18.5, 18. , 17.5, 17. , 16.5, 16. , 15.5, 15. , 14.5,
14. , 13.5, 13. , 12.5, 12. , 11.5, 11. , 10.5, 10. ], dtype=float32) longitude
(longitude)
float32
250.0 250.5 251.0 ... 314.5 315.0
units : degrees_east standard_name : longitude _metpy_axis : x,longitude array([250. , 250.5, 251. , 251.5, 252. , 252.5, 253. , 253.5, 254. , 254.5,
255. , 255.5, 256. , 256.5, 257. , 257.5, 258. , 258.5, 259. , 259.5,
260. , 260.5, 261. , 261.5, 262. , 262.5, 263. , 263.5, 264. , 264.5,
265. , 265.5, 266. , 266.5, 267. , 267.5, 268. , 268.5, 269. , 269.5,
270. , 270.5, 271. , 271.5, 272. , 272.5, 273. , 273.5, 274. , 274.5,
275. , 275.5, 276. , 276.5, 277. , 277.5, 278. , 278.5, 279. , 279.5,
280. , 280.5, 281. , 281.5, 282. , 282.5, 283. , 283.5, 284. , 284.5,
285. , 285.5, 286. , 286.5, 287. , 287.5, 288. , 288.5, 289. , 289.5,
290. , 290.5, 291. , 291.5, 292. , 292.5, 293. , 293.5, 294. , 294.5,
295. , 295.5, 296. , 296.5, 297. , 297.5, 298. , 298.5, 299. , 299.5,
300. , 300.5, 301. , 301.5, 302. , 302.5, 303. , 303.5, 304. , 304.5,
305. , 305.5, 306. , 306.5, 307. , 307.5, 308. , 308.5, 309. , 309.5,
310. , 310.5, 311. , 311.5, 312. , 312.5, 313. , 313.5, 314. , 314.5,
315. ], dtype=float32) metpy_crs
()
object
Projection: latitude_longitude
array(<metpy.plots.mapping.CFProjection object at 0x7f742a77c9b0>,
dtype=object) isobaric3
()
float64
5e+04
units : Pa positive : down _metpy_axis : vertical Indexes: (2)
PandasIndex
PandasIndex(Index([50.0, 49.5, 49.0, 48.5, 48.0, 47.5, 47.0, 46.5, 46.0, 45.5, 45.0, 44.5,
44.0, 43.5, 43.0, 42.5, 42.0, 41.5, 41.0, 40.5, 40.0, 39.5, 39.0, 38.5,
38.0, 37.5, 37.0, 36.5, 36.0, 35.5, 35.0, 34.5, 34.0, 33.5, 33.0, 32.5,
32.0, 31.5, 31.0, 30.5, 30.0, 29.5, 29.0, 28.5, 28.0, 27.5, 27.0, 26.5,
26.0, 25.5, 25.0, 24.5, 24.0, 23.5, 23.0, 22.5, 22.0, 21.5, 21.0, 20.5,
20.0, 19.5, 19.0, 18.5, 18.0, 17.5, 17.0, 16.5, 16.0, 15.5, 15.0, 14.5,
14.0, 13.5, 13.0, 12.5, 12.0, 11.5, 11.0, 10.5, 10.0],
dtype='float32', name='latitude')) PandasIndex
PandasIndex(Index([250.0, 250.5, 251.0, 251.5, 252.0, 252.5, 253.0, 253.5, 254.0, 254.5,
...
310.5, 311.0, 311.5, 312.0, 312.5, 313.0, 313.5, 314.0, 314.5, 315.0],
dtype='float32', name='longitude', length=131)) Attributes: (0)
For profile-based calculations (and most remaining calculations in the metpy.calc
module), xarray DataArray
s are accepted as inputs, but the outputs remain Pint
Quantities (typically scalars). Note that MetPy’s profile calculations (such as CAPE and
CIN) require the sounding to be ordered from highest to lowest pressure. As seen earlier
in this tutorial, this data is ordered the other way, so we need to reverse the inputs
to mpcalc.surface_based_cape_cin
.
2106.334501780329 joule/kilogram
A few remaining portions of MetPy’s calculations (mainly the interpolation module and a few
other functions) do not fully support xarray, and so, use of .values
may be needed to
convert to a bare NumPy array. For full information on xarray support for your function of
interest, see the Reference Guide .
CF-Compliant Dataset Example
The GFS sample used throughout this tutorial so far has been an example of a CF-compliant
dataset. These kinds of datasets are easiest to work with it MetPy, since most of the
“xarray magic” uses CF metadata. For this kind of dataset, a typical workflow looks like the
following
<matplotlib.collections.QuadMesh object at 0x7f742bd20f50>
# Save output
subset . metpy . dequantify () . drop_vars ( 'metpy_crs' ) . to_netcdf ( '500hPa_analysis.nc' )
Non-Compliant Dataset Example
When CF metadata (such as grid mapping, coordinate attributes, etc.) are missing, a bit more
work is required to manually supply the required information, for example,
nonstandard = xr . Dataset ({
'temperature' : (( 'y' , 'x' ), np . arange ( 0 , 9 ) . reshape ( 3 , 3 ) * units . degC ),
'y' : ( 'y' , np . arange ( 0 , 3 ) * 1e5 , { 'units' : 'km' }),
'x' : ( 'x' , np . arange ( 0 , 3 ) * 1e5 , { 'units' : 'km' })
})
# Add both CRS and then lat/lon coords using chained methods
data = nonstandard . metpy . assign_crs (
grid_mapping_name = 'lambert_conformal_conic' ,
latitude_of_projection_origin = 38.5 ,
longitude_of_central_meridian = 262.5 ,
standard_parallel = 38.5 ,
earth_radius = 6371229.0
) . metpy . assign_latitude_longitude ()
# Preview the changes
data
<xarray.Dataset> Size: 272B
Dimensions: (y: 3, x: 3)
Coordinates:
* y (y) float64 24B 0.0 1e+05 2e+05
* x (x) float64 24B 0.0 1e+05 2e+05
metpy_crs object 8B Projection: lambert_conformal_conic
latitude (y, x) float64 72B 38.5 38.49 38.48 39.4 ... 40.3 40.29 40.28
longitude (y, x) float64 72B -97.5 -96.35 -95.2 ... -97.5 -96.32 -95.14
Data variables:
temperature (y, x) int64 72B <Quantity([[0 1 2] [3 4 5] [6 7 8]], 'deg... Dimensions:
Coordinates: (5)
y
(y)
float64
0.0 1e+05 2e+05
array([ 0., 100000., 200000.]) x
(x)
float64
0.0 1e+05 2e+05
array([ 0., 100000., 200000.]) metpy_crs
()
object
Projection: lambert_conformal_conic
array(<metpy.plots.mapping.CFProjection object at 0x7f742a57aad0>,
dtype=object) latitude
(y, x)
float64
38.5 38.49 38.48 ... 40.29 40.28
units : degrees_north standard_name : latitude array([[38.5 , 38.49438649, 38.47754859],
[39.39925224, 39.39356847, 39.37651982],
[40.29828138, 40.29252697, 40.27526648]]) longitude
(y, x)
float64
-97.5 -96.35 ... -96.32 -95.14
units : degrees_east standard_name : longitude array([[-97.5 , -96.35096705, -95.20229214],
[-97.5 , -96.33644176, -95.17325532],
[-97.5 , -96.32154456, -95.14347537]]) Data variables: (1)
Indexes: (2)
Attributes: (0)
Once the CRS and additional coordinates are assigned, you can generally proceed as you would
for a CF-compliant dataset.
What Could Go Wrong?
Depending on your dataset and what you are trying to do, you might run into problems with
xarray and MetPy. Below are examples of some of the most common issues
Multiple coordinate conflict
An axis not being available
An axis not being interpretable
UndefinedUnitError
Coordinate Conflict
Code:
x = data [ 'Temperature' ] . metpy . x
Error Message:
/ home / user / env / MetPy / metpy / xarray . py : 305 : UserWarning : More than
one x coordinate present for variable "Temperature" .
Fix:
Manually assign the coordinates using the assign_coordinates()
method on your DataArray,
or by specifying the coordinates
argument to the parse_cf()
method on your Dataset,
to map the time
, vertical
, y
, latitude
, x
, and longitude
axes (as
applicable to your data) to the corresponding coordinates.
data [ 'Temperature' ] . assign_coordinates ({ 'time' : 'time' , 'vertical' : 'isobaric' ,
'y' : 'y' , 'x' : 'x' })
x = data [ 'Temperature' ] . metpy . x
or
temperature = data . metpy . parse_cf ( 'Temperature' ,
coordinates = { 'time' : 'time' , 'vertical' : 'isobaric' ,
'y' : 'y' , 'x' : 'x' })
x = temperature . metpy . x
Axis Unavailable
Code:
data [ 'Temperature' ] . metpy . vertical
Error Message:
AttributeError : vertical attribute is not available .
This means that your data variable does not have the coordinate that was requested, at
least as far as the parser can recognize. Verify that you are requesting a
coordinate that your data actually has, and if it still is not available,
you will need to manually specify the coordinates as discussed above.
Axis Not Interpretable
Code:
x , y , ensemble = data [ 'Temperature' ] . metpy . coordinates ( 'x' , 'y' , 'ensemble' )
Error Message:
AttributeError : 'ensemble' is not an interpretable axis
This means that you are requesting a coordinate that MetPy is (currently) unable to parse.
While this means it cannot be recognized automatically, you can still obtain your desired
coordinate directly by accessing it by name. If you have a need for systematic
identification of a new coordinate type, we welcome pull requests for such new functionality
on GitHub!
Undefined Unit Error
If the units attribute on your xarray data is not recognizable by Pint, you will likely
receive an UndefinedUnitError
. In this case, you will likely have to update the units
attribute to one that can be parsed properly by Pint. It is our aim to have all valid
CF/UDUNITS unit strings be parseable, but this work is ongoing. If many variables in your
dataset are not parseable, the .update_attribute
method on the MetPy accessor may come
in handy.
Total running time of the script: (0 minutes 2.833 seconds)
Gallery generated by Sphinx-Gallery