Source code for otoole.results.convert

"""Converts an OSeMOSYS solution file from CPLEX, CBC or GLPK into CBC or CSV format

"""
import argparse
from typing import List, Tuple


[docs]class ConvertLine(object): """Abstract class which defines the interface to the family of convertors Inherit this class and implement the ``_do_it()`` method to produce the data to be written out into a new format Example ------- >>> cplex_line = "AnnualCost REGION CDBACKSTOP 1.0 0.0 137958.8400384134" >>> convertor = RegionTechnology() >>> convertor.convert() VariableName(REGION,TECHCODE01,2015) 42.69 0\\n VariableName(REGION,TECHCODE01,2017) 137958.84 0\\n """ def __init__(self, data: List, start_year: int, end_year: int, output_format='cbc'): self.data = data self.start_year = start_year self.end_year = end_year self.output_format = output_format def _do_it(self) -> Tuple: raise NotImplementedError()
[docs] def convert(self) -> List[str]: if self.output_format == 'cbc': convert = self.convert_cbc() elif self.output_format == 'csv': convert = self.convert_csv() return convert
[docs] def convert_csv(self) -> List[str]: """Format the data for writing to a csv file """ data = [] variable, dimensions, values = self._do_it() for index, value in enumerate(values): year = self.start_year + index if (value not in ["0.0", "0", ""]) and (year <= self.end_year): try: value = float(value) except ValueError: value = 0 full_dims = ",".join(dimensions + (str(year),)) formatted_data = '{0},"{1}",{2}\n'.format( variable, full_dims, value ) data.append(formatted_data) return data
[docs] def convert_cbc(self) -> List[str]: """Format the data for writing to a CBC file """ cbc_data = [] variable, dimensions, values = self._do_it() for index, value in enumerate(values): year = self.start_year + index if (value not in ["0.0", "0", ""]) and (year <= self.end_year): try: value = float(value) except ValueError: value = 0 full_dims = ",".join(dimensions + (str(year),)) formatted_data = "0 {0}({1}) {2} 0\n".format( variable, full_dims, value ) cbc_data.append(formatted_data) return cbc_data
[docs]class RegionTimeSliceTechnologyMode(ConvertLine): def _do_it(self) -> Tuple: """Produces output indexed by Region, Timeslice, Tech and Mode ``0 VariableName(REGION,SD1D,TECHCODE01,2,2015) 42.69 0\n`` """ variable = self.data[0] region = self.data[1] timeslice = self.data[2] technology = self.data[3] mode = self.data[4] values = self.data[5:] dimensions = (region, timeslice, technology, mode) return (variable, dimensions, values)
[docs]class RegionTechnology(ConvertLine): def _do_it(self) -> Tuple: """Produces output indexed by dimensions Region and Technology ``0 VariableName(REGION,TECHCODE01,2015) 42.69 0\n`` """ variable = self.data[0] region = self.data[1] technology = self.data[2] dimensions = (region, technology) values = self.data[3:] return (variable, dimensions, values)
[docs]def process_line(line: str, start_year: int, end_year: int, output_format: str) -> List[str]: """Processes an individual line in a CPLEX file A different ConvertLine implementation is chosen depending upon the variable name Arguments --------- line: str start_year: int end_year: int output_format: str The file format required - either ``csv`` or ``cbc`` """ row_as_list = line.split('\t') variable = row_as_list[0] if variable in ['NewCapacity', 'TotalCapacityAnnual', 'CapitalInvestment', 'AnnualFixedOperatingCost', 'AnnualVariableOperatingCost']: convertor = RegionTechnology(row_as_list, start_year, end_year, output_format).convert() elif variable in ['RateOfActivity']: convertor = RegionTimeSliceTechnologyMode(row_as_list, start_year, end_year, output_format).convert() else: convertor = [] return convertor
[docs]def convert_cplex_file(cplex_filename: str, output_filename: str, start_year=2015, end_year=2070, output_format='cbc'): """Converts a CPLEX solution file into that of the CBC solution file Arguments --------- cplex_filename : str Path to the transformed CPLEX solution file output_filename : str Path for the processed data to be written to """ with open(output_filename, 'w') as cbc_file: with open(cplex_filename, 'r') as cplex_file: for linenum, line in enumerate(cplex_file): try: convertor = process_line(line, start_year, end_year, output_format) if convertor: cbc_file.writelines(convertor) except ValueError: msg = "Error caused at line {}: {}" raise ValueError(msg.format(linenum, line))
if __name__ == '__main__': parser = argparse.ArgumentParser(description="Convert OSeMOSYS CPLEX files into different formats") parser.add_argument("cplex_file", help="The filepath of the OSeMOSYS cplex output file") parser.add_argument("output_file", help="The filepath of the converted file that will be written") parser.add_argument("-s", "--start_year", type=int, default=2015, help="Output only the results from this year onwards") parser.add_argument("-e", "--end_year", type=int, default=2070, help="Output only the results upto and including this year") group = parser.add_mutually_exclusive_group() group.add_argument("--csv", action="store_true", help="Output file in comma-separated-values format") group.add_argument("--cbc", action="store_true", help="Output file in CBC format, (default option)") args = parser.parse_args() if args.csv: output_format = 'csv' else: output_format = 'cbc' convert_cplex_file(args.cplex_file, args.output_file, args.start_year, args.end_year, output_format)