Plot Profiles from ICON 3D Data
Here, we proceed with ICON data. We will have a look at 3D ICON data.
Load Python Libraries
[1]:
%matplotlib inline
# system libs
import os, sys, glob
# array operators and netcdf datasets
import numpy as np
import xarray as xr
xr.set_options(keep_attrs=True)
# plotting
import pylab as plt
import seaborn as sns
sns.set_context('talk')
Open Data with xarray
General Paths
[2]:
exercise_path = '/work/bb1224/2023_MS-COURSE'
data_path = f'{exercise_path}/data'
icon_data_path = f'{data_path}/icon-lem'
This is very similar to the tasks already done.
[3]:
os.listdir(icon_data_path)
[3]:
['grids-extpar', 'experiments', 'bc-init']
Now, we select the experiment
folder in which pre-calculated experiments are stored. Later, you need to change this directory to your ICON output directory!
[4]:
exp_name = 'icon_lam_1dom_lpz-base'
exp_path = f'{icon_data_path}/experiments/{exp_name}'
[5]:
sorted( os.listdir( exp_path, ))
[5]:
['2d_cloud_DOM01_ML_20210516T000000Z.nc',
'2d_cloud_DOM01_ML_20210516T010000Z.nc',
'2d_cloud_DOM01_ML_20210516T020000Z.nc',
'2d_cloud_DOM01_ML_20210516T030000Z.nc',
'2d_cloud_DOM01_ML_20210516T040000Z.nc',
'2d_cloud_DOM01_ML_20210516T050000Z.nc',
'2d_cloud_DOM01_ML_20210516T060000Z.nc',
'2d_cloud_DOM01_ML_20210516T070000Z.nc',
'2d_cloud_DOM01_ML_20210516T080000Z.nc',
'2d_cloud_DOM01_ML_20210516T090000Z.nc',
'2d_cloud_DOM01_ML_20210516T100000Z.nc',
'2d_cloud_DOM01_ML_20210516T110000Z.nc',
'2d_cloud_DOM01_ML_20210516T120000Z.nc',
'2d_cloud_DOM01_ML_20210516T130000Z.nc',
'2d_cloud_DOM01_ML_20210516T140000Z.nc',
'2d_cloud_DOM01_ML_20210516T150000Z.nc',
'2d_cloud_DOM01_ML_20210516T160000Z.nc',
'2d_cloud_DOM01_ML_20210516T170000Z.nc',
'2d_cloud_DOM01_ML_20210516T180000Z.nc',
'2d_cloud_DOM01_ML_20210516T190000Z.nc',
'2d_cloud_DOM01_ML_20210516T200000Z.nc',
'2d_cloud_DOM01_ML_20210516T210000Z.nc',
'2d_cloud_DOM01_ML_20210516T220000Z.nc',
'2d_cloud_DOM01_ML_20210516T230000Z.nc',
'2d_cloud_DOM01_ML_20210517T000000Z.nc',
'2d_rad_DOM01_ML_20210516T000000Z.nc',
'2d_rad_DOM01_ML_20210516T010000Z.nc',
'2d_rad_DOM01_ML_20210516T020000Z.nc',
'2d_rad_DOM01_ML_20210516T030000Z.nc',
'2d_rad_DOM01_ML_20210516T040000Z.nc',
'2d_rad_DOM01_ML_20210516T050000Z.nc',
'2d_rad_DOM01_ML_20210516T060000Z.nc',
'2d_rad_DOM01_ML_20210516T070000Z.nc',
'2d_rad_DOM01_ML_20210516T080000Z.nc',
'2d_rad_DOM01_ML_20210516T090000Z.nc',
'2d_rad_DOM01_ML_20210516T100000Z.nc',
'2d_rad_DOM01_ML_20210516T110000Z.nc',
'2d_rad_DOM01_ML_20210516T120000Z.nc',
'2d_rad_DOM01_ML_20210516T130000Z.nc',
'2d_rad_DOM01_ML_20210516T140000Z.nc',
'2d_rad_DOM01_ML_20210516T150000Z.nc',
'2d_rad_DOM01_ML_20210516T160000Z.nc',
'2d_rad_DOM01_ML_20210516T170000Z.nc',
'2d_rad_DOM01_ML_20210516T180000Z.nc',
'2d_rad_DOM01_ML_20210516T190000Z.nc',
'2d_rad_DOM01_ML_20210516T200000Z.nc',
'2d_rad_DOM01_ML_20210516T210000Z.nc',
'2d_rad_DOM01_ML_20210516T220000Z.nc',
'2d_rad_DOM01_ML_20210516T230000Z.nc',
'2d_rad_DOM01_ML_20210517T000000Z.nc',
'2d_surface_DOM01_ML_20210516T000000Z.nc',
'2d_surface_DOM01_ML_20210516T010000Z.nc',
'2d_surface_DOM01_ML_20210516T020000Z.nc',
'2d_surface_DOM01_ML_20210516T030000Z.nc',
'2d_surface_DOM01_ML_20210516T040000Z.nc',
'2d_surface_DOM01_ML_20210516T050000Z.nc',
'2d_surface_DOM01_ML_20210516T060000Z.nc',
'2d_surface_DOM01_ML_20210516T070000Z.nc',
'2d_surface_DOM01_ML_20210516T080000Z.nc',
'2d_surface_DOM01_ML_20210516T090000Z.nc',
'2d_surface_DOM01_ML_20210516T100000Z.nc',
'2d_surface_DOM01_ML_20210516T110000Z.nc',
'2d_surface_DOM01_ML_20210516T120000Z.nc',
'2d_surface_DOM01_ML_20210516T130000Z.nc',
'2d_surface_DOM01_ML_20210516T140000Z.nc',
'2d_surface_DOM01_ML_20210516T150000Z.nc',
'2d_surface_DOM01_ML_20210516T160000Z.nc',
'2d_surface_DOM01_ML_20210516T170000Z.nc',
'2d_surface_DOM01_ML_20210516T180000Z.nc',
'2d_surface_DOM01_ML_20210516T190000Z.nc',
'2d_surface_DOM01_ML_20210516T200000Z.nc',
'2d_surface_DOM01_ML_20210516T210000Z.nc',
'2d_surface_DOM01_ML_20210516T220000Z.nc',
'2d_surface_DOM01_ML_20210516T230000Z.nc',
'2d_surface_DOM01_ML_20210517T000000Z.nc',
'3d_full_aux_DOM01_ML_20210516T000000Z.nc',
'3d_full_aux_DOM01_ML_20210516T010000Z.nc',
'3d_full_aux_DOM01_ML_20210516T020000Z.nc',
'3d_full_aux_DOM01_ML_20210516T030000Z.nc',
'3d_full_aux_DOM01_ML_20210516T040000Z.nc',
'3d_full_aux_DOM01_ML_20210516T050000Z.nc',
'3d_full_aux_DOM01_ML_20210516T060000Z.nc',
'3d_full_aux_DOM01_ML_20210516T070000Z.nc',
'3d_full_aux_DOM01_ML_20210516T080000Z.nc',
'3d_full_aux_DOM01_ML_20210516T090000Z.nc',
'3d_full_aux_DOM01_ML_20210516T100000Z.nc',
'3d_full_aux_DOM01_ML_20210516T110000Z.nc',
'3d_full_aux_DOM01_ML_20210516T120000Z.nc',
'3d_full_aux_DOM01_ML_20210516T130000Z.nc',
'3d_full_aux_DOM01_ML_20210516T140000Z.nc',
'3d_full_aux_DOM01_ML_20210516T150000Z.nc',
'3d_full_aux_DOM01_ML_20210516T160000Z.nc',
'3d_full_aux_DOM01_ML_20210516T170000Z.nc',
'3d_full_aux_DOM01_ML_20210516T180000Z.nc',
'3d_full_aux_DOM01_ML_20210516T190000Z.nc',
'3d_full_aux_DOM01_ML_20210516T200000Z.nc',
'3d_full_aux_DOM01_ML_20210516T210000Z.nc',
'3d_full_aux_DOM01_ML_20210516T220000Z.nc',
'3d_full_aux_DOM01_ML_20210516T230000Z.nc',
'3d_full_aux_DOM01_ML_20210517T000000Z.nc',
'3d_full_base_DOM01_ML_20210516T000000Z.nc',
'3d_full_base_DOM01_ML_20210516T010000Z.nc',
'3d_full_base_DOM01_ML_20210516T020000Z.nc',
'3d_full_base_DOM01_ML_20210516T030000Z.nc',
'3d_full_base_DOM01_ML_20210516T040000Z.nc',
'3d_full_base_DOM01_ML_20210516T050000Z.nc',
'3d_full_base_DOM01_ML_20210516T060000Z.nc',
'3d_full_base_DOM01_ML_20210516T070000Z.nc',
'3d_full_base_DOM01_ML_20210516T080000Z.nc',
'3d_full_base_DOM01_ML_20210516T090000Z.nc',
'3d_full_base_DOM01_ML_20210516T100000Z.nc',
'3d_full_base_DOM01_ML_20210516T110000Z.nc',
'3d_full_base_DOM01_ML_20210516T120000Z.nc',
'3d_full_base_DOM01_ML_20210516T130000Z.nc',
'3d_full_base_DOM01_ML_20210516T140000Z.nc',
'3d_full_base_DOM01_ML_20210516T150000Z.nc',
'3d_full_base_DOM01_ML_20210516T160000Z.nc',
'3d_full_base_DOM01_ML_20210516T170000Z.nc',
'3d_full_base_DOM01_ML_20210516T180000Z.nc',
'3d_full_base_DOM01_ML_20210516T190000Z.nc',
'3d_full_base_DOM01_ML_20210516T200000Z.nc',
'3d_full_base_DOM01_ML_20210516T210000Z.nc',
'3d_full_base_DOM01_ML_20210516T220000Z.nc',
'3d_full_base_DOM01_ML_20210516T230000Z.nc',
'3d_full_base_DOM01_ML_20210517T000000Z.nc',
'3d_full_geo_DOM01_ML_20210516T000000Z.nc',
'3d_full_geo_DOM01_ML_20210517T000000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T000000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T010000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T020000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T030000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T040000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T050000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T060000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T070000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T080000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T090000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T100000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T110000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T120000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T130000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T140000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T150000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T160000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T170000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T180000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T190000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T200000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T210000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T220000Z.nc',
'3d_full_qmix_DOM01_ML_20210516T230000Z.nc',
'3d_full_qmix_DOM01_ML_20210517T000000Z.nc',
'3d_full_tend_DOM01_ML_20210516T000000Z.nc',
'3d_full_tend_DOM01_ML_20210516T010000Z.nc',
'3d_full_tend_DOM01_ML_20210516T020000Z.nc',
'3d_full_tend_DOM01_ML_20210516T030000Z.nc',
'3d_full_tend_DOM01_ML_20210516T040000Z.nc',
'3d_full_tend_DOM01_ML_20210516T050000Z.nc',
'3d_full_tend_DOM01_ML_20210516T060000Z.nc',
'3d_full_tend_DOM01_ML_20210516T070000Z.nc',
'3d_full_tend_DOM01_ML_20210516T080000Z.nc',
'3d_full_tend_DOM01_ML_20210516T090000Z.nc',
'3d_full_tend_DOM01_ML_20210516T100000Z.nc',
'3d_full_tend_DOM01_ML_20210516T110000Z.nc',
'3d_full_tend_DOM01_ML_20210516T120000Z.nc',
'3d_full_tend_DOM01_ML_20210516T130000Z.nc',
'3d_full_tend_DOM01_ML_20210516T140000Z.nc',
'3d_full_tend_DOM01_ML_20210516T150000Z.nc',
'3d_full_tend_DOM01_ML_20210516T160000Z.nc',
'3d_full_tend_DOM01_ML_20210516T170000Z.nc',
'3d_full_tend_DOM01_ML_20210516T180000Z.nc',
'3d_full_tend_DOM01_ML_20210516T190000Z.nc',
'3d_full_tend_DOM01_ML_20210516T200000Z.nc',
'3d_full_tend_DOM01_ML_20210516T210000Z.nc',
'3d_full_tend_DOM01_ML_20210516T220000Z.nc',
'3d_full_tend_DOM01_ML_20210516T230000Z.nc',
'3d_full_tend_DOM01_ML_20210517T000000Z.nc',
'ECHAM6_CldOptProps.nc',
'NAMELIST_ICON_output_atm',
'NAMELIST_icon_lam_1dom_lpz-base',
'check_global_quantities.dat',
'dmin_wetgrowth_lookup.nc',
'dwdFG_R2B09_DOM01.nc',
'extpar_lpz_r2_dom01_DOM01.nc',
'extpar_lpz_r2_dom02_DOM02.nc',
'finish.status',
'icon_master.namelist',
'ifs2icon_R2B09_DOM01.nc',
'lpz_r2_dom01_DOM01.nc',
'lsdata.nc',
'nml.atmo.log',
'output_schedule.ps',
'output_schedule.txt',
'rrtmg_lw.nc',
'rrtmg_sw.nc',
'sound_rce',
'total_integrals.dat',
'tracer_total_integrals.dat']
Ui, many files! Again, files with .nc
are our netcdf data. The suffix _mean
indicates files for domain-mean quantities that have been calculated with cdo
.
Let’s have a look at the different categories:
[6]:
sorted( glob.glob( f'{exp_path}/*DOM01_ML_20210516T120000Z.nc') )
[6]:
['/work/bb1224/2023_MS-COURSE/data/icon-lem/experiments/icon_lam_1dom_lpz-base/2d_cloud_DOM01_ML_20210516T120000Z.nc',
'/work/bb1224/2023_MS-COURSE/data/icon-lem/experiments/icon_lam_1dom_lpz-base/2d_rad_DOM01_ML_20210516T120000Z.nc',
'/work/bb1224/2023_MS-COURSE/data/icon-lem/experiments/icon_lam_1dom_lpz-base/2d_surface_DOM01_ML_20210516T120000Z.nc',
'/work/bb1224/2023_MS-COURSE/data/icon-lem/experiments/icon_lam_1dom_lpz-base/3d_full_aux_DOM01_ML_20210516T120000Z.nc',
'/work/bb1224/2023_MS-COURSE/data/icon-lem/experiments/icon_lam_1dom_lpz-base/3d_full_base_DOM01_ML_20210516T120000Z.nc',
'/work/bb1224/2023_MS-COURSE/data/icon-lem/experiments/icon_lam_1dom_lpz-base/3d_full_qmix_DOM01_ML_20210516T120000Z.nc',
'/work/bb1224/2023_MS-COURSE/data/icon-lem/experiments/icon_lam_1dom_lpz-base/3d_full_tend_DOM01_ML_20210516T120000Z.nc']
2d_rad
: variables related to radiation2d_cloud
: variable related to clouds & precipitation2d_surface
: variable related to surface properties or surface budgets3d_full_base
: main prognostic variables3d_full_qmix
: hydrometeor mass mixing ratios3d_full_qnum
: hydrometeor number mixing ratios3d_full_tend
: tendencies of some prognostic variables (incl. physic parameterizations)3d_full_aux
: some additional 3d fields
Please, open a terminal and look at the file content. (Using either cdo sinfov <filename>
or ncdump -h <filename>
).
Base Files
[7]:
dset = xr.open_dataset( f'{exp_path}/3d_full_base_DOM01_ML_20210516T120000Z.nc', chunks={} )
This is the content of the dataset.
[8]:
dset.data_vars
[8]:
Data variables:
height_bnds (height, bnds) float64 dask.array<chunksize=(50, 2), meta=np.ndarray>
u (time, height, ncells) float32 dask.array<chunksize=(1, 50, 10212), meta=np.ndarray>
v (time, height, ncells) float32 dask.array<chunksize=(1, 50, 10212), meta=np.ndarray>
w (time, height_2, ncells) float32 dask.array<chunksize=(1, 51, 10212), meta=np.ndarray>
clc (time, height, ncells) float32 dask.array<chunksize=(1, 50, 10212), meta=np.ndarray>
qv (time, height, ncells) float32 dask.array<chunksize=(1, 50, 10212), meta=np.ndarray>
temp (time, height, ncells) float32 dask.array<chunksize=(1, 50, 10212), meta=np.ndarray>
pres (time, height, ncells) float32 dask.array<chunksize=(1, 50, 10212), meta=np.ndarray>
theta_v (time, height, ncells) float32 dask.array<chunksize=(1, 50, 10212), meta=np.ndarray>
It is easy to guess for which each variable name stands. If you don’t like to guess, you could further look at dataset attributes:
[9]:
dset['u']
[9]:
<xarray.DataArray 'u' (time: 1, height: 50, ncells: 10212)> dask.array<open_dataset-64fac6d26e8a9b24d92022a341bd8692u, shape=(1, 50, 10212), dtype=float32, chunksize=(1, 50, 10212), chunktype=numpy.ndarray> Coordinates: * time (time) float64 2.021e+07 * height (height) float64 1.0 2.0 3.0 4.0 5.0 ... 46.0 47.0 48.0 49.0 50.0 Dimensions without coordinates: ncells Attributes: standard_name: eastward_wind long_name: Zonal wind units: m s-1 param: 2.2.0 CDI_grid_type: unstructured number_of_grid_in_reference: 1
Calculate Average Profiles
[10]:
dset_mean = dset.mean( 'ncells' )
There is an additional time dimension of length = 1
. This is not needed and we get rid of it if the queeze
method:
[11]:
dset_mean = dset_mean.squeeze()
Plotting the Profiles
Model Level as Vertical Coordinate
The coordinate height
denotes the ICON model level:
[12]:
dset['height']
[12]:
<xarray.DataArray 'height' (height: 50)> array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24., 25., 26., 27., 28., 29., 30., 31., 32., 33., 34., 35., 36., 37., 38., 39., 40., 41., 42., 43., 44., 45., 46., 47., 48., 49., 50.]) Coordinates: * height (height) float64 1.0 2.0 3.0 4.0 5.0 ... 46.0 47.0 48.0 49.0 50.0 Attributes: standard_name: height long_name: generalized_height axis: Z bounds: height_bnds
These are terrain-following coordinates and additional data are needed to relate model level to a geometric height above ground or perhaps to atmospheric pressure.
Let’ shave a look at the pressure profile first to understand how model level are sorted.
[13]:
plt.figure( figsize = (4,6))
dset_mean['pres'].plot( y = 'height', lw = 3)
plt.title( 'Pressure / Pa', fontweight = 'bold')
sns.despine()
OK; pressure is lowest at model level equal to one, i.e. model levels increase from top to bottom!
Average Pressure on Vertical Axis
Atmospheric scientist like the pressure coordinate. Here, we do the trick that we still plot model level, but show the typical average pressure which each level corresponds to. This practice is very often sufficient.
We prepare the average pressure:
[14]:
p_average = dset_mean['pres'] / 1e2 # conversion into hPa
p_average.attrs['units'] = 'hPa'
and then assign the pressure to the height
coordinate:
[15]:
dset_mean = dset_mean.assign_coords( {'height': p_average})
dset_mean = dset_mean.rename( {'height': 'pressure'})
dset_mean = dset_mean.sel( pressure = slice(200,1000))
finally, we plot the profiles of the atmopsheric variables as multi-panel plot:
[16]:
figure, axs = plt.subplots( ncols = 3, nrows = 2, figsize = (14,16),)
axs = axs.flatten()
plt.subplots_adjust( hspace = 0.5, wspace = 0.5)
for i, varname in enumerate( ['u', 'v', 'qv', 'clc', 'temp', 'theta_v'] ):
plt.sca( axs[i] )
v = dset_mean[varname]
v.plot( y = 'pressure', lw = 3 )
plt.title('%s / %s' % (v.long_name, v.units), pad = 20, fontweight = 'bold')
plt.ylim(1000., 200.)
sns.despine()
Tasks
Use this notebook to explore the other 3d_*nc
files:
Do you understand the meaning of the different variables?
Specifically, how are liquid and frozen hydrometeors distributed?