Data Extraction

This notebook demonstrates gcmprocpy’s data extraction functions (arr_*) for slicing model output along various dimensions, as well as height interpolation utilities.

Note: This notebook requires TIE-GCM or WACCM-X model output files.

[ ]:
import warnings
warnings.filterwarnings('ignore')

import numpy as np
import gcmprocpy as gy

directory = '/glade/work/nikhilr/tiegcm3.0/benchmarks/2.5/seasons/decsol_smin/hist'
datasets = gy.load_datasets(directory, dataset_filter='sech')
times = gy.time_list(datasets)
t_val = times[0]
print(f'Using time: {t_val}')
Using time: 2002-12-21T01:00:00.000000000

arr_lat_lon — Latitude x Longitude Slice

Extract a 2D lat/lon array at a given time and pressure level. Use plot_mode=True to get a PlotData object with metadata.

[17]:
result = gy.arr_lat_lon(datasets, 'TN', t_val, selected_lev_ilev=5.0, plot_mode=True)
print(f'shape:  {result.values.shape}')
print(f'unit:   {result.variable_unit}')
print(f'level:  {result.selected_lev}')
print(f'lats:   {result.lats[0]:.1f} to {result.lats[-1]:.1f}')
print(f'lons:   {result.lons[0]:.1f} to {result.lons[-1]:.1f}')
shape:  (72, 144)
unit:   K
level:  5.0
lats:   -88.8 to 88.8
lons:   -180.0 to 177.5

arr_var — Full Variable at a Time

Extract the full 3D field (lev x lat x lon) at a single time step.

[18]:
result = gy.arr_var(datasets, 'TN', t_val, plot_mode=True)
print(f'shape: {result.values.shape}  (nlev x nlat x nlon)')
print(f'levs:  {result.levs.shape}')
shape: (57, 72, 144)  (nlev x nlat x nlon)
levs:  (57,)

arr_lev_var — Vertical Profile

Extract a 1D vertical profile at a specific latitude and longitude.

[19]:
result = gy.arr_lev_var(datasets, 'TN', t_val, selected_lat=0.0, selected_lon=0.0, plot_mode=True)
print(f'shape: {result.values.shape}')
print(f'levs:  {result.levs}')
shape: (57,)
levs:  [-6.875 -6.625 -6.375 -6.125 -5.875 -5.625 -5.375 -5.125 -4.875 -4.625
 -4.375 -4.125 -3.875 -3.625 -3.375 -3.125 -2.875 -2.625 -2.375 -2.125
 -1.875 -1.625 -1.375 -1.125 -0.875 -0.625 -0.375 -0.125  0.125  0.375
  0.625  0.875  1.125  1.375  1.625  1.875  2.125  2.375  2.625  2.875
  3.125  3.375  3.625  3.875  4.125  4.375  4.625  4.875  5.125  5.375
  5.625  5.875  6.125  6.375  6.625  6.875  7.125]

arr_lev_lon — Level x Longitude Cross-Section

Extract a 2D lev/lon cross-section at a given latitude.

[20]:
result = gy.arr_lev_lon(datasets, 'TN', t_val, selected_lat=0.0, plot_mode=True)
print(f'shape: {result.values.shape}  (nlev x nlon)')
print(f'levs:  {result.levs.shape}')
print(f'lons:  {result.lons.shape}')
shape: (57, 144)  (nlev x nlon)
levs:  (57,)
lons:  (144,)

arr_lev_lat — Level x Latitude Cross-Section

Extract a 2D lev/lat cross-section at a given longitude.

[21]:
result = gy.arr_lev_lat(datasets, 'TN', t_val, selected_lon=0.0, plot_mode=True)
print(f'shape: {result.values.shape}  (nlev x nlat)')
print(f'levs:  {result.levs.shape}')
print(f'lats:  {result.lats.shape}')
shape: (57, 72)  (nlev x nlat)
levs:  (57,)
lats:  (72,)

arr_lev_time — Level x Time Cross-Section

Extract a 2D lev/time cross-section at a specific latitude and longitude.

[22]:
result = gy.arr_lev_time(datasets, 'TN', selected_lat=0.0, selected_lon=0.0, plot_mode=True)
print(f'shape:  {result.values.shape}  (nlev x ntime)')
print(f'levs:   {result.levs.shape}')
print(f'mtimes: {len(result.mtime_values)}')
shape:  (57, 120)  (nlev x ntime)
levs:   (57,)
mtimes: 120

arr_lat_time — Latitude x Time Cross-Section

Extract a 2D lat/time cross-section at a given longitude and level.

[23]:
result = gy.arr_lat_time(datasets, 'TN', selected_lon=0.0, selected_lev_ilev=5.0, plot_mode=True)
print(f'shape:  {result.values.shape}  (nlat x ntime)')
print(f'lats:   {result.lats.shape}')
print(f'mtimes: {len(result.mtime_values)}')
shape:  (72, 120)  (nlat x ntime)
lats:   (72,)
mtimes: 120

