def main(inargs): """Run the program.""" # Read the data dset_in = xarray.open_dataset(inargs.infile) gio.check_xarrayDataset(dset_in, inargs.variable) subset_dict = gio.get_subset_kwargs(inargs) darray = dset_in[inargs.variable].sel(**subset_dict) # Calculate the zonal anomaly zonal_mean = darray.mean(dim='longitude') zonal_anomaly = darray - zonal_mean # Write output file d = {} for dim in darray.dims: d[dim] = darray[dim] d[inargs.variable] = (darray.dims, zonal_anomaly) dset_out = xarray.Dataset(d) dset_out[inargs.variable].attrs = { 'long_name': darray.attrs['long_name'], 'standard_name': darray.attrs['standard_name'], 'units': darray.attrs['units'], 'notes': 'The zonal mean has been subtracted at each time step.' } gio.set_global_atts(dset_out, dset_in.attrs, { inargs.infile: dset_in.attrs['history'], }) dset_out.to_netcdf(inargs.outfile, format='NETCDF3_CLASSIC')
def calc_zw3(ifile, var_id, ofile): """Calculate an index of the Southern Hemisphere ZW3 pattern. Ref: Raphael (2004). A zonal wave 3 index for the Southern Hemisphere. Geophysical Research Letters, 31(23), L23212. doi:10.1029/2004GL020365. Expected input: Raphael (2004) uses is the 500hPa geopotential height, sea level pressure or 500hPa zonal anomalies which are constructed by removing the zonal mean of the geopotential height from each grid point (preferred). The running mean (and zonal mean too if using it) should have been applied to the input data beforehand. Raphael (2004) uses a 3-month running mean. Design notes: This function uses cdo instead of CDAT because the cdutil library doesn't have routines for calculating the daily climatology or stdev. """ # Read data dset_in = xarray.open_dataset(ifile) gio.check_xarrayDataset(dset_in, var_id) # Calculate the index groupby_op = get_groupby_op(dset_in['time'].values) index = {} for region in ['zw31', 'zw32', 'zw33']: south_lat, north_lat, west_lon, east_lon = gio.regions[region] darray = dset_in[var_id].sel( latitude=slice(south_lat, north_lat), longitude=slice(west_lon, east_lon)).mean(dim=['latitude', 'longitude']) clim = darray.groupby(groupby_op).mean(dim='time') anom = darray.groupby(groupby_op) - clim stdev = darray.groupby(groupby_op).std(dim='time') norm = anom.groupby(groupby_op) / stdev index[region] = norm.values zw3_timeseries = (index['zw31'] + index['zw32'] + index['zw33']) / 3.0 # Write output file d = {} d['time'] = darray['time'] d['zw3'] = (['time'], zw3_timeseries) dset_out = xarray.Dataset(d) dset_out['zw3'].attrs = { 'id': 'zw3', 'long_name': 'zonal_wave_3_index', 'standard_name': 'zonal_wave_3_index', 'units': '', 'notes': 'Ref: ZW3 index of Raphael (2004)' } gio.set_global_atts(dset_out, dset_in.attrs, {ifile: dset_in.attrs['history']}) dset_out.to_netcdf(ofile, format='NETCDF3_CLASSIC')
def calc_sam(ifile, var_id, ofile): """Calculate an index of the Southern Annular Mode. Ref: Gong & Wang (1999). Definition of Antarctic Oscillation index. Geophysical Research Letters, 26(4), 459-462. doi:10.1029/1999GL900003 Expected input: Mean sea level pressure data. Concept: Difference between the normalised zonal mean pressure at 40S and 65S. """ # Read data dset_in = xarray.open_dataset(ifile) gio.check_xarrayDataset(dset_in, var_id) # Calculate index north_lat = uconv.find_nearest(dset_in['latitude'].values, -40) south_lat = uconv.find_nearest(dset_in['latitude'].values, -65) darray = dset_in[var_id].sel(latitude=(south_lat, north_lat)).mean(dim='longitude') groupby_op = get_groupby_op(darray['time'].values) clim = darray.groupby(groupby_op).mean(dim='time') anom = darray.groupby(groupby_op) - clim stdev = darray.groupby(groupby_op).std(dim='time') norm = anom.groupby(groupby_op) / stdev sam_timeseries = norm.sel(latitude=north_lat).values - norm.sel( latitude=south_lat).values # Write output file d = {} d['time'] = darray['time'] d['sam'] = (['time'], sam_timeseries) dset_out = xarray.Dataset(d) hx = 'Ref: Gong & Wang (1999). GRL, 26, 459-462. doi:10.1029/1999GL900003' dset_out['sam'].attrs = { 'long_name': 'Southern_Annular_Mode_Index', 'standard_name': 'Southern_Annular_Mode_Index', 'units': '', 'notes': hx } gio.set_global_atts(dset_out, dset_in.attrs, {ifile: dset_in.attrs['history']}) dset_out.to_netcdf(ofile, format='NETCDF3_CLASSIC')
def main(inargs): """Run the program.""" # Read the data dset_in = xarray.open_dataset(inargs.infile) gio.check_xarrayDataset(dset_in, inargs.var) darray, long_name, units = extract_data(dset_in, inargs) # Perform task outdata_dict = {} if inargs.outtype == 'coefficients': outdata_dict = _get_coefficients(darray.values, darray['longitude'].values, inargs.min_freq, inargs.max_freq, long_name, units, outdata_dict) if inargs.sign_change: outdata_dict = _get_sign_change(darray.values, outdata_dict) if inargs.env_max: env_max_min_freq, env_max_max_freq = inargs.env_max outdata_dict = _get_env_max(darray.values, darray['longitude'].values, env_max_min_freq, env_max_max_freq, units, outdata_dict) dims = darray.dims[:-1] else: outdata_dict = _filter_data(darray.values, darray['longitude'].values, inargs.min_freq, inargs.max_freq, inargs.var, long_name, units, inargs.outtype, outdata_dict) dims = darray.dims # Write the output file d = {} for dim in dims: d[dim] = darray[dim] for outvar in outdata_dict.keys(): d[outvar] = (dims, outdata_dict[outvar][0]) dset_out = xarray.Dataset(d) for outvar in outdata_dict.keys(): dset_out[outvar].attrs = outdata_dict[outvar][1] gio.set_global_atts(dset_out, dset_in.attrs, { inargs.infile: dset_in.attrs['history'], }) dset_out.to_netcdf(inargs.outfile)
def calc_nino(index, ifile, var_id, base_period, ofile): """Calculate a Nino index. Expected input: Sea surface temperature data. """ index_name = 'nino' + index[4:] # Read the data dset_in = xarray.open_dataset(ifile) gio.check_xarrayDataset(dset_in, var_id) # Calculate the index south_lat, north_lat, west_lon, east_lon = gio.regions[index_name] darray = dset_in[var_id].sel( latitude=slice(south_lat, north_lat), longitude=slice(west_lon, east_lon)).mean(dim=['latitude', 'longitude']) groupby_op = get_groupby_op(darray['time'].values) clim = darray.sel( time=slice(base_period[0], base_period[1])).groupby(groupby_op).mean() anom = darray.groupby(groupby_op) - clim # Write output if ofile: d = {} d['time'] = darray['time'] d[index_name] = (['time'], anom.values) dset_out = xarray.Dataset(d) hx = 'lat: %s to %s, lon: %s to %s, base: %s to %s' % ( south_lat, north_lat, west_lon, east_lon, base_period[0], base_period[1]) dset_out[index_name].attrs = { 'long_name': index_name + '_index', 'standard_name': index_name + '_index', 'units': 'Celsius', 'notes': hx } gio.set_global_atts(dset_out, dset_in.attrs, {ifile: dset_in.attrs['history']}) dset_out.to_netcdf(ofile, format='NETCDF3_CLASSIC') else: return dset_in, anom.values
def calc_pwi(ifile, var_id, ofile): """Calculate the Planetary Wave Index. Ref: Irving & Simmonds (2015). A novel approach to diagnosing Southern Hemisphere planetary wave activity and its influence on regional climate variability. Journal of Climate. 28, 9041-9057. doi:10.1175/JCLI-D-15-0287.1. Expected input: Wave envelope. """ # Read data dset_in = xarray.open_dataset(ifile) gio.check_xarrayDataset(dset_in, var_id) # Calculate index darray = dset_in[var_id].sel(latitude=slice(-70, -40)) mermax = darray.max(dim='latitude') pwi_timeseries = mermax.median(dim='longitude') # Write output file d = {} d['time'] = darray['time'] d['pwi'] = (['time'], pwi_timeseries.values) dset_out = xarray.Dataset(d) dset_out['pwi'].attrs = { 'long_name': 'planetary_wave_index', 'standard_name': 'planetary_wave_index', 'units': darray.attrs['units'], 'notes': 'Ref: PWI of Irving and Simmonds (2015)' } gio.set_global_atts(dset_out, dset_in.attrs, {ifile: dset_in.attrs['history']}) dset_out.to_netcdf(ofile, format='NETCDF3_CLASSIC')
def calc_mi(ifile, var_id, ofile): """Calculate the meridional wind index. Represents the average amplitude of the meridional wind over the 70S to 40S latitude band. Expected input: Meridional wind """ # Read data dset_in = xarray.open_dataset(ifile) gio.check_xarrayDataset(dset_in, var_id) # Calculate index darray = dset_in[var_id].sel(latitude=slice(-70, -40)) units = darray.attrs['units'] darray = (darray**2)**0.5 # absolute value mi_timeseries = darray.mean(dim=['latitude', 'longitude']) # Write output file d = {} d['time'] = darray['time'] d['pwi'] = (['time'], mi_timeseries.values) dset_out = xarray.Dataset(d) dset_out['pwi'].attrs = { 'long_name': 'meridional_wind_index', 'standard_name': 'meridional_wind_index', 'units': units, 'notes': 'Average amplitude of meridional wind over 70S to 40S' } gio.set_global_atts(dset_out, dset_in.attrs, {ifile: dset_in.attrs['history']}) dset_out.to_netcdf(ofile, format='NETCDF3_CLASSIC')
def calc_asl(ifile, var_id, ofile): """Calculate the Amundsen Sea Low index. Ref: Turner et al (2013). The Amundsen Sea Low. International Journal of Climatology. 33(7), 1818-1829 doi:10.1002/joc.3558. Expected input: Mean sea level pressure data. Concept: Location and value of minimum MSLP is the region bounded by 60-75S and 180-310E. """ # Read data dset_in = xarray.open_dataset(ifile) gio.check_xarrayDataset(dset_in, var_id) south_lat, north_lat, west_lon, east_lon = gio.regions['asl'] darray = dset_in[var_id].sel(latitude=slice(south_lat, north_lat), longitude=slice(west_lon, east_lon)) assert darray.dims == ('time', 'latitude', 'longitude'), \ "Order of the data must be time, latitude, longitude" # Get axis information lat_values = darray['latitude'].values lon_values = darray['longitude'].values lats, lons = uconv.coordinate_pairs(lat_values, lon_values) # Reshape data ntimes, nlats, nlons = darray.values.shape darray_reshaped = numpy.reshape(darray.values, (ntimes, nlats * nlons)) # Get the ASL index info (min value for each timestep and its lat/lon) min_values = numpy.amin(darray_reshaped, axis=1) min_indexes = numpy.argmin(darray_reshaped, axis=1) min_lats = numpy.take(lats, min_indexes) min_lons = numpy.take(lons, min_indexes) # Write the output file d = {} d['time'] = darray['time'] d['asl_value'] = (['time'], min_values) d['asl_lat'] = (['time'], min_lats) d['asl_lon'] = (['time'], min_lons) dset_out = xarray.Dataset(d) ref = 'Ref: Turner et al (2013). Int J Clim. 33, 1818-1829. doi:10.1002/joc.3558.' dset_out['asl_value'].attrs = { 'long_name': 'asl_minimum_pressure', 'standard_name': 'asl_minimum_pressure', 'units': 'Pa', 'notes': ref } dset_out['asl_lat'].attrs = { 'long_name': 'asl_latitude', 'standard_name': 'asl_latitude', 'units': 'degrees_north', 'notes': ref } dset_out['asl_lon'].attrs = { 'long_name': 'asl_longitude', 'standard_name': 'asl_longitude', 'units': 'degrees_east', 'notes': ref } gio.set_global_atts(dset_out, dset_in.attrs, {ifile: dset_in.attrs['history']}) dset_out.to_netcdf(ofile, format='NETCDF3_CLASSIC')