def main(cfg): """Run the diagnostic. Parameters ---------- cfg : dict Configuration dictionary of the recipe. """ # Get dataset and variable information logging.debug("Found datasets in recipe:\n%s", diag.Datasets(cfg)) logging.debug("Found variables in recipe:\n%s", diag.Variables(cfg)) # Check for correct variables if not diag.Variables(cfg).vars_available('pr', 'mrro', 'evspsbl'): raise ValueError( "Diagnostic requires precipitation, runoff and evaporation data") # Read catchmentmask # to check: Correct way to read auxillary data using recipes? my_catch = get_catchment_data(cfg) # Read data, convert units and compute long term means # to check: Shouldn't this be part of preprocessing? # to check: How to regrid onto catchment_cube grid # with preproc recipe statements # instead of using regrid here? allcubes = {} plotdata = {} for datapath in diag.Datasets(cfg): # Get simulation data var, identifier, cube = get_sim_data(cfg, datapath, my_catch['cube']) # Get river catchment averages rivervalues = get_catch_avg(my_catch, cube) # Sort into data dictionaries datainfo = diag.Datasets(cfg).get_dataset_info(path=datapath) model = datainfo['dataset'] if model == datainfo.get('reference_dataset', None): update_reference(my_catch, model, rivervalues, var) else: update_plotdata(identifier, plotdata, rivervalues, var) # Append to cubelist for temporary output if model not in allcubes.keys(): allcubes[model] = [] allcubes[model].append(cube) # Write regridded and temporal aggregated netCDF data files (one per model) # to do: update attributes, something fishy with unlimited dimension for model, mcube in allcubes.items(): filepath = os.path.join(cfg[diag.names.WORK_DIR], '_'.join(['postproc', model]) + '.nc') if cfg[diag.names.WRITE_NETCDF]: iris.save(mcube, filepath) logger.info("Writing %s", filepath) # Write plotdata as ascii files for user information write_plotdata(cfg, plotdata, my_catch) # Plot catchment data make_catchment_plots(cfg, plotdata, my_catch)
def main(cfg): """Compute the time average for each input dataset.""" datasets = e.Datasets(cfg) variables = e.Variables(cfg) logger.debug("Found datasets: %s", datasets) logger.debug("Found variables: %s", variables) for path in datasets: logger.info("Processing variable %s from dataset %s", datasets.get_info(n.STANDARD_NAME, path), datasets.get_info(n.DATASET, path)) logger.debug("Loading %s", path) cube = iris.load_cube(path) logger.debug("Running example computation") cube = cube.collapsed(n.TIME, iris.analysis.MEAN) name = os.path.splitext(os.path.basename(path))[0] + '_mean' if cfg[n.WRITE_NETCDF]: filepath = os.path.join(cfg[n.WORK_DIR], name + '.nc') logger.debug("Saving analysis results to %s", filepath) iris.save(cube, target=filepath) if cfg[n.WRITE_PLOTS] and cfg.get('quickplot'): filepath = os.path.join(cfg[n.PLOT_DIR], name + '.' + cfg[n.OUTPUT_FILE_TYPE]) logger.debug("Plotting analysis results to %s", filepath) e.plot.quickplot(cube, filename=filepath, **cfg['quickplot'])
def focus2model(cfg, lcdata, refset): """Resort lcdata for model focus. Parameters ---------- cfg : dict Configuration dictionary of the recipe. lcdata : dict collection of land cover values per region refset : dict reference dataset names for all variables. """ var = diag.Variables(cfg).short_names()[0] shuffle = {key: {} for key in lcdata[var]['groups']['area']} for dset in shuffle.keys(): ids = lcdata[var]['groups']['area'].index(dset) if refset[var] in dset: shuffle[dset] = { 'groups': { 'area': [], 'frac': [] }, 'values': { 'area': [], 'frac': [] } } else: shuffle[dset] = { 'groups': { 'area': [], 'frac': [], 'bias': [] }, 'values': { 'area': [], 'frac': [], 'bias': [] } } for var in sorted(diag.Variables(cfg).short_names()): for metric in shuffle[dset]['groups'].keys(): shuffle[dset]['groups'][metric].append(var) shuffle[dset]['values'][metric].append( lcdata[var]['values'][metric][ids]) lcdata = shuffle
def main(cfg): """Run the diagnostic. Parameters ---------- cfg : dict Configuration dictionary of the recipe. """ # Print dataset and variable information logging.debug("Found datasets in recipe:\n%s", diag.Datasets(cfg)) logging.debug("Found variables in recipe:\n%s", diag.Variables(cfg)) # Get metadata information grouped_input_data = diag.group_metadata(cfg['input_data'].values(), 'standard_name', sort='dataset') # Prepare dictionaries timcubes = { 'exp': {key: [] for key in diag.Variables(cfg).short_names()}, 'ref': {key: [] for key in diag.Variables(cfg).short_names()} } lcdata = {key: {} for key in diag.Variables(cfg).short_names()} refset = {} prov_rec = {key: {} for key in diag.Variables(cfg).short_names()} # Read data and compute long term means for standard_name in grouped_input_data: for attributes in grouped_input_data[standard_name]: get_timmeans(attributes, timcubes, refset, prov_rec) for var in diag.Variables(cfg).short_names(): # Write regridded and temporal aggregated netCDF data files write_data(cfg, timcubes, var, prov_rec) # Compute aggregated and fraction average land cover regnam = compute_landcover(var, lcdata, timcubes['exp'][var] + timcubes['ref'][var]) # Reshuffle data if models are the comparison target if cfg.get('comparison', 'variable') == 'model': focus2model(cfg, lcdata, refset) prov_rec = None elif cfg.get('comparison', 'variable') != 'variable': raise ValueError('Only variable or model are valid comparison targets') # Output ascii files and plots for target in lcdata.keys(): # Write plotdata as ascii files for user information infos = [cfg, regnam, prov_rec, target] write_plotdata(infos, lcdata[target]['groups'], lcdata[target]['values']) # Plot area values make_landcover_bars(cfg, regnam, lcdata[target]['groups'], lcdata[target]['values'], target)
def get_sim_data(cfg, datapath, catchment_cube): """Read and postprocess netcdf data from experiments. Check units, aggregate to long term mean yearly sum and regrid to resolution of catchment mask. Parameters ---------- cfg : dict Configuration dictionary of the recipe. dataset_path : str Path to the netcdf file catchment_cube : obj iris cube object containing simulation data """ datainfo = diag.Datasets(cfg).get_dataset_info(path=datapath) identifier = "_".join( [datainfo['dataset'].upper(), datainfo['exp'], datainfo['ensemble']]) # Load data into iris cube new_cube = iris.load(datapath, diag.Variables(cfg).standard_names())[0] # Check for expected unit if new_cube.units != 'kg m-2 s-1': raise ValueError('Unit [kg m-2 s-1] is expected for ', new_cube.long_name.lower(), ' flux') # Convert to unit mm per month timelist = new_cube.coord('time') daypermonth = [] for mydate in timelist.units.num2date(timelist.points): daypermonth.append(calendar.monthrange(mydate.year, mydate.month)[1]) new_cube.data *= 86400.0 for i, days in enumerate(daypermonth): new_cube.data[i] *= days # Aggregate over year --> unit mm per year iris.coord_categorisation.add_year(new_cube, 'time') year_cube = new_cube.aggregated_by('year', iris.analysis.SUM) year_cube.units = "mm a-1" # Compute long term mean mean_cube = year_cube.collapsed([diag.names.TIME], iris.analysis.MEAN) # Regrid to catchment data grid --> maybe use area_weighted instead? if mean_cube.coord('latitude').bounds is None: mean_cube.coord('latitude').guess_bounds() if mean_cube.coord('longitude').bounds is None: mean_cube.coord('longitude').guess_bounds() m_grid = [iris.analysis.Linear(), iris.analysis.AreaWeighted()] mean_cube_regrid = mean_cube.regrid(catchment_cube, m_grid[1]) return datainfo['short_name'], identifier, mean_cube_regrid
def main(cfg): """Run the diagnostic.""" ########################################################################### # Read recipe data ########################################################################### # Dataset data containers data = e.Datasets(cfg) logging.debug("Found datasets in recipe:\n%s", data) # Variables var = e.Variables(cfg) logging.debug("Found variables in recipe:\n%s", var) # Check for tas and rlnst if not var.vars_available('pr', 'ua', 'va', 'ts'): raise ValueError("This diagnostic needs 'pr', 'ua', " + " 'va', and 'ts'") available_exp = list(group_metadata(cfg['input_data'].values(), 'exp')) if 'historical' not in available_exp: raise ValueError("The diagnostic needs an historical experiment " + " and one other experiment.") if len(available_exp) != 2: raise ValueError("The diagnostic needs an two model experiments: " + " onehistorical and one other one.") available_exp.remove('historical') future_exp = available_exp[0] ########################################################################### # Read data ########################################################################### # Create iris cube for each dataset and save annual means for dataset_path in data: cube = iris.load(dataset_path)[0] cat.add_month_number(cube, 'time', name='month_number') # MJJAS mean (monsoon season) cube = cube[np.where( np.absolute(cube.coord('month_number').points - 7) <= 2)] cube = cube.collapsed('time', iris.analysis.MEAN) short_name = data.get_info(n.SHORT_NAME, dataset_path) if short_name == 'pr': # convert from kg m-2 s-1 to mm d-1 # cube.convert_units('mm d-1') doesn't work. cube.data = cube.data * (60.0 * 60.0 * 24.0) cube.units = 'mm d-1' # Possible because all data must be interpolated to the same grid. if 'lats' not in locals(): lats = cube.coord('latitude').points lons = cube.coord('longitude').points data.set_data(cube.data, dataset_path) ########################################################################### # Process data ########################################################################### data_ar = substract_li(cfg, data, lats, lons, future_exp) # data_ar {"datasets": datasets, "ar_diff_rain": ar_diff_rain, # "ar_diff_ua": ar_diff_ua, "ar_diff_va": ar_diff_va, # "ar_hist_rain": ar_hist_rain, "mism_diff_rain": mism_diff_rain, # "mwp_hist_rain": mwp_hist_rain} plot_rain_and_wind(cfg, 'Multi-model_mean', {'ar_diff_rain': data_ar["ar_diff_rain"], 'ar_diff_ua': data_ar["ar_diff_ua"], 'ar_diff_va': data_ar["ar_diff_va"], 'lats': lats, 'lons': lons}, future_exp) # Regression between mean ISM rain difference and historical rain reg2d = get_reg_2d_li(data_ar["mism_diff_rain"], data_ar["ar_hist_rain"], lats, lons) plot_2dcorrelation_li(cfg, reg2d, lats, lons) plot_reg_li(cfg, data_ar, future_exp) # Regression between mean WP rain and rain difference for each location reg2d_wp = get_reg_2d_li(data_ar["mwp_hist_rain"], data_ar["ar_diff_rain"], lats, lons) data_ar2 = correct_li(data_ar, lats, lons, reg2d_wp) # return {"datasets": data["datasets"], "ar_diff_cor": ar_diff_cor, # "proj_err": proj_err, "mism_diff_cor": mism_diff_cor, # "mism_hist_rain": mism_hist_rain, "mwp_hist_cor": mwp_hist_cor} plot_reg_li2(cfg, data_ar["datasets"], data_ar["mism_diff_rain"], data_ar2["mism_diff_cor"], data_ar2["mism_hist_rain"]) plot_rain(cfg, 'Multi-model mean rainfall change due to model error', np.mean(data_ar2["proj_err"], axis=2), lats, lons) plot_rain(cfg, 'Corrected multi-model mean rainfall change', np.mean(data_ar2["ar_diff_cor"], axis=2), lats, lons)
def main(cfg): """Run the diagnostic. Parameters : ---------- cfg : dict Configuration dictionary of the recipe. """ ########################################################################### # Read recipe data ########################################################################### # Dataset data containers data = e.Datasets(cfg) logging.debug("Found datasets in recipe:\n%s", data) # Variables var = e.Variables(cfg) # logging.debug("Found variables in recipe:\n%s", var) available_vars = list( group_metadata(cfg['input_data'].values(), 'short_name')) logging.debug("Found variables in recipe:\n%s", available_vars) available_exp = list(group_metadata(cfg['input_data'].values(), 'exp')) # Check for available variables required_vars = ('tas', 'lvp', 'rlnst', 'rsnst', 'rlnstcs', 'rsnstcs', 'hfss') if not e.variables_available(cfg, required_vars): raise ValueError("This diagnostic needs {required_vars} variables") # Check for experiments if 'abrupt-4xCO2' not in available_exp: if 'abrupt4xCO2' not in available_exp: raise ValueError("The diagnostic needs an experiment with " + "4 times CO2.") if 'piControl' not in available_exp: raise ValueError("The diagnostic needs a pre industrial control " + "experiment.") ########################################################################### # Read data ########################################################################### # Create iris cube for each dataset and save annual means for dataset_path in data: cube = iris.load(dataset_path)[0] cat.add_year(cube, 'time', name='year') cube = cube.aggregated_by('year', iris.analysis.MEAN) experiment = data.get_info(n.EXP, dataset_path) if experiment == PICONTROL: # DeAngelis use a 21 year running mean on piControl but the # full extend of 150 years abrupt4xCO2. I could not find out, # how they tread the edges, currently I just skip the mean for # the edges. This is not exacly the same as done in the paper, # small differences remain in extended data Fig 1, # but closer than other methods I # tried, e.g. skipping the edges. # For most data sets it would be also possible to # extend the piControl for 20 years, but then it would # not be centered means of piControl for each year of # abrupt4xCO2 any more. cube_new = cube.rolling_window('time', iris.analysis.MEAN, 21) endm10 = len(cube.coord('time').points) - 10 cube.data[10:endm10] = cube_new.data data.set_data(cube.data, dataset_path) ########################################################################### # Process data ########################################################################### data_dict = substract_and_reg_deangelis2(cfg, data, var) plot_slope_regression(cfg, data_dict) plot_slope_regression_all(cfg, data_dict, available_vars)