def scmdf_to_emissions(scmdf, include_cfcs=True, startyear=1765, endyear=2100): """ Opens an ScmDataFrame and extracts the data. Interpolates linearly between non-consecutive years in the SCEN file. Fills in chlorinated gases from a specified SSP scenario. Note this is a temporary fix for FaIR 1.6. Inputs: scmdf: ScmDataFrame Keywords: include_cfcs: bool MAGICC files do not come loaded with CFCs (indices 24-39). - if True, use the values from RCMIP for SSPs (all scenarios are the same). - Use False to ignore and create a 23-species emission file. startyear: First year of output file. endyear: Last year of output file. Returns: nt x 40 numpy emissions array (nt x 23 if ``include_cfcs`` is ``False``) """ # We expect that aeneris and silicone are going to give us a nicely # formatted ScmDataFrame with all 23 species present and correct at # timesteps 2015, 2020 and ten-yearly to 2100. # We also implicitly assume that data up until 2014 will follow SSP # historical. # This adapter will not be tested on anything else! n_cols = 40 nt = endyear - startyear + 1 data_out = np.ones((nt, n_cols)) * np.nan data_out[:, 0] = np.arange(startyear, endyear + 1) if not has_scmdata: raise ImportError( "This is not going to work without having scmdata installed") if not isinstance(scmdf, ScmDataFrame): raise TypeError("scmdf must be an scmdata.ScmDataFrame instance") if not include_cfcs: raise NotImplementedError("include_cfcs equal to False") if scmdf[["model", "scenario"]].drop_duplicates().shape[0] != 1: raise AssertionError("Should only have one model-scenario pair") scen_start_year = 2015 scmdf = ScmRun(scmdf.timeseries()).interpolate( [dt.datetime(y, 1, 1) for y in range(scen_start_year, endyear + 1)]) years = scmdf["year"].values first_scenyear = years[0] first_scen_row = int(first_scenyear - startyear) # if correct units and interpolation were guaranteed we could do this for scenario too which is quicker hist_df = ssp245_world_emms_holder.values_fair_units.filter( year=range(startyear, 2015)).timeseries() future_ssp245_df = ssp245_world_emms_holder.values_fair_units.filter( year=range(2015, endyear + 1)).timeseries() for species in EMISSIONS_SPECIES_UNITS_CONTEXT["species"]: fair_col, _, _ = _get_fair_col_unit_context(species) hist_df_row = hist_df.index.get_level_values("variable").str.endswith( species) data_out[:first_scen_row, fair_col] = hist_df[hist_df_row].values.squeeze() future_ssp245_df_row = future_ssp245_df.index.get_level_values( "variable").str.endswith(species) data_out[first_scen_row:, fair_col] = future_ssp245_df[ future_ssp245_df_row].values.squeeze() for var_df in scmdf.groupby("variable"): variable = var_df.get_unique_meta("variable", no_duplicates=True) in_unit = var_df.get_unique_meta("unit", no_duplicates=True) fair_col, fair_unit, context = _get_fair_col_unit_context(variable) if in_unit != fair_unit: var_df_fair_unit = var_df.convert_unit(fair_unit, context=context) else: var_df_fair_unit = var_df data_out[first_scen_row:, fair_col] = var_df_fair_unit.values.squeeze() return data_out
def test_plumeplot_values(plumeplot_scmrun, quantiles_plumes, time_axis, linewidth): mock_ax = MagicMock() palette = {"a_model": "tab:blue", "a_model_2": "tab:red"} dashes = {"a_scenario": "-", "a_scenario_2": "--"} quantiles = [v for qv in quantiles_plumes for v in qv[0]] summary_stats = ScmRun( plumeplot_scmrun.quantiles_over("ensemble_member", quantiles=quantiles) ) summary_stats.plumeplot( ax=mock_ax, quantiles_plumes=quantiles_plumes, pre_calculated=True, hue_var="climate_model", palette=palette, style_var="scenario", dashes=dashes, time_axis=time_axis, linewidth=linewidth, ) xaxis = summary_stats.timeseries(time_axis=time_axis).columns.tolist() def _is_in_calls(call_to_check, call_args_list): pargs_to_check = call_to_check[1] kargs_to_check = call_to_check[2] in_call = False for ca in call_args_list: pargs = ca[0] pargs_match = True for i, p in enumerate(pargs): if isinstance(p, np.ndarray): if not np.allclose(p, pargs_to_check[i]): pargs_match = False else: if not p == pargs_to_check[i]: pargs_match = False if not pargs_match: print(p) print(pargs_to_check[i]) kargs = ca[1] if pargs_match and kargs == kargs_to_check: in_call = True return in_call def _get_with_empty_check(idf_filtered): if idf_filtered.empty: raise ValueError("Empty") return idf_filtered.values.squeeze() def _make_fill_between_call(idf, cm, scen, quant_alpha): quantiles = quant_alpha[0] alpha = quant_alpha[1] return call( xaxis, _get_with_empty_check( idf.filter(climate_model=cm, scenario=scen, quantile=quantiles[0]) ), _get_with_empty_check( idf.filter(climate_model=cm, scenario=scen, quantile=quantiles[1]) ), alpha=alpha, color=palette[cm], label="{:.0f}th - {:.0f}th".format(quantiles[0] * 100, quantiles[1] * 100), ) def _make_plot_call(idf, cm, scen, quant_alpha): quantiles = quant_alpha[0] alpha = quant_alpha[1] return call( xaxis, _get_with_empty_check( idf.filter(climate_model=cm, scenario=scen, quantile=quantiles[0]) ), color=palette[cm], linestyle=dashes[scen], linewidth=linewidth, label="{:.0f}th".format(quantiles[0] * 100), alpha=alpha, ) cm_scen_combos = summary_stats.meta[["climate_model", "scenario"]].drop_duplicates() cm_scen_combos = [v[1].values.tolist() for v in cm_scen_combos.iterrows()] plume_qa = [q for q in quantiles_plumes if len(q[0]) == 2] fill_between_calls = [ _make_fill_between_call(summary_stats, cm, scen, qa) for cm, scen in cm_scen_combos for qa in plume_qa ] # debug by looking at mock_ax.fill_between.call_args_list assert all( [ _is_in_calls(c, mock_ax.fill_between.call_args_list) for c in fill_between_calls ] ) line_qa = [q for q in quantiles_plumes if len(q[0]) == 1] plot_calls = [ _make_plot_call(summary_stats, cm, scen, qa) for cm, scen in cm_scen_combos for qa in line_qa ] # debug by looking at mock_ax.plot.call_args_list assert all([_is_in_calls(c, mock_ax.plot.call_args_list) for c in plot_calls])