def test_dir_aerosols(variable, suffix_part_1, suffix): no_prefix_variable = ["BIOMASSAER", "MINERALDUST"] if variable in no_prefix_variable: # Ignoring the prefix openscm_var = convert_magicc7_to_openscm_variables( "{}_{}".format(variable, suffix) ) else: openscm_var = convert_magicc7_to_openscm_variables( "{}{}_{}".format(variable, suffix_part_1, suffix) ) assert "Aerosols|Direct Effect" in openscm_var if suffix == "RF": assert openscm_var.startswith("Radiative Forcing") elif suffix == "ERF": assert openscm_var.startswith("Effective Radiative Forcing") openscm_var_name = variable if variable != "SOX" else "SOx" if variable not in no_prefix_variable: if suffix_part_1 == "I": assert openscm_var.endswith("MAGICC Fossil and Industrial") assert "|{}|".format(openscm_var_name) in openscm_var elif suffix_part_1 == "B": assert openscm_var.endswith("MAGICC AFOLU") assert "|{}|".format(openscm_var_name) in openscm_var else: assert openscm_var.endswith(openscm_var_name)
def test_convert_openscm_to_magicc7_variables(magicc7, openscm): assert convert_magicc7_to_openscm_variables(openscm, inverse=True) == magicc7 # OpenSCM variables are case sensitive hence this should warn pytest.xfail("Warnings are turned off") msg = "No substitution available for {'" + "{}".format(openscm.upper()) + "'}" with warnings.catch_warnings(record=True) as warn_result: convert_magicc7_to_openscm_variables(openscm.upper(), inverse=True) assert len(warn_result) == 1 assert str(warn_result[0].message) == msg
def _get_column_headers_and_update_metadata(self, stream, metadata): units = self._read_data_header_line(stream, "UNITS:") variables = convert_magicc7_to_openscm_variables( convert_magicc6_to_magicc7_variables( self._read_data_header_line(stream, "YEARS:") ) ) column_headers = { "variable": variables, "todo": [self._default_todo_fill_value] * len(variables), "unit": units, "region": ["World"] * len(variables), } for k in ["unit", "units", "gas"]: try: metadata.pop(k) except KeyError: pass # get rid of confusing units before passing to read_units column_headers["unit"] = [ v.replace("kt/yr", "kt") for v in column_headers["unit"] ] column_headers = super()._read_units(column_headers) return column_headers, metadata
def _convert_variables_to_openscm_variables(self, rcp_variables): magicc7_vars = convert_magicc6_to_magicc7_variables(rcp_variables) # work out whether we have emissions, concentrations or radiative # forcing, I think this is the best way to do it given the stability # of the format first_var = magicc7_vars[0] if first_var == "CO2I": intermediate_vars = [m + "_EMIS" for m in magicc7_vars] elif first_var == "CO2EQ": intermediate_vars = [m + "_CONC" for m in magicc7_vars] elif first_var == "TOTAL_INCLVOLCANIC_RF": intermediate_vars = [] for m in magicc7_vars: if not m.endswith("_RF"): m = m + "_RF" intermediate_vars.append(m) elif first_var == "TOTAL_INCLVOLCANIC_ERF": intermediate_vars = [] for m in magicc7_vars: if not m.endswith("_ERF"): m = m + "_ERF" intermediate_vars.append(m) else: raise ValueError( "I don't know how you got this file, but the format is not recognised by pymagicc" ) res = convert_magicc7_to_openscm_variables(intermediate_vars) return res
def process_data(cls, reader, stream, metadata): index = np.arange(metadata["firstyear"], metadata["lastyear"] + 1) columns = {} data = [] for i in range(metadata["datacolumns"]): column_header, column_data = cls.process_variable(stream) for k in column_header: if k not in columns: columns[k] = [] columns[k].append(column_header[k]) data.append(column_data) df = pd.DataFrame(np.asarray(data).T, index=index) if isinstance(df.index, pd.core.indexes.numeric.Float64Index): df.index = df.index.to_series().round(3) df.index.name = "time" # Convert the regions to openscm regions columns["region"] = convert_magicc_to_openscm_regions(columns["region"]) # Convert the variable names to openscm variables columns["variable"] = [ d[4:] if d.startswith("DAT_") else d for d in columns["variable"] ] columns["variable"] = convert_magicc6_to_magicc7_variables(columns["variable"]) columns["variable"] = convert_magicc7_to_openscm_variables(columns["variable"]) return df, metadata, columns
def _get_initial_nml_and_data_block(self): data_block = self.data_block regions = convert_magicc_to_openscm_regions( data_block.columns.get_level_values("region").tolist(), inverse=True) regions = self._ensure_file_region_type_consistency(regions) variables = convert_magicc7_to_openscm_variables( data_block.columns.get_level_values("variable").tolist(), inverse=True) # trailing EMIS is incompatible, for now variables = [v.replace("_EMIS", "") for v in variables] units = convert_pint_to_fortran_safe_units( data_block.columns.get_level_values("unit").tolist()) todos = data_block.columns.get_level_values("todo").tolist() data_block = data_block.rename(columns=str).reset_index() data_block.columns = [ [self._variable_header_row_name] + variables, ["TODO"] + todos, ["UNITS"] + units, ["YEARS"] + regions, ] nml = Namelist() nml["THISFILE_SPECIFICATIONS"] = Namelist() nml["THISFILE_SPECIFICATIONS"]["THISFILE_DATACOLUMNS"] = ( len(data_block.columns) - 1 # for YEARS column ) nml["THISFILE_SPECIFICATIONS"]["THISFILE_DATAROWS"] = len(data_block) nml["THISFILE_SPECIFICATIONS"]["THISFILE_FIRSTYEAR"] = int( np.floor(data_block.iloc[0, 0])) nml["THISFILE_SPECIFICATIONS"]["THISFILE_LASTYEAR"] = int( np.floor(data_block.iloc[-1, 0])) step_length = data_block.iloc[1:, 0].values - data_block.iloc[:-1, 0].values try: np.testing.assert_allclose(step_length, step_length[0], rtol=0.02) step_length = step_length[0] annual_steps = np.round(1 / step_length, 1) if annual_steps < 1: annual_steps = 0 else: annual_steps = int(annual_steps) except AssertionError: annual_steps = 0 # irregular timesteps nml["THISFILE_SPECIFICATIONS"]["THISFILE_ANNUALSTEPS"] = annual_steps units_unique = list(set(self._get_df_header_row("unit"))) nml["THISFILE_SPECIFICATIONS"]["THISFILE_UNITS"] = ( convert_pint_to_fortran_safe_units(units_unique[0]) if len(units_unique) == 1 else "MISC") nml["THISFILE_SPECIFICATIONS"].update( self._get_dattype_regionmode(regions)) return nml, data_block
def read_data_block(self): number_years = int(self.lines[0].strip()) # go through datablocks until there are none left while True: ch = {} pos_block = self._stream.tell() region = convert_magicc_to_openscm_regions(self._stream.readline().strip()) try: variables = self._read_data_header_line( self._stream, ["Years", "Year", "YEARS", "YEAR"] ) except IndexError: # tried to get variables from empty string break except AssertionError: # tried to get variables from a notes line break variables = convert_magicc6_to_magicc7_variables(variables) ch["variable"] = convert_magicc7_to_openscm_variables( [v + "_EMIS" for v in variables] ) ch["unit"] = self._read_data_header_line(self._stream, ["Yrs", "YEARS"]) ch = self._read_units(ch) ch["todo"] = ["SET"] * len(variables) ch["region"] = [region] * len(variables) region_block = StringIO() for i in range(number_years): region_block.write(self._stream.readline()) region_block.seek(0) region_df = self._convert_data_block_to_df(region_block) try: df = pd.concat([region_df, df], axis="columns") columns = {key: ch[key] + columns[key] for key in columns} except NameError: df = region_df columns = ch self._stream.seek(pos_block) try: return df, columns except NameError: error_msg = ( "This is unexpected, please raise an issue on " "https://github.com/openscm/pymagicc/issues" ) raise Exception(error_msg)
def _get_column_headers_and_update_metadata(self, stream, metadata): if self._magicc7_style_header(): column_headers, metadata = self._read_magicc7_style_header( stream, metadata) else: column_headers, metadata = self._read_magicc6_style_header( stream, metadata) column_headers["variable"] = convert_magicc7_to_openscm_variables( column_headers["variable"]) column_headers["region"] = convert_magicc_to_openscm_regions( column_headers["region"]) return column_headers, metadata
def _write_header(self, output): header_lines = [] header_lines.append("{}".format(len(self.data_block))) variables = self._get_df_header_row("variable") variables = convert_magicc7_to_openscm_variables(variables, inverse=True) variables = _strip_emis_variables(variables) regions = self._get_df_header_row("region") regions = convert_magicc_to_openscm_regions(regions, inverse=True) regions = self._ensure_file_region_type_consistency(regions) special_scen_code = get_special_scen_code(regions=regions, emissions=variables) header_lines.append("{}".format(special_scen_code)) # for a scen file, the convention is (although all these lines are # actually ignored by source so could be anything): # - line 3 is name # - line 4 is description # - line 5 is notes (other notes lines go at the end) # - line 6 is empty header_lines.append("name: {}".format(self.minput["scenario"].unique()[0])) header_lines.append( "description: {}".format( self.minput.metadata.pop( "description", "metadata['description'] is written here" ) ) ) header_lines.append( "notes: {}".format( self.minput.metadata.pop("notes", "metadata['notes'] is written here") ) ) header_lines.append("") try: header_lines.append(self.minput.metadata.pop("header")) except KeyError: pass for k, v in self.minput.metadata.items(): header_lines.append("{}: {}".format(k, v)) output.write(self._newline_char.join(header_lines)) output.write(self._newline_char) return output
def _get_column_headers_and_update_metadata(self, stream, metadata): column_headers, metadata = super()._get_column_headers_and_update_metadata( stream, metadata ) tmp_vars = [] for v in column_headers["variable"]: # TODO: work out a way to avoid this fragile check and calling the # conversion once in the superclass method and again below if v.endswith("_EMIS") or v.startswith("Emissions"): tmp_vars.append(v) else: tmp_vars.append(v + "_EMIS") column_headers["variable"] = convert_magicc7_to_openscm_variables(tmp_vars) column_headers = self._read_units(column_headers) return column_headers, metadata
def test_ch4_co2_n2o(variable, prefix, suffix): openscm_var = convert_magicc7_to_openscm_variables("{}{}_{}".format( variable, prefix, suffix)) if suffix == "RF": assert openscm_var.startswith("Radiative Forcing") elif suffix == "ERF": assert openscm_var.startswith("Effective Radiative Forcing") elif suffix == "CONC": assert openscm_var.startswith("Atmospheric Concentrations") elif suffix == "OT": assert openscm_var.startswith("Optical Thickness") if prefix == "I": assert openscm_var.endswith("MAGICC Fossil and Industrial") assert "|{}|".format(variable) in openscm_var elif prefix == "B": assert openscm_var.endswith("MAGICC AFOLU") assert "|{}|".format(variable) in openscm_var else: assert openscm_var.endswith(variable)
def test_aerosols_not_rf(variable, suffix_part_1, suffix): openscm_var = convert_magicc7_to_openscm_variables("{}{}_{}".format( variable, suffix_part_1, suffix)) assert "Aerosols|Direct Effect" not in openscm_var if suffix == "CONC": assert openscm_var.startswith("Atmospheric Concentrations") elif suffix == "OT": assert openscm_var.startswith("Optical Thickness") elif suffix == "EMIS": assert openscm_var.startswith("Emissions") elif suffix == "INVERSE_EMIS": assert openscm_var.startswith("Inverse Emissions") openscm_var_name = variable if variable != "SOX" else "SOx" if suffix_part_1 == "I": assert openscm_var.endswith("MAGICC Fossil and Industrial") assert "|{}|".format(openscm_var_name) in openscm_var elif suffix_part_1 == "B": assert openscm_var.endswith("MAGICC AFOLU") assert "|{}|".format(openscm_var_name) in openscm_var else: assert openscm_var.endswith(openscm_var_name)
def _get_openscm_var_from_filepath(filepath): """ Determine the OpenSCM variable from a filepath. Uses MAGICC's internal, implicit, filenaming conventions. Parameters ---------- filepath : str Filepath from which to determine the OpenSCM variable. Returns ------- str The OpenSCM variable implied by the filepath. """ from pymagicc.io import determine_tool reader = determine_tool(filepath, "reader")(filepath) openscm_var = convert_magicc7_to_openscm_variables( convert_magicc6_to_magicc7_variables( reader._get_variable_from_filepath())) return openscm_var
def test_convert_magicc7_to_openscm_variables(magicc7, openscm): assert convert_magicc7_to_openscm_variables(magicc7) == openscm assert convert_magicc7_to_openscm_variables(magicc7.upper()) == openscm assert convert_magicc7_to_openscm_variables(magicc7.lower()) == openscm
def process_data(reader, stream, metadata): """ Extract the tabulated data from the input file # Arguments stream (Streamlike object): A Streamlike object (nominally StringIO) containing the table to be extracted metadata (dict): metadata read in from the header and the namelist # Returns df (pandas.DataFrame): contains the data, processed to the standard MAGICCData format metadata (dict): updated metadata based on the processing performed """ index = np.arange(metadata["firstyear"], metadata["lastyear"] + 1) # The first variable is the global values globe = stream.read_chunk("d") if not len(globe) == len(index): raise AssertionError( "Length of data doesn't match length of index: " "{} != {}".format(len(globe), len(index)) ) if metadata["datacolumns"] == 1: num_boxes = 0 data = globe[:, np.newaxis] regions = ["World"] else: regions = stream.read_chunk("d") num_boxes = int(len(regions) / len(index)) regions = regions.reshape((-1, num_boxes), order="F") data = np.concatenate((globe[:, np.newaxis], regions), axis=1) regions = [ "World", "World|Northern Hemisphere|Ocean", "World|Northern Hemisphere|Land", "World|Southern Hemisphere|Ocean", "World|Southern Hemisphere|Land", ] df = pd.DataFrame(data, index=index) if isinstance(df.index, pd.core.indexes.numeric.Float64Index): df.index = df.index.to_series().round(3) df.index.name = "time" variable = convert_magicc6_to_magicc7_variables( reader._get_variable_from_filepath() ) variable = convert_magicc7_to_openscm_variables(variable) column_headers = { "variable": [variable] * (num_boxes + 1), "region": regions, "unit": "unknown", } return df, metadata, column_headers
def _convert_compact_table_to_df_metadata_column_headers( self, compact_table): ts_cols = [c for c in compact_table if "__" in c] para_cols = [c for c in compact_table if "__" not in c] ts = compact_table[ts_cols] ts = ts.T def sort_ts_ids(inid): variable, region, year = inid.split("__") variable = variable.replace("DAT_", "") return {"variable": variable, "region": region, "year": year} ts["variable"] = ts.index.map( lambda x: convert_magicc7_to_openscm_variables( x.split("__")[0].replace("DAT_", ""))) ts["region"] = ts.index.map( lambda x: convert_magicc_to_openscm_regions(x.split("__")[1])) ts["year"] = ts.index.map(lambda x: x.split("__")[2]) # Make sure all the year strings are four characters long. Not the best test, # but as good as we can do for now. if not (ts["year"].apply(len) == 4).all(): # pragma: no cover # safety valve raise NotImplementedError("Non-annual data not yet supported") ts["year"] = ts["year"].astype(int) ts = ts.reset_index(drop=True) id_cols = {"variable", "region", "year"} run_cols = set(ts.columns) - id_cols ts = ts.melt(value_vars=run_cols, var_name="run_id", id_vars=id_cols) ts["unit"] = "unknown" new_index = list(set(ts.columns) - {"value"}) ts = ts.set_index(new_index)["value"].unstack("year") paras = compact_table[para_cols] paras.index.name = "run_id" cols_to_merge = find_parameter_groups(paras.columns.tolist()) paras_clean = paras.copy() # Aggregate the columns for new_col, components in cols_to_merge.items(): components = sorted(components) paras_clean.loc[:, new_col] = tuple(paras[components].values.tolist()) paras_clean = paras_clean.drop(columns=components) years = ts.columns.tolist() ts = ts.reset_index().set_index("run_id") out = pd.merge(ts, paras_clean, left_index=True, right_index=True).reset_index() id_cols = set(out.columns) - set(years) out = out.melt(value_vars=years, var_name="year", id_vars=id_cols) new_index = list(set(out.columns) - {"value"}) out = out.set_index(new_index)["value"].unstack("year") out = out.T column_headers = { name.lower(): out.columns.get_level_values(name).tolist() for name in out.columns.names } df = out.copy() metadata = {} return metadata, df, column_headers
def _write_datablock(self, output): # for SCEN files, the data format is vitally important for the source code # we have to work out a better way of matching up all these conventions/testing them, tight coupling between pymagicc and MAGICC may solve it for us... lines = output.getvalue().split(self._newline_char) # notes are everything except the first 6 lines number_notes_lines = len(lines) - 6 def _gip(lines, number_notes_lines): """ Get the point where we should insert the data block. """ return len(lines) - number_notes_lines region_order_db = get_region_order( self._get_df_header_row("region"), scen7=self._scen_7 ) region_order_magicc = self._ensure_file_region_type_consistency(region_order_db) # format is vitally important for SCEN files as far as I can tell time_col_length = 11 first_col_format_str = ("{" + ":{}d".format(time_col_length) + "}").format other_col_format_str = "{:10.4f}".format # TODO: doing it this way, out of the loop, should ensure things # explode if your regions don't all have the same number of emissions # timeseries or does extra timeseries in there (that probably # shouldn't raise an error, another one for the future), although the # explosion will be cryptic so should add a test for good error # message at some point formatters = [other_col_format_str] * ( int(len(self.data_block.columns) / len(region_order_db)) + 1 # for the years column ) formatters[0] = first_col_format_str variables = convert_magicc7_to_openscm_variables( self._get_df_header_row("variable"), inverse=True ) variables = _strip_emis_variables(variables) special_scen_code = get_special_scen_code( regions=region_order_magicc, emissions=variables ) if special_scen_code % 10 == 0: variable_order = PART_OF_SCENFILE_WITH_EMISSIONS_CODE_0 else: variable_order = PART_OF_SCENFILE_WITH_EMISSIONS_CODE_1 for region_db, region_magicc in zip(region_order_db, region_order_magicc): region_block_region = convert_magicc_to_openscm_regions(region_db) region_block = self.data_block.xs( region_block_region, axis=1, level="region", drop_level=False ) region_block.columns = region_block.columns.droplevel("todo") region_block.columns = region_block.columns.droplevel("region") variables = region_block.columns.levels[0] variables = convert_magicc7_to_openscm_variables(variables, inverse=True) region_block.columns = region_block.columns.set_levels( levels=_strip_emis_variables(variables), level="variable", ) region_block = region_block.reindex( variable_order, axis=1, level="variable" ) variables = region_block.columns.get_level_values("variable").tolist() variables = convert_magicc6_to_magicc7_variables( [v.replace("_EMIS", "") for v in variables], inverse=True ) units = convert_pint_to_fortran_safe_units( region_block.columns.get_level_values("unit").tolist() ) # column widths don't work with expressive units units = [u.replace("_", "").replace("peryr", "") for u in units] if not (region_block.columns.names == ["variable", "unit"]): raise AssertionError( "Unexpected region block columns: " "{}".format(region_block.columns.names) ) region_block = region_block.rename(columns=str).reset_index() region_block.columns = [["YEARS"] + variables, ["Yrs"] + units] region_block_str = region_magicc + self._newline_char region_block_str += region_block.to_string( index=False, formatters=formatters, sparsify=False ) region_block_str += self._newline_char * 2 lines.insert(_gip(lines, number_notes_lines), region_block_str) output.seek(0) output.write(self._newline_char.join(lines)) return output
class _ScenWriter(_Writer): SCEN_VARS_CODE_0 = convert_magicc7_to_openscm_variables( [v + "_EMIS" for v in PART_OF_SCENFILE_WITH_EMISSIONS_CODE_0] ) SCEN_VARS_CODE_1 = convert_magicc7_to_openscm_variables( [v + "_EMIS" for v in PART_OF_SCENFILE_WITH_EMISSIONS_CODE_1] ) def write(self, magicc_input, filepath): orig_length = len(magicc_input) orig_vars = magicc_input["variable"] if not (set(self.SCEN_VARS_CODE_1) - set(orig_vars)): magicc_input.filter(variable=self.SCEN_VARS_CODE_1, inplace=True) elif not (set(self.SCEN_VARS_CODE_0) - set(orig_vars)): magicc_input.filter(variable=self.SCEN_VARS_CODE_0, inplace=True) if len(magicc_input) != orig_length: warnings.warn("Ignoring input data which is not required for .SCEN file") super().write(magicc_input, filepath) def _write_header(self, output): header_lines = [] header_lines.append("{}".format(len(self.data_block))) variables = self._get_df_header_row("variable") variables = convert_magicc7_to_openscm_variables(variables, inverse=True) variables = _strip_emis_variables(variables) regions = self._get_df_header_row("region") regions = convert_magicc_to_openscm_regions(regions, inverse=True) regions = self._ensure_file_region_type_consistency(regions) special_scen_code = get_special_scen_code(regions=regions, emissions=variables) header_lines.append("{}".format(special_scen_code)) # for a scen file, the convention is (although all these lines are # actually ignored by source so could be anything): # - line 3 is name # - line 4 is description # - line 5 is notes (other notes lines go at the end) # - line 6 is empty header_lines.append("name: {}".format(self.minput["scenario"].unique()[0])) header_lines.append( "description: {}".format( self.minput.metadata.pop( "description", "metadata['description'] is written here" ) ) ) header_lines.append( "notes: {}".format( self.minput.metadata.pop("notes", "metadata['notes'] is written here") ) ) header_lines.append("") try: header_lines.append(self.minput.metadata.pop("header")) except KeyError: pass for k, v in self.minput.metadata.items(): header_lines.append("{}: {}".format(k, v)) output.write(self._newline_char.join(header_lines)) output.write(self._newline_char) return output def _write_namelist(self, output): # No namelist for SCEN files return output def _write_datablock(self, output): # for SCEN files, the data format is vitally important for the source code # we have to work out a better way of matching up all these conventions/testing them, tight coupling between pymagicc and MAGICC may solve it for us... lines = output.getvalue().split(self._newline_char) # notes are everything except the first 6 lines number_notes_lines = len(lines) - 6 def _gip(lines, number_notes_lines): """ Get the point where we should insert the data block. """ return len(lines) - number_notes_lines region_order_db = get_region_order( self._get_df_header_row("region"), scen7=self._scen_7 ) region_order_magicc = self._ensure_file_region_type_consistency(region_order_db) # format is vitally important for SCEN files as far as I can tell time_col_length = 11 first_col_format_str = ("{" + ":{}d".format(time_col_length) + "}").format other_col_format_str = "{:10.4f}".format # TODO: doing it this way, out of the loop, should ensure things # explode if your regions don't all have the same number of emissions # timeseries or does extra timeseries in there (that probably # shouldn't raise an error, another one for the future), although the # explosion will be cryptic so should add a test for good error # message at some point formatters = [other_col_format_str] * ( int(len(self.data_block.columns) / len(region_order_db)) + 1 # for the years column ) formatters[0] = first_col_format_str variables = convert_magicc7_to_openscm_variables( self._get_df_header_row("variable"), inverse=True ) variables = _strip_emis_variables(variables) special_scen_code = get_special_scen_code( regions=region_order_magicc, emissions=variables ) if special_scen_code % 10 == 0: variable_order = PART_OF_SCENFILE_WITH_EMISSIONS_CODE_0 else: variable_order = PART_OF_SCENFILE_WITH_EMISSIONS_CODE_1 for region_db, region_magicc in zip(region_order_db, region_order_magicc): region_block_region = convert_magicc_to_openscm_regions(region_db) region_block = self.data_block.xs( region_block_region, axis=1, level="region", drop_level=False ) region_block.columns = region_block.columns.droplevel("todo") region_block.columns = region_block.columns.droplevel("region") variables = region_block.columns.levels[0] variables = convert_magicc7_to_openscm_variables(variables, inverse=True) region_block.columns = region_block.columns.set_levels( levels=_strip_emis_variables(variables), level="variable", ) region_block = region_block.reindex( variable_order, axis=1, level="variable" ) variables = region_block.columns.get_level_values("variable").tolist() variables = convert_magicc6_to_magicc7_variables( [v.replace("_EMIS", "") for v in variables], inverse=True ) units = convert_pint_to_fortran_safe_units( region_block.columns.get_level_values("unit").tolist() ) # column widths don't work with expressive units units = [u.replace("_", "").replace("peryr", "") for u in units] if not (region_block.columns.names == ["variable", "unit"]): raise AssertionError( "Unexpected region block columns: " "{}".format(region_block.columns.names) ) region_block = region_block.rename(columns=str).reset_index() region_block.columns = [["YEARS"] + variables, ["Yrs"] + units] region_block_str = region_magicc + self._newline_char region_block_str += region_block.to_string( index=False, formatters=formatters, sparsify=False ) region_block_str += self._newline_char * 2 lines.insert(_gip(lines, number_notes_lines), region_block_str) output.seek(0) output.write(self._newline_char.join(lines)) return output def _ensure_file_region_type_consistency(self, regions): magicc7_regions_mapping = { r: r.replace("R5.2", "R5") for r in ["R5.2ASIA", "R5.2LAM", "R5.2REF", "R5.2MAF", "R5.2OECD"] } if not any([r in regions for r in magicc7_regions_mapping]): return regions new_regions = [ magicc7_regions_mapping[r] if r in magicc7_regions_mapping else r for r in regions ] warn_msg = ( "MAGICC7 RCP region naming (R5.2*) is not compatible with " "MAGICC6, automatically renaming to MAGICC6 compatible regions " "(R5*)" ) warnings.warn(warn_msg) return new_regions