def compute_region_ensembles(): print('Computing region ensembles...') global gia, mask, settings mask['area'] = gentools.grid_area(mask['lat'],mask['lon']) pool = mp.Pool(settings['nproc']) out = pool.map(compute_region_ens_indiv, range(settings['num_ens'])) return
def comp_GrIS_grd(grace_grd, mask, ens): global settings, glaciers, icesheets grd_ens = {} area = gentools.grid_area(mask['lat'],mask['lon']) rsl = np.zeros([len(settings['time']),len(mask['lat']),len(mask['lon'])],dtype=np.float32) rad = np.zeros([len(settings['time']),len(mask['lat']),len(mask['lon'])],dtype=np.float32) rsl[np.in1d(settings['time'],settings['time_grace']),:,:] = grace_grd['GrIS']['rsl'] * 1000 rad[np.in1d(settings['time'],settings['time_grace']),:,:] = grace_grd['GrIS']['rad'] * 1000 # Compute uniform grd fingerprints rsl_uniform = gentools.field_trend(settings['time_grace'],grace_grd['GrIS']['rsl']) scale_factor = ((rsl_uniform * (1 - mask['land']) * area).sum() / ((1 - mask['land']) * area).sum()) rsl_uniform = rsl_uniform / scale_factor rad_uniform = gentools.field_trend(settings['time_grace'],grace_grd['GrIS']['rad']) / scale_factor GrIS_insitu_rsl = icesheets['GrIS_ens'][ens,:][:,np.newaxis,np.newaxis] * rsl_uniform GrIS_insitu_rad = icesheets['GrIS_ens'][ens,:][:,np.newaxis,np.newaxis] * rad_uniform ovl_time = (settings['time'] == 2003) insitu_time = settings['time'] < 2003 rsl[insitu_time,:,:] = GrIS_insitu_rsl[:-1,:,:] - GrIS_insitu_rsl[-1,:,:][np.newaxis,:,:] + rsl[ovl_time,:,:][np.newaxis,:,:] rad[insitu_time,:,:] = GrIS_insitu_rad[:-1,:,:] - GrIS_insitu_rad[-1,:,:][np.newaxis,:,:] + rad[ovl_time,:,:][np.newaxis,:,:] grd_ens['rsl'] = rsl - rsl[-19:,:,:].mean(axis=0)[np.newaxis,...] grd_ens['rad'] = rad - rad[-19:,:,:].mean(axis=0)[np.newaxis,...] area_ocn = ((area * (1 - mask['land']))[np.newaxis, ...]) area_ocn_tot = area_ocn.sum() grd_ens['barystatic'] = (area_ocn*rsl).sum(axis=(1,2)) / area_ocn_tot area_ocn = ((area * np.isfinite(mask['basin']))[np.newaxis, ...]) area_ocn_tot = area_ocn.sum() grd_ens['qglb'] = (area_ocn*rsl).sum(axis=(1,2)) / area_ocn_tot return(grd_ens)
def comp_glac_grd(grace_grd, mask, ens): # Compute glacier contribution global settings, random_numbers, glacier_insitu grd_ens = {} area = gentools.grid_area(mask['lat'],mask['lon']) rsl = np.zeros([len(settings['time']),len(mask['lat']),len(mask['lon'])],dtype=np.float32) rad = np.zeros([len(settings['time']),len(mask['lat']),len(mask['lon'])],dtype=np.float32) rsl[np.in1d(settings['time'],settings['time_grace']),:,:] = grace_grd['glac']['rsl'] * 1000 rad[np.in1d(settings['time'],settings['time_grace']),:,:] = grace_grd['glac']['rad'] * 1000 glac_insitu_rsl = np.zeros([len(settings['time_insitu']),len(mask['lat']),len(mask['lon'])],dtype=np.float32) glac_insitu_rad = np.zeros([len(settings['time_insitu']),len(mask['lat']),len(mask['lon'])],dtype=np.float32) # for reg in range(17): glac_insitu_rsl+= glacier_insitu['fp_rsl'][reg,...]*glacier_insitu['ensemble'][ens,reg,:][:,np.newaxis,np.newaxis] glac_insitu_rad+= glacier_insitu['fp_rad'][reg,...]*glacier_insitu['ensemble'][ens,reg,:][:,np.newaxis,np.newaxis] ovl_time = (settings['time'] == 2003) insitu_time = settings['time'] < 2003 rsl[insitu_time,:,:] = glac_insitu_rsl[:-1,:,:] - glac_insitu_rsl[-1,:,:][np.newaxis,:,:] + rsl[ovl_time,:,:][np.newaxis,:,:] rad[insitu_time,:,:] = glac_insitu_rad[:-1,:,:] - glac_insitu_rad[-1,:,:][np.newaxis,:,:] + rad[ovl_time,:,:][np.newaxis,:,:] grd_ens['rsl'] = rsl - rsl[-19:,:,:].mean(axis=0)[np.newaxis,...] grd_ens['rad'] = rad - rad[-19:,:,:].mean(axis=0)[np.newaxis,...] area_ocn = ((area * (1 - mask['land']))[np.newaxis, ...]) area_ocn_tot = area_ocn.sum() grd_ens['barystatic'] = (area_ocn*rsl).sum(axis=(1,2)) / area_ocn_tot area_ocn = ((area * np.isfinite(mask['basin']))[np.newaxis, ...]) area_ocn_tot = area_ocn.sum() grd_ens['qglb'] = (area_ocn*rsl).sum(axis=(1,2)) / area_ocn_tot return(grd_ens)
def proc_grid_basin(pname): print(' Processing grid ' + pname + '...') global settings, mask steric = {} file_handle = Dataset(settings['fn_' + pname]) file_handle.set_auto_mask(False) time = file_handle.variables['t'][:] lon = file_handle.variables['x'][:] lat = file_handle.variables['y'][:] slm = file_handle.variables['slm'][:] time_acc = (time < settings['years_grid'][-1] + 1) & ( time >= settings['years_grid'][0]) time = time[time_acc] steric_monthly = file_handle.variables['h_totalsteric'][time_acc, :, :] halo_glb_monthly = file_handle.variables['ts_halosteric'][time_acc] file_handle.close() steric_monthly -= halo_glb_monthly[:, np.newaxis, np.newaxis] # To annual data steric['years'] = settings['years_grid'] steric_annual = np.zeros([len(steric['years']), len(lat), len(lon)]) for idx, yr in enumerate(steric['years']): acc_idx = (time >= yr) & (time < yr + 1) steric_annual[idx, :, :] = steric_monthly[acc_idx, :, :].mean(axis=0) area = gentools.grid_area(lat, lon) steric['basin'] = np.zeros(6, dtype=object) # Basin mean for basin in range(6): msk_lcl = (mask['basin'] == basin) msk_interp = np.rint( interp2d(mask['lon'], mask['lat'], msk_lcl, kind='linear', bounds_error=False, fill_value=0)(lon, lat)) * slm steric['basin'][basin] = np.nansum( (area[np.newaxis, :, :] * msk_interp[np.newaxis, :, :] * steric_annual), axis=(1, 2)) / (area * msk_interp).sum() # Global steric msk_lcl = 1.0 * (np.isfinite(mask['basin'])) msk_interp = np.rint( interp2d(mask['lon'], mask['lat'], msk_lcl, kind='linear', bounds_error=False, fill_value=0)(lon, lat)) * slm steric['global'] = np.nansum( (area[np.newaxis, :, :] * msk_interp[np.newaxis, :, :] * steric_annual), axis=(1, 2)) / (area * msk_interp).sum() return (steric)
def comp_tws_grd(grace_grd,mask, ens): global settings, tws, random_numbers grd_ens = {} area = gentools.grid_area(mask['lat'],mask['lon']) rsl = np.zeros([len(settings['time']),len(mask['lat']),len(mask['lon'])],dtype=np.float32) rad = np.zeros([len(settings['time']),len(mask['lat']),len(mask['lon'])],dtype=np.float32) rsl[np.in1d(settings['time'],settings['time_grace']),:,:] = grace_grd['tws']['rsl'] * 1000 rad[np.in1d(settings['time'],settings['time_grace']),:,:] = grace_grd['tws']['rad'] * 1000 # Compute natural, grd, and dam over Thompson mask tws_natural_rsl,tws_natural_rad = read_tws_natural(ens) tws_dams_rsl = random_numbers['tws_dam_scale'][ens] * tws['grd_dam_rsl'] tws_dams_rad = random_numbers['tws_dam_scale'][ens] * tws['grd_dam_rad'] if random_numbers['tws_wada_doll'][ens] == 0: tws_gwd_rsl = random_numbers['tws_gwd_scale'][ens] * tws['grd_gwd_wada_rsl'] tws_gwd_rad = random_numbers['tws_gwd_scale'][ens] * tws['grd_gwd_wada_rad'] else: tws_gwd_rsl = random_numbers['tws_gwd_scale'][ens] * tws['grd_gwd_doll_rsl'] tws_gwd_rad = random_numbers['tws_gwd_scale'][ens] * tws['grd_gwd_doll_rad'] # Combine three sources tws_insitu_rsl = tws_dams_rsl + tws_gwd_rsl + tws_natural_rsl tws_insitu_rad = tws_dams_rad + tws_gwd_rad + tws_natural_rad ovl_time = (settings['time'] == 2003) insitu_time = settings['time'] < 2003 rsl[insitu_time,:,:] = tws_insitu_rsl[:-1,:,:] - tws_insitu_rsl[-1,:,:][np.newaxis,:,:] + rsl[ovl_time,:,:][np.newaxis,:,:] rad[insitu_time,:,:] = tws_insitu_rad[:-1,:,:] - tws_insitu_rad[-1,:,:][np.newaxis,:,:] + rad[ovl_time,:,:][np.newaxis,:,:] grd_ens['rsl'] = rsl - rsl[-19:,:,:].mean(axis=0)[np.newaxis,...] grd_ens['rad'] = rad - rad[-19:,:,:].mean(axis=0)[np.newaxis,...] # Save barystatic terms, as well as individual terms area_ocn = ((area * (1 - mask['land']))[np.newaxis, ...]) area_ocn_tot = area_ocn.sum() grd_ens['barystatic'] = (area_ocn*rsl).sum(axis=(1,2)) / area_ocn_tot grd_ens['barystatic_dam'] = np.hstack([(area_ocn*tws_dams_rsl).sum(axis=(1,2)) / area_ocn_tot, np.zeros(15,dtype=np.float32)*np.nan]) grd_ens['barystatic_gwd'] = np.hstack([(area_ocn*tws_gwd_rsl).sum(axis=(1,2))/ area_ocn_tot, np.zeros(15,dtype=np.float32)*np.nan]) grd_ens['barystatic_natural'] = np.hstack([(area_ocn*tws_natural_rsl).sum(axis=(1,2)) / area_ocn_tot, np.zeros(15,dtype=np.float32)*np.nan]) # Save quasi-global estimate (i.e. Thompsons mask) area_ocn = ((area * np.isfinite(mask['basin']))[np.newaxis, ...]) area_ocn_tot = area_ocn.sum() grd_ens['qglb'] = (area_ocn*rsl).sum(axis=(1,2)) / area_ocn_tot grd_ens['qglb_dam'] = np.hstack([(area_ocn*tws_dams_rsl).sum(axis=(1,2)) / area_ocn_tot, np.zeros(15,dtype=np.float32)*np.nan]) grd_ens['qglb_gwd'] = np.hstack([(area_ocn*tws_gwd_rsl).sum(axis=(1,2))/ area_ocn_tot, np.zeros(15,dtype=np.float32)*np.nan]) grd_ens['qglb_natural'] = np.hstack([(area_ocn*tws_natural_rsl).sum(axis=(1,2)) / area_ocn_tot, np.zeros(15,dtype=np.float32)*np.nan]) # Same baseline grd_ens['barystatic_dam'] = grd_ens['barystatic_dam'] - grd_ens['barystatic_dam'][103] + grd_ens['barystatic'][103] grd_ens['barystatic_gwd'] = grd_ens['barystatic_gwd'] - grd_ens['barystatic_gwd'][103] + grd_ens['barystatic'][103] grd_ens['barystatic_natural'] = grd_ens['barystatic_natural'] - grd_ens['barystatic_natural'][103] + grd_ens['barystatic'][103] grd_ens['qglb_dam'] = grd_ens['qglb_dam'] - grd_ens['qglb_dam'][103] + grd_ens['qglb'][103] grd_ens['qglb_gwd'] = grd_ens['qglb_gwd'] - grd_ens['qglb_gwd'][103] + grd_ens['qglb'][103] grd_ens['qglb_natural'] = grd_ens['qglb_natural'] - grd_ens['qglb_natural'][103] + grd_ens['qglb'][103] return(grd_ens)
def read_mask(): global settings, mask mask = {} mask_raw = np.load(settings['fn_mask'], allow_pickle=True).all() mask['lon'] = mp_filled_float(mask_raw['lon']) mask['lat'] = mp_filled_float(mask_raw['lat']) mask['basin'] = mp_filled_float(mask_raw['basin']) mask['area'] = mp_filled_float(gentools.grid_area(mask['lat'], mask['lon'])) return
def prep_GWD(GRACE,settings): # ------------------------------------------------------------------ # Groundwater depletion # Use estimates from Wada et al., 2010, 2014, which cover 1900-2010 # Merge the 2 data sets # Sum depletion rate to get total depletion # Wada 2016: not all depleted water ends up in ocean. We apply a # correction factor of 0.6 to account for this effect. # ------------------------------------------------------------------ wada_2016_scale = 0.6 # Scale factor (Wada 2016) area = gentools.grid_area(GRACE['lat'], GRACE['lon']) time_tot = np.arange(1900,2004) depletion = np.zeros([len(time_tot),len(GRACE['lat']),len(GRACE['lon'])]) # Old Wada 2010 data time_past = np.arange(1900,1960) for idx,yr in enumerate(time_past): data_raw = np.loadtxt(settings['dir_gwd_20c'] + 'gwd0' + str(yr) + '.asc', skiprows=6) data_raw[data_raw == -9999] = 0 data_raw = np.flipud(data_raw) data_raw = np.hstack([data_raw[:, 360:], data_raw[:, 0:360]]) depletion[idx, :, :] = data_raw # Present (Wada 2014) file_handle = Dataset(settings['fn_gwd_wada'], 'r') file_handle.set_auto_mask(False) depletion_pd_monthly = file_handle.variables["anrg"][:] depletion_pd_monthly[depletion_pd_monthly < 0] = 0 file_handle.close() time_pd_m = gentools.monthly_time(1960, 2010) time_present = np.arange(1960, 2004) # To normal grid depletion_rate_monthly = np.fliplr(depletion_pd_monthly) depletion_rate_monthly = np.dstack([depletion_rate_monthly[:, :, 360:], depletion_rate_monthly[:, :, 0:360]]) for idx,yr in enumerate(time_present): idx_m = (time_pd_m>yr) & (time_pd_m<yr+1) depletion[idx+60, :, :] = np.sum(depletion_rate_monthly[idx_m, :, :], axis=0) depletion = depletion/ area * -1e9 depletion = np.cumsum(depletion, axis=0)* wada_2016_scale # Test global depletion_global = np.nansum(depletion * area, axis=(1, 2)) depletion_mscn = np.zeros(depletion.shape) # Into mascons for k in range(len(GRACE['mscn_coords'])): lat_acc = np.where((GRACE['lat'] >= GRACE['mscn_coords'][k, 0]) & (GRACE['lat'] < GRACE['mscn_coords'][k, 1]))[0] lon_acc = np.where((GRACE['lon'] >= GRACE['mscn_coords'][k, 2]) & (GRACE['lon'] < GRACE['mscn_coords'][k, 3]))[0] lsm_acc = GRACE['land'][lat_acc[0]:lat_acc[-1] + 1, lon_acc[0]:lon_acc[-1] + 1] dp_mean = np.mean(depletion[:,lat_acc[0]:lat_acc[-1] + 1, lon_acc[0]:lon_acc[-1] + 1]*lsm_acc[np.newaxis,:,:],axis=(1,2)) depletion_mscn[:,lat_acc[0]:lat_acc[-1] + 1, lon_acc[0]:lon_acc[-1] + 1] = dp_mean[:,np.newaxis,np.newaxis] depletion_mscn = depletion_mscn * GRACE['land'][np.newaxis,:,:] depletion_global_mscn = np.nansum(depletion_mscn * area, axis=(1, 2)) depletion_mscn = depletion_mscn * (depletion_global/depletion_global_mscn)[:,np.newaxis,np.newaxis] return(depletion_mscn)
def read_gia_ens(ens): global mask, settings gia = {} file_handle = Dataset(settings['fn_gia_rsl'], 'r') file_handle.set_auto_mask(False) gia['lat'] = file_handle.variables['y'][:] gia['lon'] = file_handle.variables['x'][:] if settings['test_run_ICE6G_D']: gia['rsl'] = file_handle.variables['RSL'][:] else: gia['rsl'] = file_handle.variables['rsl'][ens,:,:] file_handle.close() # Basin-mean estimate area = gentools.grid_area(gia['lat'],gia['lon']) gia['basin_mean'] = np.zeros(6) for basin in range(6): # Basin-mean GIA mask_lcl = (mask['basin']==basin) gia['basin_mean'][basin] = np.sum(gia['rsl']*mask_lcl*area)/np.sum(mask_lcl*area) return(gia)
def compute_global_ensembles(basin_ensembles,settings): # Compute weights of each basin # Take into account that not all basins are complete basin_mask = read_basin_mask(settings) area = gentools.grid_area(basin_mask['lat'],basin_mask['lon']) slm = np.isfinite(basin_mask['num']) total_area = np.sum(area*slm) basin_weight = np.zeros(len(basin_ensembles)) for basin in range(len(basin_ensembles)): basin_weight[basin] = np.sum(area*(basin_mask['num']==basin)) / total_area reg_acc = np.zeros([len(basin_ensembles),len(settings['years'])],dtype=bool) for basin in range(len(basin_ensembles)): reg_acc[basin,:] = np.isfinite(basin_ensembles[basin]['tg_no_corrections'][0, :]) weight_idx = reg_acc * basin_weight[:,np.newaxis] weight_idx = weight_idx / weight_idx.sum(axis=0) global_ensembles = {} for method in basin_ensembles[0].keys(): global_ensembles[method] = np.zeros([settings['num_ens'],len(settings['years'])]) for basin in range(len(basin_ensembles)): basin_lcl = basin_ensembles[basin][method].copy() basin_lcl[np.isnan(basin_lcl)] = 0 global_ensembles[method] = global_ensembles[method] + weight_idx[basin,:] * basin_lcl return(global_ensembles)
def prep_GWD_Doll(GRACE, depletion_mscn, settings): # --------------------------------------------- # Ground water depletion from Doll et al (2014) # - Transform from monthly to annual # - 0-360 # - Mask out Greenland # --------------------------------------------- file_handle = Dataset(settings['fn_gwd_doll_irr'], 'r') file_handle.set_auto_mask(False) time = 1960+file_handle.variables['time'][:]/12 + 1/24 lat = file_handle.variables['lat'][:] lon = file_handle.variables['lon'][:] tws_irr = file_handle.variables['TWS_mm'][:] tws_irr[tws_irr < -9998] = np.nan file_handle.close() tws_nouse = Dataset(settings['fn_gwd_doll_nouse'], 'r').variables['TWS_mm'][:]._get_data() tws_nouse[tws_nouse < -9998] = np.nan # To 0-360 tws_irr = np.dstack([tws_irr[:,:,360:],tws_irr[:,:,:360]]) tws_nouse = np.dstack([tws_nouse[:,:,360:],tws_nouse[:,:,:360]]) # Depletion in irrigated minus natural tws = tws_irr - tws_nouse area = gentools.grid_area(GRACE['lat'], GRACE['lon']) mask = np.load(settings['fn_mask'],allow_pickle=True).all() mask_tws = (mask['land']) & (~mask['AIS']) & (~mask['GrIS']) # To annual tws[:,~mask_tws] = 0 tws[np.isnan(tws)] = 0 time_ann_doll = np.arange(1960,2004,1) tws_ann_doll = np.zeros([len(time_ann_doll),len(lat),len(lon)]) for idx, t in enumerate(time_ann_doll): acc_t = (np.floor(time).astype(int)==t) tws_ann_doll[idx,:,:] = tws[acc_t,:,:].mean(axis=0) # To mascon tws_ann_doll_global = np.nansum(tws_ann_doll * area, axis=(1, 2)) tws_ann_doll_mscn = np.zeros(tws_ann_doll.shape) # Into mascons for k in range(len(GRACE['mscn_coords'])): lat_acc = np.where((GRACE['lat'] >= GRACE['mscn_coords'][k, 0]) & (GRACE['lat'] < GRACE['mscn_coords'][k, 1]))[0] lon_acc = np.where((GRACE['lon'] >= GRACE['mscn_coords'][k, 2]) & (GRACE['lon'] < GRACE['mscn_coords'][k, 3]))[0] lsm_acc = GRACE['land'][lat_acc[0]:lat_acc[-1] + 1, lon_acc[0]:lon_acc[-1] + 1] dp_mean = np.mean(tws_ann_doll[:,lat_acc[0]:lat_acc[-1] + 1, lon_acc[0]:lon_acc[-1] + 1]*lsm_acc[np.newaxis,:,:],axis=(1,2)) tws_ann_doll_mscn[:,lat_acc[0]:lat_acc[-1] + 1, lon_acc[0]:lon_acc[-1] + 1] = dp_mean[:,np.newaxis,np.newaxis] tws_ann_doll_mscn = tws_ann_doll_mscn * GRACE['land'][np.newaxis,:,:] tws_ann_doll_global_mscn = np.nansum(tws_ann_doll_mscn * area, axis=(1, 2)) tws_ann_doll_mscn *= (tws_ann_doll_global/tws_ann_doll_global_mscn)[:,np.newaxis,np.newaxis] depletion_doll_mscn = np.zeros(depletion_mscn.shape) depletion_doll_mscn[:61,...] = depletion_mscn[:61,...] depletion_doll_mscn[60:,...] = tws_ann_doll_mscn - tws_ann_doll_mscn[0,...][np.newaxis,...] + depletion_doll_mscn[60,...][np.newaxis,...] # tst = np.nansum(tws_annual * area, axis=(1, 2)) # tst2 = np.nansum(depletion_mscn * area, axis=(1, 2)) # tst3 = np.nansum(depletion_doll_mscn * area, axis=(1, 2)) return(depletion_doll_mscn)
def prep_dams(GRACE,settings): # -------------------------------------------------------------------------------------------- # Prepare dam water storage data # 1. Read dam lists from the GRanD list and the data from Ben Chao # 2. Remove duplicates as good as it gets # 3. Fill global grid with dam retention data and seepage estimates based on Chao et al., 2008 # -------------------------------------------------------------------------------------------- print(' Reading spreadsheets...') chao_list_raw = pd.read_excel(settings['fn_chao_list'], header=None).values # Read Chao list chao_loc_raw = pd.read_excel(settings['fn_chao_loc'], header=None).values # Read Chao locs lehner_raw = pd.read_excel(settings['fn_lehner'], header=None).values # Read Lehner locs # name lat lon year cap loc_avail dam_list_grand = np.zeros([len(lehner_raw), 6], dtype=object) print(' Processing GRanD list...') lehner_raw[:, 2][lehner_raw[:, 2]<0] = lehner_raw[:, 2][lehner_raw[:, 2]<0] + 360 for i in range(len(lehner_raw)): dam_list_grand[i, 0] = lehner_raw[i, 1].split('(')[0].lower().replace(" ", "") dam_list_grand[i, 1] = lehner_raw[i, 3] dam_list_grand[i, 2] = lehner_raw[i, 2] dam_list_grand[i, 3] = lehner_raw[i, 7] dam_list_grand[i, 4] = lehner_raw[i, 6] * 1000 dam_list_grand[i, 5] = True dam_list_grand = dam_list_grand[dam_list_grand[:, 4] > 0, :] print(' Processing Ben Chaos location list...') # -------------------------------------------------------------- # GRanD list and Benjamin Chao's location list have overlap # Challenge: find dams that are in Chao's list, but not in GRanD # These dams have a known lat/lon location # -------------------------------------------------------------- dam_list_chao_loc = [] chao_loc_raw[:, 6][chao_loc_raw[:, 6]<0] = chao_loc_raw[:, 6][chao_loc_raw[:, 6]<0] + 360 for i in range(len(chao_loc_raw)): dam_list_lcl = np.zeros(6, dtype=object) dam_list_lcl[0] = chao_loc_raw[i, 2].split('(')[0].lower().replace(" ", "") diff_score = np.zeros(len(dam_list_grand)) for lcl in range(len(diff_score)): diff_score[lcl] = Levenshtein.ratio(dam_list_lcl[0], dam_list_grand[lcl, 0]) vol_ratio = chao_loc_raw[i, 3] / (dam_list_grand[lcl, 4]) if (vol_ratio < 0.5) | (vol_ratio > 2): diff_score[lcl] = -1 # If capacity is vastly different, probably different dam if np.abs(chao_loc_raw[i, 4] - dam_list_grand[lcl, 3]) > 2: diff_score[lcl] = -1 # If year of construction is vastly different, probably different dam if np.max(diff_score) < 0.9: dam_list_lcl[1] = chao_loc_raw[i, 5] dam_list_lcl[2] = chao_loc_raw[i, 6] dam_list_lcl[3] = chao_loc_raw[i, 4] dam_list_lcl[4] = chao_loc_raw[i, 3] dam_list_lcl[5] = True dam_list_chao_loc.append(dam_list_lcl) dam_list_chao_loc = np.array(dam_list_chao_loc) dam_list_loc = np.vstack([dam_list_grand, dam_list_chao_loc]) # -------------------------------------------------------------- # GRanD list and Benjamin Chao's location list have overlap # Challenge: find dams that are in Chao's list, but not in GRanD # These dams don't have a known lat/lon location # -------------------------------------------------------------- print(' Processing Ben Chaos full list...') dam_list_chao_full = [] for i in range(len(chao_list_raw)): if chao_list_raw[i, 3] > 1000: dam_list_lcl = np.zeros(6, dtype=object) dam_list_lcl[0] = chao_list_raw[i, 2].split('(')[0].lower().replace(" ", "") diff_score = np.zeros(len(dam_list_loc)) for lcl in range(len(dam_list_loc)): diff_score[lcl] = Levenshtein.ratio(dam_list_lcl[0], dam_list_loc[lcl, 0]) if np.max(diff_score) < 0.7: dam_list_lcl[3] = chao_list_raw[i, 4] dam_list_lcl[4] = chao_list_raw[i, 3] dam_list_lcl[5] = False dam_list_chao_full.append(dam_list_lcl) dam_list_chao_full = np.array(dam_list_chao_full) dam_list = np.vstack([dam_list_grand, dam_list_chao_loc,dam_list_chao_full]) # From 1000 m3 to kg dam_list[:, 4] = dam_list[:, 4] * 1e6 dam_years = np.arange(1800, 2004, 1) # Index for dams with known locations nlocs = np.sum(dam_list[:, 5]) dam_load_list = np.zeros([nlocs, len(dam_years)]) no_seepage = ['manicouagan', 'jenpeg', 'smallwoodreservoir', 'missifallscontrol', 'earfalls', 'whitesandrapids', 'pipmuacan', 'keenleyside', 'sanhezha', 'tainionkoski', 'irkutsk', 'verkhnetulomskaya', 'ondakumskaya', 'verkhnesvirskaya', 'structure308'] # Total volumes print(' Computing storage and seepage...') total_volume = np.zeros(len(dam_years)) # Total water in dam assuming 85% full total_scaled = np.zeros(len(dam_years)) # Total water in dam assuming 85% full total_seepage = np.zeros(len(dam_years)) # Total TWS due to seepage after dam construction total_storage = np.zeros(len(dam_years)) # Total TWS due to water in dam and seepage for i in range(len(dam_list)): local_volume = np.zeros(len(dam_years)) local_seepage = np.zeros(len(dam_years)) if (dam_list[i, 3] > 1799) & (dam_list[i, 3] < 2004): startindex = int(dam_list[i, 3] - 1800) else: startindex = 0 local_volume[startindex:] = dam_list[i, 4] * 0.85 seepage_growth = np.minimum(np.cumsum(1 / np.sqrt(dam_years[startindex + 1:] - (dam_years[startindex]))), 20) local_seepage[startindex + 1:] = dam_list[i, 4] * 0.05 * seepage_growth total_scaled = total_scaled + local_volume total_seepage = total_seepage + local_seepage if dam_list[i, 0] in no_seepage: local_storage = local_volume else: local_storage = local_seepage + local_volume total_storage = total_storage + local_storage total_volume = total_volume + local_volume/0.85 # If location known, add as new entry, otherwise spread over all other locations if i < nlocs: dam_load_list[i, :] = local_storage else: dam_load_list = dam_load_list + (local_storage / nlocs)[np.newaxis, :] # List with dam indices print(' Adding all dams to grid...') area = gentools.grid_area(GRACE['lat'],GRACE['lon']) dam_load = np.zeros([len(dam_years),len(GRACE['lat']),len(GRACE['lon'])]) for i in range(nlocs): idx_lat = np.argmin(np.abs(GRACE['lat'] - dam_list[i, 1])) idx_lon = np.argmin(np.abs(GRACE['lon'] - dam_list[i, 2])) dam_load[:, idx_lat, idx_lon] = dam_load[:, idx_lat, idx_lon] + dam_load_list[i, :] / area[idx_lat, idx_lon] # Only 1900-2004 acc_idx = np.in1d(dam_years, settings['time']) dam_load = dam_load[acc_idx, :, :] total_scaled = total_scaled[acc_idx] total_seepage = total_seepage[acc_idx] total_storage = total_storage[acc_idx] total_volume = total_volume[acc_idx] # smooth_trend_s = np.zeros(len(settings['time']))*np.nan # # flen=30 # fhalf = int(flen/2) # for idx,yr in enumerate(settings['time']): # if (idx>(fhalf-1)) & (idx<len(settings['time'])-fhalf-1): # amat = np.ones([flen,2]) # amat[:,1] = settings['time'][idx-fhalf:idx+fhalf] # smooth_trend_s[idx] = np.linalg.lstsq(amat,total_storage[idx-fhalf:idx+fhalf],rcond=None)[0][1] # To mascon print(' Grid to mascon...') dam_load_mscn = np.zeros(dam_load.shape) # Into mascons for k in range(len(GRACE['mscn_coords'])): lat_acc = np.where((GRACE['lat'] >= GRACE['mscn_coords'][k, 0]) & (GRACE['lat'] < GRACE['mscn_coords'][k, 1]))[0] lon_acc = np.where((GRACE['lon'] >= GRACE['mscn_coords'][k, 2]) & (GRACE['lon'] < GRACE['mscn_coords'][k, 3]))[0] lsm_acc = GRACE['land'][lat_acc[0]:lat_acc[-1] + 1, lon_acc[0]:lon_acc[-1] + 1] dp_mean = np.mean(dam_load[:,lat_acc[0]:lat_acc[-1] + 1, lon_acc[0]:lon_acc[-1] + 1]*lsm_acc[np.newaxis,:,:],axis=(1,2)) dam_load_mscn[:,lat_acc[0]:lat_acc[-1] + 1, lon_acc[0]:lon_acc[-1] + 1] = dp_mean[:,np.newaxis,np.newaxis] dam_load_mscn = dam_load_mscn * GRACE['land'][np.newaxis,:,:] dam_load_global_mscn = np.nansum(dam_load_mscn * area, axis=(1, 2)) dam_load_mscn = dam_load_mscn * (total_storage/dam_load_global_mscn)[:,np.newaxis,np.newaxis] return(dam_load_mscn)
def read_glacier_mask(grace_mask, settings): print(' Processing glacier masks...') glacier_mask = {} glacier_mask['lat'] = grace_mask['lat'] glacier_mask['lon'] = grace_mask['lon'] area = gentools.grid_area(grace_mask['lat'], grace_mask['lon']) # Read RGI masks and areas and remove the Greenland and Antarctic Periphery glacier_mask['num_grace'] = np.array( [1, 3, 4, 6, 7, 9, 17]) # Glacier regions where mascons are dominated by GIS glacier_mask['num_insitu'] = np.array([ 2, 8, 10, 11, 12, 13, 14, 15, 16, 18 ]) # Regions where GIS contribution is determined from Zemp et al (2019) glacier_mask['num'] = np.sort( np.hstack([glacier_mask['num_grace'], glacier_mask['num_insitu']])) # Read and remove the Greenland and Antarctic Periphery rgi_mask = Dataset(settings['fn_rgi_mask'], 'r').variables['mask'][:]._get_data().astype(bool) rgi_area = Dataset(settings['fn_rgi_mask'], 'r').variables['total_area'][:]._get_data() * 1e6 # m^2 rgi_mask = np.delete(rgi_mask, 4, axis=0)[:-1, :, :] rgi_area = np.delete(rgi_area, 4, axis=0)[:-1, :, :] # Compute mascons that contain glaciers and determine load scale: # Multiply scale by mass loss in GT to get local load in kg/m^2 rgi_scale_mscn = np.zeros( [rgi_mask.shape[0], len(grace_mask['lat']), len(grace_mask['lon'])]) for reg in range(rgi_mask.shape[0]): print(' RGI region ' + str(glacier_mask['num'][reg]) + '...') scale_lcl = np.zeros([len(grace_mask['lat']), len(grace_mask['lon'])]) glac_area_rgi_region = rgi_area[reg, :, :].sum() for k in range(len(grace_mask['mscn_coords'])): lat_acc = np.where( (grace_mask['lat'] >= grace_mask['mscn_coords'][k, 0]) & (grace_mask['lat'] < grace_mask['mscn_coords'][k, 1]))[0] lon_acc = np.where( (grace_mask['lon'] >= grace_mask['mscn_coords'][k, 2]) & (grace_mask['lon'] < grace_mask['mscn_coords'][k, 3]))[0] glac_area_in_mscn = rgi_area[reg, lat_acc[0]:lat_acc[-1] + 1, lon_acc[0]:lon_acc[-1] + 1].sum() area_mscn = np.maximum( 1, (area[lat_acc[0]:lat_acc[-1] + 1, lon_acc[0]:lon_acc[-1] + 1] * grace_mask['mask_land'][lat_acc[0]:lat_acc[-1] + 1, lon_acc[0]:lon_acc[-1] + 1]).sum()) scale_lcl[lat_acc[0]:lat_acc[-1] + 1, lon_acc[0]:lon_acc[-1] + 1] = (glac_area_in_mscn / glac_area_rgi_region) * (1 / area_mscn) rgi_scale_mscn[reg, :, :] = scale_lcl * grace_mask['mask_no_is'] * 1e12 rgi_scale_mscn[reg, :, :] = rgi_scale_mscn[reg, :, :] * 1e12 / ( rgi_scale_mscn[reg, :, :] * area).sum() glacier_mask['scale'] = rgi_scale_mscn glacier_mask['mask_all'] = (rgi_scale_mscn.sum(axis=0) > 0) glacier_mask['mask_grace'] = (rgi_scale_mscn[ np.in1d(glacier_mask['num'], glacier_mask['num_grace']), :, :].sum( axis=0) > 0) glacier_mask['mask_insitu'] = (rgi_scale_mscn[ np.in1d(glacier_mask['num'], glacier_mask['num_insitu']), :, :].sum( axis=0) > 0) return (glacier_mask)
def compute_basin_estimate(regions_for_selection, settings): print('Computing basin estimates:') # -------------------------------------------- # Read GIA and GRD and compute basin estimates # -------------------------------------------- basin_mask = read_basin_mask(settings) # Sample locations regions_for_selection['grd_sample_points'] = np.zeros( [len(regions_for_selection['id']), 2], dtype=int) lat = np.arange(-89.75, 90.25, 0.5) lon = np.arange(0.25, 360.25, 0.5) regions_for_selection['grd_sample_points'][:, 0] = np.argmin( np.abs(regions_for_selection['coords'][:, 0][np.newaxis, :] - lat[:, np.newaxis]), axis=0) regions_for_selection['grd_sample_points'][:, 1] = np.argmin( np.abs(regions_for_selection['coords'][:, 1][np.newaxis, :] - lon[:, np.newaxis]), axis=0) # Sample GIA at region locations GIA = read_GIA_rsl(settings) regions_for_selection['rsl_gia_mean'] = np.zeros( len(regions_for_selection['id'])) regions_for_selection['rsl_gia_dev'] = np.zeros( len(regions_for_selection['id'])) # Deviation of region from basin for region in range(len(regions_for_selection['id'])): regions_for_selection['rsl_gia_mean'][region] = ( GIA['probability'] * GIA['rsl'][:, regions_for_selection['grd_sample_points'][region, 0], regions_for_selection['grd_sample_points'][region, 1]]).sum() GIA_basin = np.zeros(len(basin_mask['basins'])) # Basin-mean GIA area = gentools.grid_area(GIA['lat'], GIA['lon']) for basin in range(len(basin_mask['basins'])): GIA_basin[basin] = (GIA['probability'] * ( ((area * (basin_mask['num'] == basin))[np.newaxis, :, :] * GIA['rsl']).sum(axis=(1, 2)) / (area * (basin_mask['num'] == basin)).sum())).sum() for region in range(len(regions_for_selection['id'])): regions_for_selection['rsl_gia_dev'][region] = regions_for_selection[ 'rsl_gia_mean'][region] - GIA_basin[ regions_for_selection['basin_num'][region]] # Sample GRD at region locations regions_for_selection['rsl_grd_mean'] = np.zeros( [len(regions_for_selection['id']), len(settings['years'])]) regions_for_selection['rsl_grd_dev'] = np.zeros( [len(regions_for_selection['id']), len(settings['years'])]) # Deviation of region from basin grd_region_ens = np.zeros([ settings['num_ens'], len(regions_for_selection['id']), len(settings['years']) ]) grd_basin_ens = np.zeros([ settings['num_ens'], len(basin_mask['basins']), len(settings['years']) ]) for ens in range(settings['num_ens']): print(' Ensemble ' + str(ens)) GRD_rsl_ens = read_GRD_rsl_ens(ens, settings) for region in range(len(regions_for_selection['id'])): grd_region_ens[ ens, region, :] = GRD_rsl_ens[:, regions_for_selection[ 'grd_sample_points'][ region, 0], regions_for_selection['grd_sample_points'][region, 1]] for basin in range(len(basin_mask['basins'])): grd_basin_ens[ens, basin, :] = ( (area * (basin_mask['num'] == basin))[np.newaxis, :, :] * GRD_rsl_ens ).sum(axis=(1, 2)) / (area * (basin_mask['num'] == basin)).sum() grd_basin = (GIA['probability'][:, np.newaxis, np.newaxis] * grd_basin_ens).sum(axis=0) grd_region = (GIA['probability'][:, np.newaxis, np.newaxis] * grd_region_ens).sum(axis=0) for region in range(len(regions_for_selection['id'])): regions_for_selection['rsl_grd_mean'][region, :] = grd_region[ region, :] regions_for_selection['rsl_grd_dev'][region] = grd_region[ region, :] - grd_basin[ regions_for_selection['basin_num'][region], :] return (regions_for_selection)
def compute_indiv_tws(settings): indiv_tws = {} # Natural: Read Humphrey average fn = settings[ 'dir_data'] + 'Hydrology/Humphrey/01_monthly_grids_ensemble_means_allmodels/GRACE_REC_v03_JPL_GSWP3_monthly_ensemble_mean.nc' file_handle = Dataset(fn, 'r') file_handle.set_auto_mask(False) lat = file_handle.variables['lat'][:] lon = file_handle.variables['lon'][:] time = file_handle.variables['time'][:] / 365.25 + 1901 load = file_handle.variables['rec_ensemble_mean'][:] file_handle.close() mask = np.load(settings['fn_mask'], allow_pickle=True).all() load = np.dstack([load[:, :, 360:], load[:, :, :360]]) load[load < -32e4] = 0 bary_annual = np.zeros(len(settings['years'])) * np.nan area = gentools.grid_area(lat, lon) for idx, year in enumerate(settings['years']): acc_idx = np.floor(time).astype(int) == year if acc_idx.sum() > 0: bary_annual[idx] = np.nansum(area * mask['tws'] * load[acc_idx, :, :].mean(axis=0)) indiv_tws['Humphrey'] = bary_annual / -362e12 # GWD Wada/Doll wada_2016_scale = 0.6 # Scale factor (Wada 2016) wada_depletion = np.zeros(len(settings['years'])) * np.nan # Old Wada 2010 data time_past = np.arange(1900, 1960) for idx, yr in enumerate(time_past): data_raw = np.loadtxt(settings['dir_gwd_20c'] + 'gwd0' + str(yr) + '.asc', skiprows=6) data_raw[data_raw == -9999] = 0 data_raw = np.flipud(data_raw) data_raw = np.hstack([data_raw[:, 360:], data_raw[:, 0:360]]) wada_depletion[idx] = data_raw.sum() * 1e9 # Present (Wada 2014) file_handle = Dataset(settings['fn_gwd_wada'], 'r') file_handle.set_auto_mask(False) depletion_pd_monthly = file_handle.variables["anrg"][:] depletion_pd_monthly[depletion_pd_monthly < 0] = 0 file_handle.close() time_pd_m = gentools.monthly_time(1960, 2010) time_present = np.arange(1960, 2011) # To normal grid depletion_rate_monthly = np.fliplr(depletion_pd_monthly) depletion_rate_monthly = np.dstack([ depletion_rate_monthly[:, :, 360:], depletion_rate_monthly[:, :, 0:360] ]) for idx, yr in enumerate(time_present): idx_m = (time_pd_m > yr) & (time_pd_m < yr + 1) wada_depletion[idx + 60] = (np.sum(depletion_rate_monthly[idx_m, :, :], axis=0)).sum() * 1e9 indiv_tws['Wada'] = wada_2016_scale * np.cumsum(wada_depletion) / 362e12 ### DOLL file_handle = Dataset(settings['fn_gwd_doll_irr'], 'r') file_handle.set_auto_mask(False) time = 1960 + file_handle.variables['time'][:] / 12 + 1 / 24 tws_irr = file_handle.variables['TWS_mm'][:] tws_irr[tws_irr < -9998] = np.nan file_handle.close() tws_nouse = Dataset(settings['fn_gwd_doll_nouse'], 'r').variables['TWS_mm'][:]._get_data() tws_nouse[tws_nouse < -9998] = np.nan # To 0-360 tws_irr = np.dstack([tws_irr[:, :, 360:], tws_irr[:, :, :360]]) tws_nouse = np.dstack([tws_nouse[:, :, 360:], tws_nouse[:, :, :360]]) # Depletion in irrigated minus natural tws_doll = tws_irr - tws_nouse mask = np.load(settings['fn_mask'], allow_pickle=True).all() mask_tws = (mask['land']) & (~mask['AIS']) & (~mask['GrIS']) doll_depletion = np.zeros(len(settings['years'])) * np.nan # To annual tws_doll[:, ~mask_tws] = 0 tws_doll[np.isnan(tws_doll)] = 0 time_ann_doll = np.arange(1960, 2010, 1) for idx, t in enumerate(time_ann_doll): acc_t = (np.floor(time).astype(int) == t) doll_depletion[idx + 60] = (area * (tws_doll[acc_t, :, :].mean(axis=0))).sum() indiv_tws['Doll'] = doll_depletion / -362e12 #################### Dams print(' Reading spreadsheets...') chao_list_raw = pd.read_excel(settings['fn_chao_list'], header=None).values # Read Chao list chao_loc_raw = pd.read_excel(settings['fn_chao_loc'], header=None).values # Read Chao locs lehner_raw = pd.read_excel(settings['fn_lehner'], header=None).values # Read Lehner locs # name lat lon year cap loc_avail dam_list_grand = np.zeros([len(lehner_raw), 6], dtype=object) print(' Processing GRanD list...') lehner_raw[:, 2][ lehner_raw[:, 2] < 0] = lehner_raw[:, 2][lehner_raw[:, 2] < 0] + 360 for i in range(len(lehner_raw)): dam_list_grand[i, 0] = lehner_raw[i, 1].split('(')[0].lower().replace( " ", "") dam_list_grand[i, 1] = lehner_raw[i, 3] dam_list_grand[i, 2] = lehner_raw[i, 2] dam_list_grand[i, 3] = lehner_raw[i, 7] dam_list_grand[i, 4] = lehner_raw[i, 6] * 1000 dam_list_grand[i, 5] = True dam_list_grand = dam_list_grand[dam_list_grand[:, 4] > 0, :] print(' Processing Ben Chaos location list...') # -------------------------------------------------------------- # GRanD list and Benjamin Chao's location list have overlap # Challenge: find dams that are in Chao's list, but not in GRanD # These dams have a known lat/lon location # -------------------------------------------------------------- dam_list_chao_loc = [] chao_loc_raw[:, 6][chao_loc_raw[:, 6] < 0] = chao_loc_raw[:, 6][chao_loc_raw[:, 6] < 0] + 360 for i in range(len(chao_loc_raw)): dam_list_lcl = np.zeros(6, dtype=object) dam_list_lcl[0] = chao_loc_raw[i, 2].split('(')[0].lower().replace( " ", "") diff_score = np.zeros(len(dam_list_grand)) for lcl in range(len(diff_score)): diff_score[lcl] = Levenshtein.ratio(dam_list_lcl[0], dam_list_grand[lcl, 0]) vol_ratio = chao_loc_raw[i, 3] / (dam_list_grand[lcl, 4]) if (vol_ratio < 0.5) | (vol_ratio > 2): diff_score[ lcl] = -1 # If capacity is vastly different, probably different dam if np.abs(chao_loc_raw[i, 4] - dam_list_grand[lcl, 3]) > 2: diff_score[ lcl] = -1 # If year of construction is vastly different, probably different dam if np.max(diff_score) < 0.9: dam_list_lcl[1] = chao_loc_raw[i, 5] dam_list_lcl[2] = chao_loc_raw[i, 6] dam_list_lcl[3] = chao_loc_raw[i, 4] dam_list_lcl[4] = chao_loc_raw[i, 3] dam_list_lcl[5] = True dam_list_chao_loc.append(dam_list_lcl) dam_list_chao_loc = np.array(dam_list_chao_loc) dam_list_loc = np.vstack([dam_list_grand, dam_list_chao_loc]) # -------------------------------------------------------------- # GRanD list and Benjamin Chao's location list have overlap # Challenge: find dams that are in Chao's list, but not in GRanD # These dams don't have a known lat/lon location # -------------------------------------------------------------- print(' Processing Ben Chaos full list...') dam_list_chao_full = [] for i in range(len(chao_list_raw)): if chao_list_raw[i, 3] > 1000: dam_list_lcl = np.zeros(6, dtype=object) dam_list_lcl[0] = chao_list_raw[i, 2].split('(')[0].lower().replace( " ", "") diff_score = np.zeros(len(dam_list_loc)) for lcl in range(len(dam_list_loc)): diff_score[lcl] = Levenshtein.ratio(dam_list_lcl[0], dam_list_loc[lcl, 0]) if np.max(diff_score) < 0.7: dam_list_lcl[3] = chao_list_raw[i, 4] dam_list_lcl[4] = chao_list_raw[i, 3] dam_list_lcl[5] = False dam_list_chao_full.append(dam_list_lcl) dam_list_chao_full = np.array(dam_list_chao_full) dam_list = np.vstack( [dam_list_grand, dam_list_chao_loc, dam_list_chao_full]) # From 1000 m3 to kg dam_list[:, 4] = dam_list[:, 4] * 1e6 dam_years = np.arange(1800, 2019, 1) # Index for dams with known locations nlocs = np.sum(dam_list[:, 5]) dam_load_list = np.zeros([nlocs, len(dam_years)]) no_seepage = [ 'manicouagan', 'jenpeg', 'smallwoodreservoir', 'missifallscontrol', 'earfalls', 'whitesandrapids', 'pipmuacan', 'keenleyside', 'sanhezha', 'tainionkoski', 'irkutsk', 'verkhnetulomskaya', 'ondakumskaya', 'verkhnesvirskaya', 'structure308' ] # Total volumes print(' Computing storage and seepage...') total_volume = np.zeros( len(dam_years)) # Total water in dam assuming 85% full total_scaled = np.zeros( len(dam_years)) # Total water in dam assuming 85% full total_seepage = np.zeros( len(dam_years)) # Total TWS due to seepage after dam construction total_storage = np.zeros( len(dam_years)) # Total TWS due to water in dam and seepage for i in range(len(dam_list)): local_volume = np.zeros(len(dam_years)) local_seepage = np.zeros(len(dam_years)) if (dam_list[i, 3] > 1799) & (dam_list[i, 3] < 2004): startindex = int(dam_list[i, 3] - 1800) else: startindex = 0 local_volume[startindex:] = dam_list[i, 4] * 0.85 seepage_growth = np.minimum( np.cumsum(1 / np.sqrt(dam_years[startindex + 1:] - (dam_years[startindex]))), 20) local_seepage[startindex + 1:] = dam_list[i, 4] * 0.05 * seepage_growth total_scaled = total_scaled + local_volume total_seepage = total_seepage + local_seepage if dam_list[i, 0] in no_seepage: local_storage = local_volume else: local_storage = local_seepage + local_volume total_storage = total_storage + local_storage total_volume = total_volume + local_volume / 0.85 indiv_tws['Chao'] = -total_storage[100:] / 362e12 for model in indiv_tws: indiv_tws[model] -= indiv_tws[model][103:108].mean() full_ens = np.zeros([settings['num_ens'], len(settings['years'])]) for ens in range(settings['num_ens']): full_ens[ens, :] = Dataset( settings['dir_data'] + 'Budget_20c/grd/grd_tws_' + str(ens) + '.nc', 'r').variables['barystatic'][:]._get_data() ts_full = ensemble_ts(full_ens, settings) indiv_tws['GRACE'] = np.zeros(len(settings['years'])) * np.nan indiv_tws['GRACE'][103:] = ts_full[103:, 1] indiv_tws['full'] = ts_full return (indiv_tws)