def test_xr_quadtrend(self): # throw error if no time coordinate not first def are_close(x, y): self.assertIsNone(xr.testing.assert_allclose(x, y)) are_close(self.A, self.A) are_close(xr_quadtrend(self.A), self.A) are_close(xr_quadtrend(self.B), self.B) print(self.C) print(xr_quadtrend(self.C)) are_close(xr_quadtrend(self.C), self.C) pass
def make_pwqd_TEMP_files(self): """ quadratically detrends annually averaged TEMP field at each point for selected 250 year segments of CTRL or LPD simulations pwqd : `point wise quadratically detrended` """ if self.run=='ctrl': path = f'{path_prace}/ctrl_rect' interp = '.interp900x602' mf_fn = f'{path}/TEMP_PD_yrly_*.interp900x602.nc' trange = np.arange(50,300) km = 42 z = 'depth_t' elif self.run=='lpd': path = f'{path_prace}/lpd' interp = '' mf_fn = f'{path}/ocn_yrly_TEMP_PD_*.nc' trange = np.arange(0,250) km = 60 z = 'z_t' # concatenate yearly files yrly_TEMP_file = f'{path}/TEMP_yrly{interp}.nc' try: # assert 1==0 assert os.path.exists(yrly_TEMP_file) except: print('making yrly TEMP file') da = xr.open_mfdataset(mf_fn, concat_dim='time').TEMP da = da.isel(time=trange) da.assign_coords(time=da.time.values).to_netcdf(yrly_TEMP_file) da.close() # calculating detrended TEMP field for each vertical level b/c of memory limitations for k in tqdm(range(km)): fn = f'{path}/TEMP_yrly_pwqd_{k:02d}{interp}.nc' try: # assert 1==0 assert os.path.exists(fn) except: da_k = xr.open_dataarray(yrly_TEMP_file, decode_times=False).isel({z:k}) da_pwqd_k = da_k - xr_quadtrend(da_k) da_pwqd_k.to_netcdf(fn) da_pwqd_k.close() # concatenating print(f'{path}/TEMP_yrly_pwqd_*{interp}.nc') da_pwqd = xr.open_mfdataset(f'{path}/TEMP_yrly_pwqd_*{interp}.nc', concat_dim=['depth_t'], chunks={'time':1}) if self.run=='ctrl': da_pwqd = da_pwqd.assign_coords(time=np.arange(51,301)) elif self.run=='lpd': da_pwqd = da_pwqd.assign_coords(time=np.arange(154,404)) # da = xr.open_dataarray(yrly_TEMP_file, decode_times=False) # da_pwqd = da - xr_quadtrend(da) # writing out files for individual years print(da_pwqd.time) for i, y in tqdm(enumerate(da_pwqd.time)): # 9 mins for ctrl da_pwqd.isel(time=i).to_netcdf(f'{path}/TEMP_pwqd_yrly_{int(y.values):04d}{interp}.nc') return
def quadratically_detrend_OHC_integral_fields(ds, name): """ iterates through all fields in OHC_integral file and quadratically detrends them in time """ # < 1 min for both ctrl_rect and lpd ds_ = ds.copy() key_list = [k for k in ds.data_vars.keys()] for k in tqdm(key_list): ds_[k].values = (ds[k] - xr_quadtrend(ds[k])).values ds_.to_netcdf(f'{path_samoc}/OHC/OHC_integrals_{name}_qd.nc') return
def detrend_monthly_data_pointwise(self, run, time): """ quadratically detrend monthly fields """ assert run in ['ctrl', 'lpd', 'lc1'] da = xr.open_dataarray( f'{path_prace}/SST/SST_monthly_ds_{run}_{time[0]}_{time[1]}.nc', decode_times=False) da = self.select_time(data=da, time=time) fn_out = f'{path_prace}/SST/SST_monthly_ds_dt_{run}_{time[0]}_{time[1]}.nc' (da - xr_quadtrend(da)).to_netcdf(fn_out) return
def plot_global_integrals_detr(dss, run): """ quadratically detrended input: dss .. list of datasets """ n = len(dss) assert n <= 6 assert run in ['ctrl', 'rcp', 'lpd', 'lpi'] if run == 'ctrl': fs = 8 elif run == 'rcp': fs = 6 elif run == 'lpd': fs = 10 elif run == 'lpi': fs = 16 f = plt.figure(figsize=(fs, 5)) ax = f.add_axes([0.13 * 8 / fs, 0.13, .98 - .13 * 8 / fs, .85]) plt.tick_params(labelsize=14) plt.axhline(0, c='k', lw=.5) for i, ds in enumerate(dss): qf = np.polyfit(ds.time, ds.OHC_global, 2) detr = ds.OHC_global - xr_quadtrend(ds.OHC_global) plt.plot(ds.time / 365, lowpass(detr, 13) / 1e21, c=colors[i], label=f'{labels[i]}', lw=lws[i]) if run in ['lpd', 'lpi']: plt.plot(ds.time / 365, lowpass(detr, 100) / 1e21, c=colors[i], label=f'{labels[i]}', lw=lws[i], ls='--') plt.text(.5, .9, f'{run.upper()}', ha='center', transform=ax.transAxes, fontsize=16) plt.text(.98, .02, '13 year lowpass filtered', ha='right', transform=ax.transAxes, fontsize=14) plt.xlabel('time [years]', fontsize=16) plt.ylabel('quad. detrended OHC [ZJ]', fontsize=16) plt.savefig(f'{path_results}/OHC/OHC_global_integrals_regional_detr_{run}')
def forcing_signal(self, run, tavg, detrend_signal, time=None): """ GMST forced component run .. dataset tavg .. time resolution detrend_signal .. time """ print('creating forcing signal') assert run in ['ctrl', 'rcp', 'lpd', 'lpi', 'had'] assert tavg in ['yrly', 'monthly'] assert detrend_signal in ['GMST', 'AMO', 'SOM', 'TPI1', 'TPI2', 'TPI3'] # simulations: linear/quadratic fit to GMST signal if run in ['ctrl', 'rcp', 'lpd', 'lpi']: assert detrend_signal == 'GMST' if run == 'rcp': # need actual GMST time series forced_signal = xr.open_dataset( f'{path_prace}/GMST/GMST_{tavg}_{run}.nc', decode_times=False).GMST forced_signal = xr_quadtrend(forced_signal) elif run in ['ctrl', 'lpd']: # use global mean SST as as proxy forced_signal = xr.open_dataarray( f'{path_prace}/SST/GMSST_{tavg}_{run}.nc', decode_times=False) if run == 'ctrl': # strong adjustment in the first 40 years forced_signal = forced_signal[40:] forced_signal = xr_quadtrend(forced_signal) else: # create mock linear trend times = xr.open_dataarray( f'{path_prace}/SST/SST_{tavg}_{run}.nc', decode_times=False).time forced_signal = xr.DataArray( np.linspace(0, 1, len(times)), coords={'time': np.sort(times.values)}, dims=('time')) forced_signal.name = 'GMST' forced_signal.attrs = { 'Note': 'This is the mock linear trend, simply going from 0 to 1' } #if tavg=='yrly': #times = forced_signal['time'] + 31 # time coordinates shifted by 31 days (SST saved end of January, GMST beginning) #if run=='ctrl': # for this run, sometimes 31 days, sometimes 15/16 days offset #times = xr.open_dataset(f'{path_prace}/SST/SST_yrly_ctrl.nc', decode_times=False).time #forced_signal = forced_signal.assign_coords(time=times) # observations: CMIP5 multi model ensemble mean of all forcings GMST elif run == 'had': forced_signal = xr.open_dataarray( f'{path_data}/CMIP5/KNMI_CMIP5_{detrend_signal}_{tavg}.nc', decode_times=False) if tavg == 'monthly': # deseasonalize for t in range(12): forced_signal[t::12] -= forced_signal[t::12].mean( dim='time') if tavg == 'yrly': # select 1870-2018 times = (forced_signal['time'].astype(int) - 9) * 365 forced_signal = forced_signal.assign_coords( time=times) # days since 1861 forced_signal = forced_signal[9:158] elif tavg == 'monthly': # ... forced_signal = forced_signal[9 * 12:158 * 12 - 1] times = xr.open_dataarray( f'{path_prace}/SST/SST_monthly_had.nc', decode_times=False).time.values forced_signal = forced_signal.assign_coords(time=times) forced_signal = self.select_time(forced_signal, time) forced_signal -= forced_signal.mean() forced_signal.name = 'forcing' return forced_signal