2 Input Data¶
The following Python scripts are provided by the author for generating a separate urban albedo stream file.
import rasterio
import xarray as xr
import numpy as np
import geopandas as gpd
from shapely.geometry import Polygon
from pyproj import CRS
from rasterio.warp import transform
from rasterio.features import geometry_mask
import netCDF4 as nc
Taking transient urban albedo as an example, the new stream file has three variables:
dyn_alb_roof_TBD,dyn_alb_roof_HD, anddyn_alb_roof_MD
2.1 For Global Simulations¶
To generate global urban albedo stream data, we take an existing stream file as a template.
ds_std_tmax = xr.open_dataset(f'{home_path}dataset/inputdata/lnd/clm2/urbandata/CTSM52_tbuildmax_OlesonFeddema_2020_0.9x1.25_simyr1849-2106_c200605.nc')
ds_template = ds_all.isel(time=slice(171, 177)) # 2020-2025
output_filename = f'dyn_alb_roof_0.9x1.25_simyr2020-2025_c240930.nc'
if os.path.exists(output_filename):
os.remove(output_filename)
time_units = "days since 0000-01-01 00:00:00"
calendar = "noleap"
time_values = nc.date2num(ds_template['time'], units=time_units, calendar=calendar)
time_bnds_units = "days since 2020-01-01 00:00:00" # time band
time_bnds_values = nc.date2num(ds_template['time_bnds'], units=time_bnds_units, calendar=calendar)
with nc.Dataset(output_filename, 'w', format='NETCDF3_CLASSIC') as output:
output.createDimension('lat', ds_template['lat'].size)
output.createDimension('lon', ds_template['lon'].size)
output.createDimension('time', None)
output.createDimension('nv', ds_template['nv'].size)
lat = output.createVariable('lat', 'f4', ('lat',))
lat.long_name = ds_template['lat'].long_name
lat.units = ds_template['lat'].units
lat[:] = ds_template['lat']
lon = output.createVariable('lon', 'f4', ('lon',))
lon.long_name = ds_template['lon'].long_name
lon.units = ds_template['lon'].units
lon[:] = ds_template['lon']
time = output.createVariable('time', 'f4', ('time',))
time.long_name = ds_template['time'].long_name
time.calendar = calendar
time.units = time_units
time[:] = time_values
time_bnds = output.createVariable('time_bnds', 'f4', ('time', 'nv'))
time_bnds.long_name = ds_template['time_bnds'].long_name
time_bnds.calendar = calendar
time_bnds.units = time_bnds_units
time_bnds[:,:] = time_bnds_values
year = output.createVariable('year', 'i4', ('time',))
year.long_name = ds_template['year'].long_name
year.units = ds_template['year'].units
year[:] = ds_template['year']
latitudes = output.createVariable('LATIXY', 'f4', ('lat','lon'))
latitudes.long_name = ds_template['LATIXY'].long_name
latitudes.units = ds_template['LATIXY'].units
latitudes[:,:] = ds_template['LATIXY']
longitudes = output.createVariable('LONGXY', 'f4', ('lat','lon'))
longitudes.long_name = ds_template['LONGXY'].long_name
longitudes.units = ds_template['LONGXY'].units
longitudes[:,:] = ds_template['LONGXY']
area = output.createVariable('area', 'f4', ('lat','lon'))
area.long_name = ds_template['area'].long_name
area.units = ds_template['area'].units
area[:,:] = ds_template['area']
landmask = output.createVariable('LANDMASK', 'i4', ('lat','lon'))
landmask.long_name = ds_template['LANDMASK'].long_name
landmask.units = ds_template['LANDMASK'].units
landmask[:,:] = ds_template['LANDMASK']
for urban_class in ['TBD', 'HD', 'MD']:
var_name = f'dyn_alb_roof_{urban_class}'
var = output.createVariable(var_name, 'f4', ('time', 'lat', 'lon'))
var.long_name = f'prescribed urban albedo for {urban_class} class'
var.units = 'unitless'
var[:, :, :] = albedo_3d_capped
albedo_3d_capped is 3D (time, lat, lon) albedo array. Users could set the albedo varying by time (e.g., year, month, day) and location (i.e., lat, lon).
2.3 For Regional Simulations¶
To generate a regional urban albedo stream, we could specify the lat and lon information from the surface data.
ds_def = xr.open_dataset('surfdata_1.2x1.2_SSP5-8.5_2035_78pfts_c250811.nc')
calendar = "noleap"
time_bnds_yearly = ds_template_tv['time_bnds'].values # shape (time, 2)
time_monthly = []
time_bnds_monthly = []
# below is a time list by month
for start, end in time_bnds_yearly:
year_start = start.year
year_end = end.year # typically start of next year
for year in range(year_start, year_end):
for month in range(1, 13):
# Append monthly time (start of month)
t_start = cftime.DatetimeNoLeap(year, month, 1)
time_monthly.append(t_start)
# Compute monthly bounds
if month == 12:
t_end = cftime.DatetimeNoLeap(year + 1, 1, 1)
else:
t_end = cftime.DatetimeNoLeap(year, month + 1, 1)
time_bnds_monthly.append([t_start, t_end])
# Convert to numpy array
time_monthly = np.array(time_monthly, dtype=object)
time_bnds_monthly = np.array(time_bnds_monthly, dtype=object)
time_units = "days since 0000-01-01 00:00:00"
calendar = "noleap"
time_values = date2num(time_monthly, units=time_units, calendar=calendar)
time_bnds_values = date2num(time_bnds_monthly, units=time_units, calendar=calendar)
if os.path.exists(tv_output_filename2):
os.remove(tv_output_filename2)
with nc.Dataset(tv_output_filename2, 'w', format='NETCDF3_CLASSIC') as output:
output.createDimension('lat', len(lat))
output.createDimension('lon', len(lon))
output.createDimension('time', None) # set time as unlimited
output.createDimension('nv', ds_template_tv['nv'].size)
lat_var = output.createVariable('lat', 'f4', ('lat',))
lat_var.long_name = ds_template_tv['lat'].long_name
lat_var.units = ds_template_tv['lat'].units
lat_var[:] = lat
lon_var = output.createVariable('lon', 'f4', ('lon',))
lon_var.long_name = ds_template_tv['lon'].long_name
lon_var.units = ds_template_tv['lon'].units
lon_var[:] = lon
time = output.createVariable('time', 'f4', ('time',)) # f8 is double
time.long_name = ds_template_tv['time'].long_name
time.calendar = calendar
time.units = time_units
time[:] = time_values
time_bnds = output.createVariable('time_bnds', 'f4', ('time', 'nv'))
time_bnds.long_name = ds_template_tv['time_bnds'].long_name
time_bnds.calendar = calendar
time_bnds.units = time_units
time_bnds[:,:] = time_bnds_values
year = output.createVariable('year', 'i4', ('time',))
year.long_name = ds_template_tv['year'].long_name
year.units = ds_template_tv['year'].units
year[:] = ds_template_tv['year']
latitudes = output.createVariable('LATIXY', 'f4', ('lat','lon'))
latitudes.long_name = ds_template_tv['LATIXY'].long_name
latitudes.units = ds_template_tv['LATIXY'].units
latitudes[:,:] = ds_def['LATIXY']
longitudes = output.createVariable('LONGXY', 'f4', ('lat','lon'))
longitudes.long_name = ds_template_tv['LONGXY'].long_name
longitudes.units = ds_template_tv['LONGXY'].units
longitudes[:,:] = ds_def['LONGXY']
area = output.createVariable('area', 'f4', ('lat','lon'))
area.long_name = ds_template_tv['area'].long_name
area.units = ds_template_tv['area'].units
#area[:,:] = ds_domain['area']
area[:,:] = 1.44 # 1.2 km
landmask = output.createVariable('LANDMASK', 'i4', ('lat','lon'))
landmask.long_name = ds_template_tv['LANDMASK'].long_name
landmask.units = ds_template_tv['LANDMASK'].units
landmask[:,:] = ds_domain['mask']
for urban_class in ['TBD', 'HD', 'MD']:
var_name = f'dyn_alb_roof_{urban_class}'
var = output.createVariable(var_name, 'f4', ('time', 'lat', 'lon'))
var.long_name = f'prescribed urban albedo for {urban_class} class'
var.units = 'unitless'
var[:, :, :] = albedo_3d_capped