def onset_TT(T, north=(5, 35, 40, 100), south=(-15, 5, 40, 100), yearnm='year', daynm='day'): """Return monsoon onset index based on tropospheric temperature. Parameters ---------- T : xray.DataArray Air temperature 200-600 hPa vertical mean. north, south : 4-tuples of floats, optional Tuple of (lat1, lat2, lon1, lon2) defining northern and southern regions to average over. yearnm, daynm : str, optional Name of year and day dimensions in DataArray Returns ------- tt : xray.Dataset TT daily timeseries for each year and monsoon onset day for each year. Reference --------- Goswami, B. N., Wu, G., & Yasunari, T. (2006). The annual cycle, intraseasonal oscillations, and roadblock to seasonal predictability of the Asian summer monsoon. Journal of Climate, 19, 5078-5099. """ ttn = atm.mean_over_geobox(T, north[0], north[1], north[2], north[3]) tts = atm.mean_over_geobox(T, south[0], south[1], south[2], south[3]) tseries = ttn - tts # Onset day is the first day that ttn-tts becomes positive years = tseries[yearnm] onset = np.zeros(years.shape) for y in range(len(years)): pos = (tseries.values[y] > 0) if not pos.any(): onset[y] = np.nan else: onset[y] = tseries[daynm][pos.argmax()] tt = xray.Dataset() tt['ttn'] = ttn tt['tts'] = tts tt['tseries'] = tseries tt['onset'] = xray.DataArray(onset, coords={yearnm : years}) tt.attrs['north'] = north tt.attrs['south'] = south return tt
def get_mfc_box(mfcfiles, precipfiles, evapfiles, years, nroll, lat1, lat2, lon1, lon2): """Return daily tseries MFC, precip and evap averaged over lat-lon box. """ subset_dict = {'lat' : (lat1, lat2), 'lon' : (lon1, lon2)} databox = {} if mfcfiles is not None: mfc = atm.combine_daily_years('MFC', mfcfiles, years, yearname='year', subset_dict=subset_dict) databox['MFC'] = mfc if precipfiles is not None: pcp = atm.combine_daily_years('PRECTOT', precipfiles, years, yearname='year', subset_dict=subset_dict) databox['PCP'] = pcp if evapfiles is not None: evap = atm.combine_daily_years('EVAP', evapfiles, years, yearname='year', subset_dict=subset_dict) databox['EVAP'] = evap nms = databox.keys() for nm in nms: var = databox[nm] var = atm.precip_convert(var, var.attrs['units'], 'mm/day') var = atm.mean_over_geobox(var, lat1, lat2, lon1, lon2) databox[nm + '_UNSM'] = var databox[nm + '_ACC'] = np.cumsum(var, axis=1) if nroll is None: databox[nm] = var else: databox[nm] = atm.rolling_mean(var, nroll, axis=-1, center=True) tseries = xray.Dataset(databox) return tseries
# ---------------------------------------------------------------------- # Read data nroll = 7 days_ssn = atm.season_days('JJAS') subset_dict = {'lat' : (lat1, lat2), 'lon' : (lon1, lon2)} ts = xray.Dataset() ssn = xray.Dataset() varnms = {'PCP' : 'PRECTOT', 'MFC' : 'MFC', 'EVAP' : 'EVAP', 'W' : 'TQV', 'ANA' : 'DQVDT_ANA'} for nm in files: var = atm.combine_daily_years(varnms[nm], files[nm], years, yearname='year', subset_dict=subset_dict) var = atm.mean_over_geobox(var, lat1, lat2, lon1, lon2) units = var.attrs.get('units') if units in ['kg/m2/s', 'kg m-2 s-1']: var = atm.precip_convert(var, units, 'mm/day') var_sm = atm.rolling_mean(var, nroll, axis=-1, center=True) ts[nm] = var_sm if nm == 'W': # Difference in precipitable water from beginning to end of season var_ssn = var_sm.sel(day=days_ssn) ssn['d' + nm] = (var_ssn[:,-1] - var_ssn[:, 0]) / len(days_ssn) # dW/dt dvar = np.nan * np.ones(var.shape) for y, year in enumerate(years): dvar[y] = np.gradient(var[y]) ts['d%s/dt' % nm] = xray.DataArray(dvar, coords=var.coords) else:
season = 'jja' lon1, lon2 = 0, 100 lat1, lat2 = -20, 50 u = load_daily_season(ustr, year, season, 'U', lat1, lat2, lon1, lon2) plt.figure() atm.pcolor_latlon(u.mean(dim='TIME')) ds = load_daily_season(ustr, year, season, None, lat1, lat2, lon1, lon2) u2 = ds['U'] print((u == u2).any()) season = 'ann' lon1, lon2 = 20, 120 lat1, lat2 = -60, 60 n = 8 # Number of time points per day days = np.arange(1, 366) u = load_daily_season(ustr, year, season, 'U', lat1, lat2, lon1, lon2) udaily = atm.daily_from_subdaily(u, n, dayvals=days) plt.figure() atm.pcolor_latlon(udaily.mean(axis=0), axlims=(lat1,lat2,lon1,lon2)) lat1, lat2 = 10, 30 lon1, lon2 = 60, 100 ubar = atm.mean_over_geobox(u, lat1, lat2, lon1, lon2) ubar_daily = atm.mean_over_geobox(udaily, lat1, lat2, lon1, lon2) plt.figure(figsize=(7,8)) plt.subplot(211) plt.plot(ubar) plt.subplot(212) plt.plot(ubar_daily)
def onset_SJKE(u, v, latlon = (-5, 20, 50, 70), ndays=3, yearnm='Year', daynm='Day', thresh_std=1.0): """Return monsoon onset based on Somali Jet kinetic energy. Parameters ---------- u, v : xray.DataArray 850 hPa zonal and meridional wind. latlon : 4-tuple of floats, optional Tuple of (lat1, lat2, lon1, lon2) defining Somali jet region to average over. ndays : int, optional Number of consecutive days threshold must be exceeded to define onset. yearnm, daynm : str, optional Name of year and day dimensions in DataArray thresh_std : float, optional Number of standard deviations excursion to use as onset threshold. Returns ------- sjke : xray.Dataset Somali jet index daily timeseries for each year and monsoon onset day for each year. Reference --------- Boos, W. R., & Emanuel, K. A. (2009). Annual intensification of the Somali jet in a quasi-equilibrium framework : Observational composites. Quarterly Journal of the Royal Meteorological Society, 135, 319-335. """ days = atm.get_coord(u, coord_name=daynm) years = atm.get_coord(u, coord_name=yearnm) nyears = len(years) # Kinetic energy index ke = np.sqrt(u**2 + v**2) # Average over Somali jet region lat1, lat2, lon1, lon2 = latlon ke = atm.mean_over_geobox(ke, lat1, lat2, lon1, lon2) ke.attrs['title'] = 'KE' ke.attrs['long_name'] = 'sqrt(u**2 + v**2)' # Threshold for onset date vals = ke.values.flatten() keclim = np.nanmean(vals) kestd = np.nanstd(vals) threshold = keclim + thresh_std * kestd # Find first day when KE exceeds threshold and stays above the # threshold for consecutive ndays def onset_day(tseries, threshold, ndays, daynm): above = (tseries.values > threshold) d0 = above.argmax() while not above[d0:d0+ndays].all(): d0 += 1 return tseries[daynm].values[d0] # Find onset day for each year onset = [onset_day(ke[y], threshold, ndays, daynm) for y in range(nyears)] # Pack into dataset sjke = xray.Dataset() sjke['tseries'] = ke sjke['onset'] = xray.DataArray(onset, coords={yearnm : years}) sjke.attrs = {'latlon' : latlon, 'thresh_std' : thresh_std, 'threshold' : threshold, 'ndays' : ndays} return sjke
def onset_OCI(u, latlon = (5, 15, 40, 80), mmdd_thresh=(6,1), ndays=7, yearnm='Year', daynm='Day'): """Return monsoon Onset Circulation Index. Parameters ---------- u : xray.DataArray 850 hPa zonal wind. latlon : 4-tuple of floats, optional Tuple of (lat1, lat2, lon1, lon2) defining South Arabian Sea region to average over. mmdd_thres : 2-tuple of ints, optional Tuple of (month, day) defining climatological mean onset date to use for threshold value of u. ndays : int, optional Number of consecutive days threshold must be exceeded to define onset. yearnm, daynm : str, optional Name of year and day dimensions in DataArray Returns ------- oci : xray.Dataset OCI daily timeseries for each year and monsoon onset day for each year. Reference --------- Wang, B., Ding, Q., & Joseph, P. V. (2009). Objective Definition of the Indian Summer Monsoon Onset. Journal of Climate, 22(12), 3303-3316. """ days = atm.get_coord(u, coord_name=daynm) years = atm.get_coord(u, coord_name=yearnm) nyears = len(years) # Average over South Arabian Sea region lat1, lat2, lon1, lon2 = latlon ubar = atm.mean_over_geobox(u, lat1, lat2, lon1, lon2) # Find values at climatological onset m0, d0 = mmdd_thresh d0 = [atm.mmdd_to_jday(m0, d0, year) for year in years] u0 = [ubar.sel(**{daynm : day, yearnm : year}).values for year, day in zip(years, d0)] u0 = np.array(u0).flatten() uthreshold = np.mean(u0) # Find first day when OCI exceeds threshold and stays above the # threshold for consecutive ndays def onset_day(tseries, uthreshold, ndays, daynm): above = (tseries.values > uthreshold) d0 = above.argmax() while not above[d0:d0+ndays].all(): d0 += 1 return tseries[daynm].values[d0] # Find onset day for each year onset = [onset_day(ubar[y], uthreshold, ndays, daynm) for y in range(nyears)] # Pack into dataset oci = xray.Dataset() oci['tseries'] = ubar oci['onset'] = xray.DataArray(onset, coords={yearnm : years}) oci.attrs['latlon'] = latlon oci.attrs['mmdd_thresh'] = mmdd_thresh oci.attrs['ndays'] = ndays return oci
index['tseries'] = xray.DataArray(pcp_sm, dims=['year', 'day'], coords={'year' : years, 'day': days}) index['onset'] = xray.DataArray(d_onset, coords={'year' : years}) index['retreat'] = xray.DataArray(d_retreat, coords={'year' : years}) index.attrs['title'] = titlestr return index # Threshold and smoothing parameters threshold = 5.0 kmax = 12 nroll = {'CMAP' : 3, 'MERRA_MFC' : 7, 'MERRA_PRECIP' : 7} # Read CMAP pentad precip cmap = precipdat.read_cmap(cmapfile) cmapbar = atm.mean_over_geobox(cmap, lat1, lat2, lon1, lon2) cmapdays = [atm.pentad_to_jday(p, pmin=1) for p in cmap.pentad.values] # MERRA moisture flux convergence mfc = atm.combine_daily_years('MFC', mfcfiles, years, yearname='year') mfcbar = atm.mean_over_geobox(mfc, lat1, lat2, lon1, lon2) # MERRA precip subset_dict = {'lon' : (lon1, lon2), 'lat' : (lat1, lat2)} precip = atm.combine_daily_years('PRECTOT', precipfiles, years, yearname='year', subset_dict=subset_dict) precip = atm.precip_convert(precip, precip.attrs['units'], 'mm/day') precipbar = atm.mean_over_geobox(precip, lat1, lat2, lon1, lon2) # Compute indices for each dataset for name in ['CMAP', 'MERRA_MFC', 'MERRA_PRECIP']:
# ---------------------------------------------------------------------- # Read data data = collections.OrderedDict() for nm in datafiles: var, onset, retreat = utils.load_dailyrel(datafiles[nm]) data[nm] = var # ---------------------------------------------------------------------- # Test atm.regress_field day = -60 # 1-d timeseries var = data['U200'].sel(dayrel=day) ts = atm.mean_over_geobox(var, 10, 30, 60, 100) ts_reg = atm.Linreg(onset, ts) ts_reg2 = atm.regress_field(ts, onset) print(ts_reg.r, ts_reg2.r.values) print(ts_reg.slope, ts_reg2.m.values) print(ts_reg.p, ts_reg2.p.values) # x-y data regdays = [-60, -30, 0, 30, 60] plotdays = [-60, -30] clev_r = np.arange(-1.0, 1.01, 0.05) for nm in varnms: print(nm) var = data[nm].sel(dayrel=regdays) reg_daily = atm.regress_field(var, onset, axis=0) for day in plotdays:
if nm == 'PSI': nm0 = 'V_sector_%dE-%dE' % (lon1, lon2) elif nm == 'VFLXLQV': nm0 = 'VFLXQV' elif nm == dtheta_nm: nm0 = theta_nm else: nm0 = nm relfiles[nm] = filestr % (nm0, onset_nm, yearstr) # ---------------------------------------------------------------------- # Read data and calculate indices # Precipitation precip = precipdat.read_cmap(pcpfile, yearmin=min(years), yearmax=max(years)) pcp_box = atm.mean_over_geobox(precip, lat1, lat2, lon1, lon2) # -- Interpolate to daily resolution days = np.arange(1, 367) pcp_i = np.nan * np.ones((len(years), len(days))) for y, year in enumerate(years): pcp_i[y] = np.interp(days, pcp_box['day'], pcp_box[y]) coords = {'day' : days, 'year' : years} pcp = xray.DataArray(pcp_i, dims=['year', 'day'], coords=coords) # Monsoon onset, retreat indices index = utils.get_onset_indices(onset_nm, indfiles, years) mfc = atm.rolling_mean(index['ts_daily'], nroll, center=True) onset = index['onset'] ssn_length=index['length'].mean(dim='year') data = {}
enso = enso.loc[years] for key in enso_keys: if key not in enso.columns: months = atm.season_months(key) month_names = [(atm.month_str(m)).capitalize() for m in months] enso[key] = enso[month_names].mean(axis=1) enso = enso[enso_keys] col_names = [enso_nm + ' ' + nm for nm in enso.columns] enso.columns = col_names # ---------------------------------------------------------------------- # Daily timeseries ts = xray.Dataset() for nm in ['GPCP', 'PRECTOT']: ts[nm] = atm.mean_over_geobox(data[nm], lat1, lat2, lon1, lon2) ts['MFC'] = utils.daily_rel2onset(index_all['CHP_MFC']['daily_ts'], index[ind_nm], npre, npost) ts['CMFC'] = utils.daily_rel2onset(index_all['CHP_MFC']['tseries'], index[ind_nm], npre, npost) # Extract variables at specified latitudes for nm, lat0 in lat_extract.iteritems(): var = atm.dim_mean(data[nm], 'lon', lon1, lon2) lat = atm.get_coord(var, 'lat') lat0_str = atm.latlon_labels(lat0, 'lat', deg_symbol=False) # key = nm + '_' + lat0_str key = nm lat_closest, _ = atm.find_closest(lat, lat0) print '%s %.2f %.2f' % (nm, lat0, lat_closest)
else: plot_single_WLH(pcp[y], pcp_sm[y], label_sm[y], i_onset[y], i_retreat[y], i_peak[y], titlestr + str(years[y])) if iplot < 4: plt.xticks(np.arange(0, 74, 4), []) else: plt.xticks(np.arange(0, 74, 4)) plt.xlabel('Pentad') # Read data and average over box lon1, lon2 = 60, 100 lat1, lat2 = 10, 30 titlestr = 'CMAP %d-%dE, %d-%dN ' % (lon1, lon2, lat1, lat2) precip = precipdat.read_cmap(cmap_file) precipbar = atm.mean_over_geobox(precip, lat1, lat2, lon1, lon2) nyears, npentad = precipbar.shape years = precipbar.year.values nyears = len(years) pentads = precipbar.pentad onset = {} # Threshold for onset criteria threshold = 5.0 # Smooth with truncated Fourier series kmax = 12 kann = 4 pcp_sm, Rsq = atm.fourier_smooth(precipbar, kmax) pcp_ann, Rsq_ann = atm.fourier_smooth(precipbar, kann) label_sm, label_ann = [], []
import atmos as atm datadir = "/home/jennifer/datastore/merra/daily/" filestr = "merra_uv200_40E-120E_60S-60N_" year = 1980 lon1, lon2 = 60, 100 lat1, lat2 = 10, 30 filename = "%s%s%d.nc" % (datadir, filestr, year) ds = atm.ncload(filename) iplot = {"U": 1, "V": 2, "rel_vort": 3, "Ro": 4} plt.figure(figsize=(12, 9)) for var in ds.data_vars: plt.subplot(2, 2, iplot[var]) atm.pcolor_latlon(ds[var].mean(axis=0)) plt.title(var) dsbar = xray.Dataset() for var in ds.data_vars: print(var) dsbar[var] = atm.mean_over_geobox(ds[var], lat1, lat2, lon1, lon2) plt.figure(figsize=(12, 9)) for var in dsbar.data_vars: plt.subplot(2, 2, iplot[var]) plt.plot(dsbar.Day, dsbar[var]) plt.title(var)
datadir = atm.homedir() + "datastore/merra/daily/" savedir = atm.homedir() + "datastore/merra/analysis/" icalc = False isavefigs = True if icalc: subset_dict = {"lat": (lat1, lat2), "lon": (lon1, lon2)} for varnm in varnms: if varnm == "MFC": varid, filestr = "MFC", "MFC_ps-300mb" elif varnm == "precip": varid, filestr = "PRECTOT", "precip" files = [datadir + "merra_%s_%d.nc" % (filestr, year) for year in years] data = atm.combine_daily_years(varid, files, years, yearname="year", subset_dict=subset_dict) data = atm.mean_over_geobox(data, lat1, lat2, lon1, lon2) data = atm.precip_convert(data, data.attrs["units"], "mm/day") # Accumulated precip or MFC data_acc = np.cumsum(data, axis=1) # Compute onset and retreat days chp = onset_changepoint_merged(data_acc) # Save to file savefile = savedir + "merra_onset_changepoint_merged_%s.nc" % varnm.upper() print("Saving to " + savefile) chp.to_netcdf(savefile) chp = {} for varnm in varnms: