Example scripts

Often it is quickest to learn from examples. Here are some scripts illustrating how to solve some common tasks using dynlib. They also provide a good basis for your own scripts.

Read data, apply diagnostic, plot and save results

 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
#!/usr/bin/env python
# -*- encoding: utf-8

import numpy as np

from dynlib.metio.erainterim import conf, dt, get_instantaneous, metsave
from dynlib.plotsettings import pconf, pconfl

import dynlib.diag
import dynlib.proj as proj
import dynlib.figures as fig

timeinterval = [dt(2011,12,25,0), dt(2011,12,26,12)]
plev = '850'

# Get wind velocity components on 850 hPa for Ekstremværet Dagmar
dat, grid = get_instantaneous([(plev, 'u'), (plev,'v'), ], timeinterval)

# Calculate total deformation
defabs = dynlib.diag.def_total(dat[plev,'u'][:,0,:,:], dat[plev,'v'][:,0,:,:], grid.dx, grid.dy)

# Save results as netCDF file
tosave = {
    'defabs': defabs[:,np.newaxis,:,:],      # Pressure-level data is expected to be 4-dimensional
}
metsave(tosave, grid, f'ei.ans.Dagmar.{plev}.defabs')

# Plot results
for tidx in range(len(grid.t)):
    fig.map(defabs[tidx,::], grid, q='defabs', plev=plev, 
            name=grid.t_parsed[tidx], m=proj.N_Atlantic, show=False,
            save=f'Dagmar_defabs_{grid.t_parsed[tidx].strftime("%Y%m%d_%H")}.pdf')
    fig.plt.close()

# the end

The first two lines are a standard header for a python file. Line 1 declares the file to be a python script, allowing it to be executed by ./script_name.py. Line 2 gives the file encoding, which is required of you use non-acsii characters in your script. Both lines are optional, but recommended.

Lines 4 through 11 import some standard functionality from dynlib. Of these line 6 is of special importance, as this is line defines that the script uses ERA-Interim reanalysis as its data base.

The time interval on line 13 is a list of datetime objects, that define the time interval for which data is to be fetched in lines 17. Analogously the vertical level for the requested data is set on line 14. In additon to the actual data, the data fetcher function get_instantaneous() also returns meta-information about the variable, mainly the grid that the variable is defined on.

Line 20 finally calculated total deformation from the given wind velocity components. The results are then saved to a netCDF file in line 26.

For each of the time steps available, the deformation field is also plotted on a map covering the North Atlantic (line 30-32).

 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
#!/usr/bin/env python
# -*- encoding: utf-8

import numpy as np

from dynlib.metio.erainterim import conf, dt, get_instantaneous, metsave
from dynlib.plotsettings import pconf, pconfl

import dynlib.diag

year = 2011
timeinterval = [dt(year,1,1,0), dt(year+1,1,1,0)]     # end of the time interval is excluced
plev = '850'

# Get wind velocity components on 850 hPa for the entire year 2011
dat, grid = get_instantaneous([(plev, 'u'), (plev,'v'), ], timeinterval)

# Calculate total deformation
defabs = dynlib.diag.def_total(dat[plev,'u'][:,0,:,:], dat[plev,'v'][:,0,:,:], grid.dx, grid.dy)

# Save results as netCDF file
tosave = {
    'defabs': defabs[:,np.newaxis,:,:],      # Pressure-level data is expected to be 4-dimensional
}
metsave(tosave, grid, f'ei.ans.{year}.{plev}.defabs')

# the end

The script changes hardly at all if you want to calculate and save deformation for longer period. Typically, for ERA-Interim, we would use yearly chunks as shown in the script. Differences to the first example are highlighted in yellow.

Define and calculate composites

 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
#!/usr/bin/env python
# -*- encoding: utf-8

from dynlib.metio.erainterim import conf, dt, get_composite, get_static, metopen, metsave_composite
from dynlib.metio.composite import decide_by_date, decide_by_timeseries, matrix



# Which variable(s) to composite, given by list of 2-tuples (plev, q)
qs = [('500', 'z'), ]

# Time interval to consider for the composites, here 2001-2010
timeinterval = [dt(2001,1,1,0), dt(2011,1,1,0)]


# Define the composite based on two different kinds of tests:
# 1. First, get tests for the different seasons
djf = decide_by_date('DJF', lambda date: date.month in [12,1,2])
jja = decide_by_date('JJA', lambda date: date.month in [6,7,8]) 

# 2. Then tests based on the monthly values of the NAO
ts = metopen('indexes/ts_NAO', no_static=True)
naop = decide_by_timeseries('NAO+', ts, lambda idx: idx >= 1.0)
naom = decide_by_timeseries('NAO-', ts, lambda idx: idx <= -1.0)

# 3. Combine the tests to make composites for all combinations between
#    NAO+/- and summer/winter
composites = matrix([djf, jja,], [naom, naop])


# Actually construct the composites
dat = get_composite(qs, timeinterval, composites)

# Save the composites as netCDF files; requires injection of missing vertical level information
grid = get_static()
metsave_composite(dat, composites, grid, 'ei.ans.NAO_composites')



# C'est le fin

Requesting composite averages works very similarly to requesting instantaneous data. The only additional argument in get_aggregate() over get_instantaneous() is the list of composite conditions to be applied.

These conditions can be constructed easily from the primitives defined in dynlib.metio.composite. In this example, lines 18-19 defines two conditions based on the date only to define seasonal averages through a composite. In the following, line 22 loads a monthly NAO index time series, and lines 23-24 define composites based on the NAO index. Finally, line 28 combines the seasonal and the NAO criteria by creating all combinations, here composites of NAO+ and NAO- for both summer and winter.

The function get_instantaneous() does (currently) not return the grid information itself, so we need to manually request this metadata through get_static() (line 35) before we can save the result.

 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
#!/usr/bin/env python
# -*- encoding: utf-8

from dynlib.metio.erainterim import conf, dt, get_composite, get_static, metsave_composite
from dynlib.metio.composite import decide_by_date, decide_by_data



# Which variable(s) to composite, given by list of 2-tuples (plev, q)
qs = [('500', 'z'), ]

# Time interval to consider for the composites, here 2001-2010
timeinterval = [dt(2001,1,1,0), dt(2011,1,1,0)]


# Define the composite based on two different kinds of tests:
# 1. First define summer season
jja = decide_by_date('JJA', lambda date: date.month in [6,7,8]) 

# 2. Find time steps when Bergen 2m temperatures exceed 20 degC
warm_bgo = decide_by_data('warm_BGO', 'sfc', 't2m', lambda t2m: t2m[60,370] > 293.0)

# 3. Combine the tests
composites = [warm_bgo & jja, ]


# Actually construct the composites
dat = get_composite(qs, timeinterval, composites)

# Save the composites as netCDF files; requires injection of missing vertical level information
grid = get_static()
metsave_composite(dat, composites, grid, 'ei.ans.warm_BGO_composite')



# C'est le fin

The final example adapts the previous composite definitions to an example of a data-driven composite. This example composites all time steps in which the ERA-Interim grid point closest to Bergen exceeds a 2-meter temperature of 20°C (line 21). The structure of the script is almost entirely identical to the above, only in line 24 the combination of the one seasonal criterion with the one temperature criterion is done manually instead through the matrix() function.