def _write_magicc_input_files( # pylint:disable=too-many-arguments,too-many-locals openscmdf, time_id, outfile_dir, symlink_dir, force, metadata, header, timeseriestype, ): try: var_to_write = openscmdf["variable"].unique()[0] variable_abbreviations = { "filename": var_to_write, "magicc_name": _MAGICC_VARIABLE_MAP[var_to_write][0], "magicc_internal_name": _MAGICC_VARIABLE_MAP[var_to_write][1], } except KeyError: raise KeyError( "I don't know which MAGICC variable to use for input `{}`".format( var_to_write)) region_filters = { "FOURBOX": [ "World|Northern Hemisphere|Land", "World|Southern Hemisphere|Land", "World|Northern Hemisphere|Ocean", "World|Southern Hemisphere|Ocean", ], "GLOBAL": ["World"], } for region_key, regions_to_keep in region_filters.items(): out_file = os.path.join( outfile_dir, (("{}_{}_{}_{}_{}_{}_{}.IN").format( variable_abbreviations["filename"], openscmdf["scenario"].unique()[0], openscmdf["climate_model"].unique()[0], openscmdf["member_id"].unique()[0], time_id, region_key, variable_abbreviations["magicc_internal_name"], ).upper()), ) symlink_file = os.path.join(symlink_dir, os.path.basename(out_file)) if _skip_file(out_file, force, symlink_dir): return writer = MAGICCData(openscmdf).filter(region=regions_to_keep) writer["todo"] = "SET" writer["variable"] = variable_abbreviations["magicc_name"] writer.metadata = metadata writer.metadata["header"] = header writer.metadata["timeseriestype"] = timeseriestype logger.info("Writing file to %s", out_file) writer.write(out_file, magicc_version=7) logger.info("Making symlink to %s", symlink_file) os.symlink(out_file, symlink_file)
def _write_mag_file( # pylint:disable=too-many-arguments openscmdf, metadata, header, outfile_dir, symlink_dir, fnames, force): out_file = os.path.join(outfile_dir, fnames[0]) out_file = "{}.MAG".format(os.path.splitext(out_file)[0]) if _skip_file(out_file, force, symlink_dir): return writer = MAGICCData(openscmdf) writer["todo"] = "SET" time_steps = writer.timeseries().columns[1:] - writer.timeseries( ).columns[:-1] step_upper = np.timedelta64(32, "D") # pylint:disable=too-many-function-args step_lower = np.timedelta64(28, "D") # pylint:disable=too-many-function-args if any((time_steps > step_upper) | (time_steps < step_lower)): raise ValueError("Please raise an issue at " "github.com/znicholls/netcdf-scm/issues " "to discuss how to handle non-monthly data wrangling") writer.metadata = metadata writer.metadata["timeseriestype"] = "MONTHLY" writer.metadata["header"] = header logger.info("Writing file to %s", out_file) writer.write(out_file, magicc_version=7) symlink_file = os.path.join(symlink_dir, os.path.basename(out_file)) logger.info("Making symlink to %s", symlink_file) os.symlink(out_file, symlink_file)
def test_pymagicc_writing_has_an_effect( package, test_filename, relevant_config, outputs_to_check, time_check_min, time_check_max, ): if (package.version == 6) and test_filename.endswith("SCEN7"): # maybe this should throw error instead pytest.skip("MAGICC6 cannot run SCEN7 files") if ("SRES" in test_filename) and (package.version == 7): # maybe this should throw error instead pytest.skip("MAGICC7 cannot run SRES SCEN files") if ("SCEN" in test_filename) and (package.version == 7): # special undocumented flags!!! relevant_config["fgas_adjstfutremis2past_0no1scale"] = 0 relevant_config["mhalo_adjstfutremis2past_0no1scale"] = 0 for key, value in relevant_config.items(): if value == "test_filename": relevant_config[key] = test_filename package.set_config(**relevant_config) initial_results = package.run() ttweak_factor = 0.9 mdata = MAGICCData( join(package.run_dir, test_filename), columns={ "model": ["unspecified"], "scenario": ["unspecified"] }, ) mdata._data *= ttweak_factor mdata.write(join(package.run_dir, test_filename), package.version) tweaked_results = package.run() for output_to_check in outputs_to_check: result = (tweaked_results.filter( variable=output_to_check, year=range(time_check_min, time_check_max + 1)).timeseries().values) expected = (ttweak_factor * initial_results.filter( variable=output_to_check, year=range(time_check_min, time_check_max + 1)).timeseries().values) abstol = np.max([result, expected]) * 10**-3 np.testing.assert_allclose(result, expected, rtol=1e-5, atol=abstol)
def test_external_forcing_only_run(package): time = zero_emissions["time"] forcing_external = 2.0 * np.arange(0, len(time)) / len(time) forcing_ext = MAGICCData( forcing_external, columns={ "index": time, "scenario": ["idealised"], "model": ["unspecified"], "climate_model": ["unspecified"], "variable": ["Radiative Forcing|Extra"], "unit": ["W / m^2"], "todo": ["SET"], "region": ["World"], }, ) forcing_ext_filename = "EXTERNAL_RF.IN" forcing_ext.metadata = { "header": "External radiative forcing file for testing" } forcing_ext.write(join(package.run_dir, forcing_ext_filename), package.version) results = package.run( rf_extra_read=1, file_extra_rf=forcing_ext_filename, rf_total_runmodus="QEXTRA", endyear=max(time).year, rf_initialization_method= "ZEROSTARTSHIFT", # this is default but just in case rf_total_constantafteryr=5000, ) # MAGICC's weird last year business means that last result is just constant from previous # year and is not treated properly # TODO: add this in docs validation_output = (results.filter( variable="Radiative Forcing", region="World").timeseries().values.squeeze()[:-1]) validation_input = forcing_external[:-1] np.testing.assert_allclose(validation_input, validation_output, rtol=1e-5) temperature_global = (results.filter( variable="Surface Temperature", region="World").timeseries().values.squeeze()) assert (temperature_global[1:] - temperature_global[:-1] >= 0).all()
def test_run_rewritten_scen_file(package, temp_dir): starting_scen = join(MAGICC6_DIR, "RCP26.SCEN") written_scen = join(package.run_dir, "RCP26.SCEN7") cols = { "model": ["IMAGE"], "scenario": ["RCP26"], "climate_model": ["MAGICC6"] } mdata_initial = MAGICCData(starting_scen, columns=cols) mdata_initial.write(written_scen, magicc_version=7) mdata_written = MAGICCData(written_scen, columns=cols) results = package.run(mdata_written, only=["Surface Temperature"]) assert len(results["variable"].unique()) == 1 assert "Surface Temperature" in results["variable"].values
def _write_mag_file_with_operation( # pylint:disable=too-many-arguments openscmdf, metadata, header, outfile_dir, symlink_dir, fnames, force, out_format): # pylint:disable=too-many-locals if len(fnames) > 1: raise AssertionError("more than one file to wrangle?" ) # pragma: no cover # emergency valve ts = openscmdf.timeseries() src_time_points = ts.columns original_years = ts.columns.map(lambda x: x.year).unique() time_id = "{}-{}".format(src_time_points[0].year, src_time_points[-1].year) regex_search = r"{:04d}\d*-{:04d}\d*".format(src_time_points[0].year, src_time_points[-1].year) old_time_id = re.search(regex_search, fnames[0]).group(0) out_file = os.path.join(outfile_dir, fnames[0].replace(old_time_id, time_id)) out_file = "{}.MAG".format(os.path.splitext(out_file)[0]) if _skip_file(out_file, force, symlink_dir): return writer = MAGICCData(_do_timeseriestype_operation( openscmdf, out_format)).filter(year=original_years) writer["todo"] = "SET" writer.metadata = metadata writer.metadata["timeseriestype"] = (out_format.replace( "mag-files-", "").replace("-", "_").upper()) writer.metadata["header"] = header logger.info("Writing file to %s", out_file) writer.write(out_file, magicc_version=7) symlink_file = os.path.join(symlink_dir, os.path.basename(out_file)) logger.info("Making symlink to %s", symlink_file) os.symlink(out_file, symlink_file)
"""A simple script that can be used to read and write a file to see the effects of the formatting without having to always stop and debug tests """ import os from os.path import join, expanduser from pymagicc.io import MAGICCData here = os.path.dirname(os.path.abspath(__file__)) fpath = join(here, "..", "pymagicc", "MAGICC6", "run") fname = "RCP26.SCEN" mi_writer = MAGICCData() mi_writer.read(filepath=fpath, filename=fname) mi_writer.write(join(expanduser("~"), fname))
def test_co2_emms_other_rf_run(package, emms_co2_level): package.set_zero_config() df = zero_emissions.timeseries() time = zero_emissions["time"] emms_fossil_co2 = np.zeros(len(time)) emms_fossil_co2[20:] = emms_co2_level df.loc[( df.index.get_level_values("variable") == "Emissions|CO2|MAGICC Fossil and Industrial"), :, ] = emms_fossil_co2 scen = MAGICCData(df) forcing_external = 2.0 * np.arange(0, len(time)) / len(time) forcing_ext = MAGICCData( forcing_external, columns={ "index": time, "scenario": ["idealised"], "model": ["unspecified"], "climate_model": ["unspecified"], "variable": ["Radiative Forcing|Extra"], "unit": ["W / m^2"], "todo": ["SET"], "region": ["World"], }, ) forcing_ext.metadata = { "header": "External radiative forcing file for testing" } forcing_ext_filename = "EXTERNAL_RF.IN" forcing_ext.write(join(package.run_dir, forcing_ext_filename), package.version) # TODO: fix endyear so it takes from scenario input by default results = package.run( scen, endyear=max(time).year, rf_extra_read=1, # fix writing of 'True' file_extra_rf=forcing_ext_filename, rf_total_runmodus="all", rf_initialization_method="ZEROSTARTSHIFT", rf_total_constantafteryr=5000, ) np.testing.assert_allclose( results.filter(variable="Em*CO2*Fossil*", region="World").timeseries().values.squeeze(), emms_fossil_co2, ) # CO2 temperature feedbacks mean that you get a CO2 outgassing, hence CO2 forcing. As a # result radiative forcing values don't match exactly. Numerical precision adds to this. ext_rf_output_vals = (results.filter( variable="Radiative Forcing", region="World").timeseries().values.squeeze()) zero_rows = (forcing_external == 0) & (ext_rf_output_vals == 0) greater_equal_rows = ext_rf_output_vals >= forcing_external close_rows_denominator = forcing_external close_rows_denominator[zero_rows] = 10**-10 # avoid divide by zero close_rows = (np.abs(ext_rf_output_vals - forcing_external) / close_rows_denominator <= 10**-3) matching_rows = greater_equal_rows | close_rows assert matching_rows.all()
def test_pymagicc_writing_has_an_effect( package, test_filename, relevant_config, outputs_to_check, time_check_min, time_check_max, ): if ("SCEN" in test_filename) and (package.version == 7): # special undocumented flags!!! relevant_config["fgas_adjstfutremis2past_0no1scale"] = 0 relevant_config["mhalo_adjstfutremis2past_0no1scale"] = 0 iter_dict = copy.deepcopy(relevant_config) for key, value in iter_dict.items(): if value == "test_filename": relevant_config[key] = test_filename # Handle adjustment to `.prn` handling in MAGICC if key == "file_mhalo_emis" and package.version == 7: relevant_config["mhalo_prnfile_emis"] = relevant_config.pop(key) relevant_config["mhalo_take_prnfile"] = 1 if key == "file_mhalo_conc" and package.version == 7: relevant_config["mhalo_prnfile_conc"] = relevant_config.pop(key) relevant_config["mhalo_take_prnfile"] = 1 package.set_config(conflict="ignore", **relevant_config) if (package.version == 6) and test_filename.endswith("SCEN7"): error_msg = re.compile("MAGICC6 cannot run SCEN7 files") with pytest.raises(ValueError, match=error_msg): package.run(only=outputs_to_check) return if ("SRES" in test_filename) and (package.version == 7): # MAGICC7 cannot run SRES SCEN files with pytest.raises(CalledProcessError): package.run(only=outputs_to_check) return if ".prn" in test_filename and package.version == 7: # MAGICC7's prn handling is not working with pytest.raises(CalledProcessError): package.run(only=outputs_to_check) return initial_results = package.run(only=outputs_to_check) ttweak_factor = 0.9 mdata = MAGICCData( join(package.run_dir, test_filename), columns={ "model": ["unspecified"], "scenario": ["unspecified"] }, ) mdata._data *= ttweak_factor mdata.write(join(package.run_dir, test_filename), package.version) tweaked_results = package.run(only=outputs_to_check) for output_to_check in outputs_to_check: result = (tweaked_results.filter( variable=output_to_check, year=range(time_check_min, time_check_max + 1)).timeseries().values) initial = (initial_results.filter( variable=output_to_check, year=range(time_check_min, time_check_max + 1)).timeseries().values) expected = ttweak_factor * initial abstol = np.max([result, expected]) * 10**-3 np.testing.assert_allclose(result, expected, rtol=1e-5, atol=abstol)