|
1 | 1 | #!/usr/bin/env python3
|
2 |
| -#------------------------------------------------------------------------------# |
3 | 2 | # Interpolate to isentropic levels
|
4 |
| -# NOTE: File cannot have any print statements! Need to capture output of |
5 |
| -# time command |
6 |
| -#------------------------------------------------------------------------------# |
7 |
| -# Imports |
8 |
| -# import cartopy.crs as ccrs |
9 |
| -# import cartopy.feature as cfeature |
10 |
| -# import matplotlib.pyplot as plt |
| 3 | +# NOTE: File cannot have any print statements! Need to capture output of time command. |
11 | 4 | import os
|
12 | 5 | import sys
|
| 6 | + |
13 | 7 | import numpy as np
|
14 |
| -import xarray as xr |
| 8 | + |
15 | 9 | import metpy.calc as mcalc
|
| 10 | +import xarray as xr |
16 | 11 | from metpy.units import units
|
17 | 12 |
|
18 | 13 | # File, with optional decoding
|
19 |
| -if len(sys.argv)!=3: |
| 14 | +if len(sys.argv) != 3: |
20 | 15 | raise ValueError('Require two input args.')
|
21 | 16 | filename = sys.argv[1]
|
22 | 17 | dir = filename.split('/')[0]
|
23 |
| -nt = int(sys.argv[2]) # number of time chunks; 0 to disable chunking |
24 |
| -if nt: # 1 chunk per level |
25 |
| - N = 100000 # max chunk size for lon/lat dimensions; want to chunk each 2D slice separately |
26 |
| - # N = 1000 # this made no difference |
27 |
| - chunks = {'time':nt, 'plev':N, 'lat':N, 'lon':N} # one chunk per horizontal slice, works pretty well |
| 18 | +nt = int(sys.argv[2]) # number of time chunks; 0 to disable chunking |
| 19 | +if nt: # 1 chunk per level |
| 20 | + N = 100000 # max chunk size for space (want to chunk each timestep separately) |
| 21 | + chunks = {'time': nt, 'plev': N, 'lat': N, 'lon': N} |
28 | 22 | data = xr.open_dataset(filename, chunks=chunks, decode_times=False)
|
29 | 23 | else:
|
30 | 24 | data = xr.open_dataset(filename, decode_times=False)
|
31 | 25 |
|
32 | 26 | # Interpoland
|
33 |
| -eps = 1 |
34 |
| -# thlev = np.array([*range(260, 360, 10), *range(360, 400, 20), *range(400, 800, 50), *range(800, 1600, 200)]) |
35 | 27 | # thlev = np.array([*range(260, 360, 10), *range(360, 400, 20), *range(400, 800, 50)])
|
36 | 28 | # thlev = np.array([*range(300, 360, 10), *range(360, 400, 20)])
|
37 |
| -# thlev = np.arange(240,400,20) # must be ascending! |
38 |
| -thlev = np.array([265, 275, 285, 300, 315, 330, 350, 370, 395, 430, 475, 530, 600, 700, 850]) |
| 29 | +# thlev = np.arange(240,400,20) # must be ascending! |
| 30 | +thlev = [265, 275, 285, 300, 315, 330, 350, 370, 395, 430, 475, 530, 600, 700, 850] |
| 31 | +thlev = np.array(thlev) |
| 32 | + |
39 | 33 | # Coordinates
|
40 | 34 | time = data['time']
|
41 | 35 | plev = data['plev']
|
42 | 36 | lat = data['lat']
|
43 | 37 | lon = data['lon']
|
| 38 | + |
44 | 39 | # Variables
|
45 |
| -# u = data['u'][0] |
46 | 40 | u = data['u']
|
47 | 41 | v = data['v']
|
48 | 42 | t = data['t']
|
49 |
| -t = t*units.kelvin |
50 |
| -thlev = thlev.astype('float32')*units.kelvin # assign units to input arg |
51 |
| -plev = plev.values.astype('float32')*units.hectopascals |
| 43 | +t = t * units.kelvin |
| 44 | +thlev = thlev.astype('float32') * units.kelvin |
| 45 | +plev = plev.values.astype('float32') * units.hectopascals |
52 | 46 |
|
53 | 47 | # Interpolation
|
54 | 48 | # The returned 'p' are pressure along each isentrope
|
55 |
| -# NOTE: If temps out of bounds get error: |
56 |
| -# raise ValueError('Input theta level out of data bounds') |
57 |
| -# This should just be a warning, or optionally disabled! |
58 |
| -p, t_th, u_th, v_th = mcalc.isentropic_interpolation(thlev, plev, t.values*units.kelvin, u.values, v.values, axis=1, tmpk_out=True) # output isentropes in Kelvin |
| 49 | +p, t_th, u_th, v_th = mcalc.isentropic_interpolation( |
| 50 | + thlev, plev, t.values * units.kelvin, u.values, v.values, axis=1, tmpk_out=True |
| 51 | +) |
59 | 52 | dims = ('time', 'thlev', 'lat', 'lon')
|
60 |
| -p = xr.Variable(dims, p.astype('float32'), {'long_name':'pressure', 'units':'hPa'}) |
| 53 | +p = xr.Variable(dims, p.astype('float32'), {'long_name': 'pressure', 'units': 'hPa'}) |
61 | 54 | t_th = xr.Variable(dims, t_th.astype('float32'), t.attrs)
|
62 | 55 | u_th = xr.Variable(dims, u_th.astype('float32'), u.attrs)
|
63 | 56 | v_th = xr.Variable(dims, v_th.astype('float32'), v.attrs)
|
| 57 | + |
64 | 58 | # Make dataset, add variables and coordinates
|
65 | 59 | # NOTE: Put coordinates in first, so they come first in ncdump
|
66 |
| -thlev = xr.Variable('thlev', thlev, {'long_name':'potential_temperature', 'units':'K'}) |
67 |
| -out = xr.Dataset({}, coords={'time':time, 'thlev':thlev, 'lat':lat, 'lon':lon}) |
68 |
| -for name,data in zip(('p','t','u','v'),(p,t_th,u_th,v_th)): |
| 60 | +thlev = xr.Variable( |
| 61 | + 'thlev', thlev, {'long_name': 'potential_temperature', 'units': 'K'} |
| 62 | +) |
| 63 | +out = xr.Dataset({}, coords={'time': time, 'thlev': thlev, 'lat': lat, 'lon': lon}) |
| 64 | +for name, data in zip(('p', 't', 'u', 'v'), (p, t_th, u_th, v_th)): |
69 | 65 | out[name] = data
|
70 |
| -# out = xr.Dataset({'p':p, 't':t_th, 'u':u_th, 'v':v_th}, |
71 |
| -# {'thlev':thlev, 'lon':lon, 'lat':lat}) |
72 | 66 |
|
73 | 67 | # Save file
|
74 | 68 | outname = f'{dir}/isentropes_py{nt}.nc'
|
75 | 69 | if os.path.exists(outname):
|
76 | 70 | os.remove(outname)
|
77 |
| -out.to_netcdf(outname, mode='w') # specify whether we did chunking |
78 |
| - |
| 71 | +out.to_netcdf(outname, mode='w') # specify whether we did chunking |
0 commit comments