arr_lon_time — Longitude x Time Cross-Section

[24]:
result = gy.arr_lon_time(datasets, 'TN', selected_lat=0.0, selected_lev_ilev=5.0, plot_mode=True)
print(f'shape:  {result.values.shape}  (nlon x ntime)')
print(f'lons:   {result.lons.shape}')
print(f'mtimes: {len(result.mtime_values)}')
shape:  (144, 120)  (nlon x ntime)
lons:   (144,)
mtimes: 120

arr_var_time — Variable vs Time Series

[25]:
result = gy.arr_var_time(datasets, 'TN', selected_lat=0.0, selected_lon=0.0, selected_lev_ilev=5.0, plot_mode=True)
print(f'shape:  {result.values.shape}  (ntime,)')
print(f'mtimes: {len(result.mtime_values)}')
shape:  (120,)  (ntime,)
mtimes: 120

batch_arr_lat_lon — Multiple Variables at Once

Extract several variables in a single pass over the datasets.

[26]:
results = gy.batch_arr_lat_lon(datasets, ['TN', 'O1', 'NO'], t_val, selected_lev_ilev=5.0, plot_mode=True)
for name, r in results.items():
    print(f'{name}: shape={r.values.shape}, unit={r.variable_unit}')
TN: shape=(72, 144), unit=K
O1: shape=(72, 144), unit=mmr
NO: shape=(72, 144), unit=mmr

arr_sat_track — Satellite Track Interpolation

Interpolate model data along a satellite trajectory using trilinear interpolation.

[27]:
# Simulate a LEO ascending pass
sat_time = np.array([times[0] + np.timedelta64(i * 6, 'm') for i in range(20)])
sat_lat = np.linspace(-60, 60, 20)
sat_lon = np.linspace(-120, 120, 20)

# 1D extraction at a fixed level
values = gy.arr_sat_track(datasets, 'NO', sat_time, sat_lat, sat_lon, selected_lev_ilev=5.0)
print(f'At fixed level: shape={values.shape}')

# 2D extraction across all levels
values_2d = gy.arr_sat_track(datasets, 'NO', sat_time, sat_lat, sat_lon)
print(f'All levels:     shape={values_2d.shape}')
At fixed level: shape=(20,)
All levels:     shape=(57, 20)

Height Interpolation

height_to_pres_level

Convert a target height in km to the nearest pressure level.

[28]:
pres_level = gy.height_to_pres_level(datasets, t_val, 300.0)
print(f'300 km -> pressure level {pres_level}')

# At a specific location
pres_level_ll = gy.height_to_pres_level(datasets, t_val, 300.0, latitude=0.0, longitude=0.0)
print(f'300 km at equator, 0E -> pressure level {pres_level_ll}')

# Different heights map to different levels
for h in [100.0, 200.0, 300.0, 400.0, 500.0]:
    pl = gy.height_to_pres_level(datasets, t_val, h)
    print(f'  {h:.0f} km -> {pl}')
300 km -> pressure level 3.0
300 km at equator, 0E -> pressure level 3.25
  100 km -> -6.25
  200 km -> 0.0
  300 km -> 3.0
  400 km -> 5.25
  500 km -> 7.0

interpolate_to_height

Interpolate a 2D field from pressure levels to constant height surfaces.

[29]:
# Extract a lev x lat cross-section on pressure levels
result_lev_lat = gy.arr_lev_lat(datasets, 'TN', t_val, selected_lon=0.0, plot_mode=True)

# Interpolate to 30 evenly spaced height levels
interp_vals, target_heights = gy.interpolate_to_height(
    datasets, result_lev_lat.values, result_lev_lat.levs, t_val, n_heights=30)
print(f'Input shape:  {result_lev_lat.values.shape} (nlev x nlat)')
print(f'Output shape: {interp_vals.shape} (n_heights x nlat)')
print(f'Height range: {target_heights[0]:.1f} to {target_heights[-1]:.1f} km')

# Interpolate to specific heights
custom_hts = np.array([100.0, 200.0, 300.0, 400.0, 500.0])
interp_custom, _ = gy.interpolate_to_height(
    datasets, result_lev_lat.values, result_lev_lat.levs, t_val, target_heights=custom_hts)
print(f'\nCustom heights shape: {interp_custom.shape}')
Input shape:  (57, 72) (nlev x nlat)
Output shape: (30, 72) (n_heights x nlat)
Height range: 96.4 to 482.7 km

Custom heights shape: (5, 72)

Cleanup

[30]:
gy.close_datasets(datasets)
print('Datasets closed.')
Datasets closed.