def __init__(self, scenario_id, api_run=False): self.scenario_id = scenario_id self.scenario = Scenario(self.scenario_id) self.api_run = api_run self.outputs = Output() self.demand = Demand(self.scenario) self.supply = None self.demand_solved, self.supply_solved = False, False
def __init__(self): super().__init__([pin_number1, pin_number2]) self.demand = Demand(mode='', event='key', pulse_time=0.0001) self.user_methodd = [user_method1, user_method2] self.handler = [handler1, handler2] # key指定し、self.sensor_valueにkeyと同じ値が入ったとき # user_methodを逐次的に呼び出していく super().add_event_handler(key, handler)
def configure_energy_system(self): print 'configuring energy system' self.demand = Demand(self.cfgfile_path, self.custom_pint_definitions_path) self.supply = Supply(os.path.join(os.getcwd(), 'outputs'), self.cfgfile_path, self.custom_pint_definitions_path) self.configure_demand() self.configure_supply()
def __init__(self): self.demand = Demand(mode='double', edge=1, pulse_time=0.00001) super().__init__([20, 21]) self.user_methods = [self.sensor_method, self.user_method1] self.event_handler.add_event_handler(20, self.user_method2) self.pulse_start = 0 self.pulse_end = 0 self.pulse_duration = 0 self.distance = 0
def __init__(self, scenario_id, api_run=False): self.scenario_id = scenario_id self.api_run = api_run self.scenario = cfg.scenario_dict[self.scenario_id] self.demand_case_id = util.sql_read_table('Scenarios', 'demand_case', id=self.scenario_id) self.supply_case_id = util.sql_read_table('Scenarios', 'supply_case', id=self.scenario_id) self.outputs = Output() self.demand = Demand() self.supply = None self.demand_solved, self.supply_solved = False, False
def _GetSpfPathList(self, source: Node, target: Node, demand: int, demand_obj: Demand, G): """ Used to create the path list , it's called by the new GetSpfPath that solves the issue with unequal load balancing when >3 paths """ """ G = nx.MultiDiGraph() # node_list = [node for node in self.get_nodes() if not node._failed] node_list = self.get_nodes() for node in node_list: for interface in node.interfaces: if not interface._failed: G.add_edge( node, interface.target, **interface._networkX(), data=interface ) G.add_nodes_from(node_list) """ paths = list(nx.all_shortest_paths(G, source, target, weight="metric")) num_ecmp_paths = len(paths) demand_path = demand / num_ecmp_paths if paths: demand_obj.demand_path = [] for p in paths: total_metric = 0 total_latency = 0 u = p[0] for v in p[1:]: ecmp_max_latency = [] values_u_v = G[u][v].values() min_weight = min(d["metric"] for d in values_u_v) total_metric = total_metric + min_weight # delete old path list ecmp_links = [ k for k, d in G[u][v].items() if d["metric"] == min_weight ] num_ecmp_links = len(ecmp_links) for d in ecmp_links: ecmp_max_latency.append(G[u][v][d]["data"].latency) demand_obj.demand_path.append([ u.label, v.label, min_weight, G[u][v][d]["data"].latency, ]) total_latency = total_latency + max(ecmp_max_latency) u = v demand_obj.demand_path.append([ "-", "-", "Total:" + str(total_metric), "Total:" + str(total_latency) ]) demand_obj.total_latency = total_latency demand_obj.total_metric = total_metric
def __init__(self, db_path, cfgfile_path, custom_pint_definitions_path=None, name=None, author=None): self.model_config(db_path, cfgfile_path, custom_pint_definitions_path) self.name = cfg.cfgfile.get('case', 'scenario') if name is None else name self.author = cfg.cfgfile.get('case', 'author') if author is None else author self.demand = Demand() self.supply = Supply()
def calc_eoq(row): cost = row['cost'] demand = row['demand'] rc = RawCosts(unit_cost=cost, ordering_cost=c_t, holding_rate=h) d = Demand(quantity=demand) return EOQ.optimal_order_quantity(rc, d)
def qq_06(): c_t = 525 c_e = 1.25 rc = RawCosts(unit_cost=1.00, ordering_cost=c_t, holding_cost=c_e, holding_time_unit='M') d = Demand(quantity=120, time_unit='M') Q = EOQ.optimal_order_quantity(raw_costs=rc, demand=d) print("EOQ: {}".format(Q)) B = 170 L = 1 mu_dl = 30 sigma_dl = 9 inner_value = (B * d.quantity) / (c_e * sigma_dl * Q * sqrt(2 * pi)) print("inner value: {}".format(inner_value)) k = sqrt(2 * log(inner_value)) print("k: {}".format(k)) s = mu_dl + k * sigma_dl print("s: {}".format(s))
def arrival_demand(times: Clock, system: Configuration) -> None: print("I. Arrival demand", times.current, end="\t###\t") demand = Demand(times.arrival) print("demand ID:", demand.id) if system.queue.empty() and not system.device.serves: times.service_start = times.current system.queue.put(demand) times.update_arrival_time(system.lambd)
class SonicSensorDemand(DemandGpioSensor): def __init__(self): self.demand = Demand(mode='double', edge=1, pulse_time=0.00001) super().__init__([20, 21]) self.user_methods = [self.sensor_method, self.user_method1] self.event_handler.add_event_handler(20, self.user_method2) self.pulse_start = 0 self.pulse_end = 0 self.pulse_duration = 0 self.distance = 0 def main(self): print("Distance Measurement in Progress") super().demand_issue(self.demand, self.start_method, 'high') self.demand.set_mode(None) super().demand_issue(self.demand, self.sensor_method, 'low') def start_method(self, earg=None): self.loop_flag = 0 self.pulse_start = time.time() print(self.pulse_start) def sensor_method(self, earg=None): self.loop_flag = 0 self.pulse_end = time.time() print(self.pulse_start) print(self.pulse_end) self.pulse_duration = self.pulse_end - self.pulse_start self.distance = self.pulse_duration * 17150 self.distance = round(self.distance, 2) print("Distance: ", self.distance, "cm") if (self.distance < 20): self.sensor_value = 20 if self.sensor_value in self.event_handler: self.event_handler() else: self.sensor_value = None def user_method1(self, earg=None): print('call user method') def user_method2(self, earg=None): print('hello, world')
def part3(): d = Demand(240, 'M') rc = RawCosts(50.0, 100.0, 0.01, holding_time_unit='M') Q = EOQ.optimal_order_quantity(rc, d) print(Q) T = EOQ.optimal_cycle_time(rc, d) print(T) print(T * 4)
def test_create_path(): """Test creation of a path.""" network = Network() demand = Demand(network) alice = Router(network, "alice") bob = Router(network, "bob") _path = Path(demand=demand, name="alice-to-bob", end_point_1=alice, end_point_2=bob, bandwidth=10, fidelity=0.95)
def part01(): sigma_dl = calc_sigma_dl() g_k = (0.0211 + 0.0206) / 2 # from table d = Demand(quantity=D) rc = RawCosts(unit_cost=c, ordering_cost=c_t, holding_rate=h) Q = EOQ.optimal_order_quantity(rc, d) IFR = 1 - ((sigma_dl * g_k) / Q) print("IFR: {}".format(IFR)) return Q
def part01(): sku = '3206-BO1' item = df.loc[sku] rc = RawCosts(unit_cost=item['cost'], ordering_cost=c_t, holding_rate=h) d = Demand(quantity=item['demand']) Q = EOQ.optimal_order_quantity(rc, d) print("Q: {}".format(Q)) sigma = item['rmse'] print("sigma: {}".format(sigma)) print("sigma_dl: {}".format(sigma * math.sqrt(1 / 12)))
class DemandGpioTemplate(DemandGpioSensor): def __init__(self): super().__init__([pin_number1, pin_number2]) self.demand = Demand(mode='', event='key', pulse_time=0.0001) self.user_methodd = [user_method1, user_method2] self.handler = [handler1, handler2] # key指定し、self.sensor_valueにkeyと同じ値が入ったとき # user_methodを逐次的に呼び出していく super().add_event_handler(key, handler) def main_method(self): super().periodic_read(self, user_method) # add event handler. gave methods and detect edge. # edge can receive 'hige', 'low', 'both'. super().demand_issue(self.demand, sensor_method1, cathc_edge='high') self.demand.set_mode(None) super().demand_issue(self.demand, sensor_method2, cathc_edge='high') def sensor_method1(self): # please describe "loop_flag = 0" self.loop_flag = 0 pass def sensor_method2(self): self.loop_flag = 0 # イベントハンドラを呼びたいときは以下のようにしてください # self.sensor_value = GPIO.input(self.channel[0]) # または self.sensor_value = value # if self.sensor_value in self.event_handler: # self.eent_handler() # else: # pass def handler1(self): pass def handler2(self): pass
def add_demand(self, source: str, target: str, demand: float): source_node = self.get_node_based_on_label(source) target_node = self.get_node_based_on_label(target) if source_node not in self.nodes or target_node not in self.nodes: raise Exception(f"{source} or {target} not in the Graph") damand_exists = False for existing_demand in self.demands: if (source_node == existing_demand.source and target_node == existing_demand.target): existing_demand.demand += demand damand_exists = True if not damand_exists: demand_object = Demand(source_node, target_node, demand) self.demands.append(demand_object)
def test_demand(): from demand import Demand dm = Demand() # in-home activities and out-of-home activities # madantory activities: work/business, school/college # maintenance activities: escort passengers, shopping # discretionary activities: eating out, visiting friends activity_data = [['home', 1.0, 600, -0.010, 1.0, 720, (0, 1440), 360], ['work', 0.0, 1600, 0.010, 1.0, 720, (240, 1440), 240], ['school', 0.0, 1600, 0.010, 1.0, 720, (240, 1440), 240], ['eating', 0.0, 420, 0.010, 1.0, 1170, (720, 1440), 10], ['shopping', 0.0, 500, 0.010, 1.0, 1110, (720, 1440), 10], ['visiting', 0.0, 500, 0.010, 1.0, 1110, (720, 1440), 10], [ 'escorting', 0.0, 500, 0.010, 1.0, 1110, (720, 1440), 10 ]] create_objects(dm.add_activity, activity_data) print 'activities:' pprint(dm.activities.items()) print "building activity utility..." dm.build_activity_util() logger.info('activity utility: home') logger.debug(pformat(dm.get_activity_util(dm.activities["home"]))) logger.info('activity utility: work') logger.debug(pformat(dm.get_activity_util(dm.activities["work"]))) logger.info('activity utility: shopping') logger.debug(pformat(dm.get_activity_util(dm.activities["shopping"]))) # intra-household interactions # entire day level: # staying at home, absent together # non-madantory DAP together (day-off for major shopping) # episode level: # shared activity # escorting (children to school) # allocation of maintenance task (shopping) # car allocation # types of joint travel # fully-joint tour, joint outbound, joint inbound # drop-off/get-off, pick-up/get-in program_data = [[0, []], [1, ['shopping']], [3, ['eating']], [2, ['visiting']], [4, ['shopping', 'visiting']], [5, ['shopping', 'eating']]] create_objects(dm.add_program, program_data) print 'programs:' pprint(dm.programs.items()) return dm
def test_demand(): from demand import Demand dm = Demand() # in-home activities and out-of-home activities # madantory activities: work/business, school/college # maintenance activities: escort passengers, shopping # discretionary activities: eating out, visiting friends activity_data = [ ['home', 1.0, 600, -0.010, 1.0, 720, ( 0, 1440), 360], ['work', 0.0, 1600, 0.010, 1.0, 720, (240, 1440), 240], ['school', 0.0, 1600, 0.010, 1.0, 720, (240, 1440), 240], ['eating', 0.0, 420, 0.010, 1.0, 1170, (720, 1440), 10], ['shopping', 0.0, 500, 0.010, 1.0, 1110, (720, 1440), 10], ['visiting', 0.0, 500, 0.010, 1.0, 1110, (720, 1440), 10], ['escorting', 0.0, 500, 0.010, 1.0, 1110, (720, 1440), 10] ] create_objects(dm.add_activity, activity_data) print 'activities:' pprint(dm.activities.items()) print "building activity utility..." dm.build_activity_util() logger.info('activity utility: home') logger.debug(pformat(dm.get_activity_util(dm.activities["home"]))) logger.info('activity utility: work') logger.debug(pformat(dm.get_activity_util(dm.activities["work"]))) logger.info('activity utility: shopping') logger.debug(pformat(dm.get_activity_util(dm.activities["shopping"]))) # intra-household interactions # entire day level: # staying at home, absent together # non-madantory DAP together (day-off for major shopping) # episode level: # shared activity # escorting (children to school) # allocation of maintenance task (shopping) # car allocation # types of joint travel # fully-joint tour, joint outbound, joint inbound # drop-off/get-off, pick-up/get-in program_data = [ [0, []], [1, ['shopping']], [3, ['eating']], [2, ['visiting']], [4, ['shopping', 'visiting']], [5, ['shopping', 'eating']] ] create_objects(dm.add_program, program_data) print 'programs:' pprint(dm.programs.items()) return dm
def part02(): sku = '3206-BO1' item = df.loc[sku] cost = item['cost'] demand = item['demand'] rc = RawCosts(unit_cost=cost, ordering_cost=c_t, holding_rate=h) d = Demand(quantity=demand) Q = EOQ.optimal_order_quantity(rc, d) sigma = item['rmse'] sigma_dl = sigma * math.sqrt(1 / 12) print("sigma_dl * ci: {}".format(sigma_dl * cost)) print("D/Q: {}".format(demand / Q)) print("(D/Q) * (sigma_dl * ci): {}".format((demand / Q) * sigma_dl * cost))
def _GetSpfPath(self, source: Node, target: Node, demand: int, G, demand_obj: Demand): """ Used to put demands on the links , it's called by the new GetSpfPath that solves the issue with unequal load balancing when >3 paths """ """ G = nx.MultiDiGraph() # node_list = [node for node in self.get_nodes() if not node._failed] node_list = self.get_nodes() for node in node_list: for interface in node.interfaces: if not interface._failed: G.add_edge( node, interface.target, **interface._networkX(), data=interface ) G.add_nodes_from(node_list) """ paths = list(nx.all_shortest_paths(G, source, target)) num_ecmp_paths = len(paths) demand_path = demand / num_ecmp_paths for p in paths: u = p[0] for v in p[1:]: values_u_v = G[u][v].values() min_weight = min(d["metric"] for d in values_u_v) ecmp_links = [ k for k, d in G[u][v].items() if d["metric"] == min_weight ] num_ecmp_links = len(ecmp_links) for d in ecmp_links: G[u][v][d]["data"].util += int(demand_path) / int( num_ecmp_links) if G[u][v][d]["data"].util > G[u][v][d]["data"].capacity: demand_obj.degraded = True G[u][v][d]["data"]._on_spf = True u = v
from demand_driven_io import DemandDrivenIo from sensor_exception import SensorException from demand import Demand from event_handler import EventHandler class DemandSpiSensor(SpiSensorConf, DemandtDrivenIo, SensorException): """This class is for the demand driven sensors""" def __init__(self, device=0, bus=0): super().__init__(self, device, bus) self.event_handlers = EventHandler() def demand_issue(self, demand, **catch_event) self.sensor_data = [] # 読み取ってとってくる値を取得 if isinstance(demand, Demand): demand = Demand() else: print('Please give a Demand object.') return False if catch_event != {}: # cath_eventは{'1011':method} これがもらえるとよそう # main処理 書 -> 読 -> コールバック(値に応じた) for event in catch_event: self.event_handlers.add(event, catch_event[event]) for write in demand.write_methods(): write() time.sleep(demand.interval)
class PathwaysModel(object): """ Highest level classification of the definition of an energy system. """ def __init__(self, scenario_id, api_run=False): self.scenario_id = scenario_id self.scenario = Scenario(self.scenario_id) self.api_run = api_run self.outputs = Output() self.demand = Demand(self.scenario) self.supply = None self.demand_solved, self.supply_solved = False, False def run(self, scenario_id, solve_demand, solve_supply, load_demand, load_supply, export_results, save_models, append_results): try: if solve_demand and not (load_demand or load_supply): self.calculate_demand(save_models) if not append_results: self.remove_old_results() # it is nice if when loading a demand side object to rerun supply, it doesn't re-output these results every time if self.demand_solved and export_results and not self.api_run and not (load_demand and solve_supply): self.export_result_to_csv('demand_outputs') if solve_supply and not load_supply: if load_demand: # if we are loading the demand, we are changing the supply measures and want to reload our scenarios self.scenario = Scenario(self.scenario_id) self.supply = Supply(self.scenario, demand_object=self.demand) self.calculate_supply(save_models) if load_demand and solve_supply: # we do this now because we delayed before self.export_result_to_csv('demand_outputs') if self.supply_solved and export_results: self.supply.calculate_supply_outputs() self.pass_supply_results_back_to_demand() self.calculate_combined_results() self.outputs.electricity_reconciliation = self.demand.electricity_reconciliation # we want to write these to outputs if self.api_run: self.export_results_to_db() else: self.export_result_to_csv('supply_outputs') self.export_result_to_csv('combined_outputs') self.export_io() except: # pickle the model in the event that it crashes if save_models: Output.pickle(self, file_name=str(scenario_id) + cfg.model_error_append_name, path=cfg.workingdir) raise def calculate_demand(self, save_models): self.demand.setup_and_solve() self.demand_solved = True if cfg.output_payback == 'true': if self.demand.d_all_energy_demand_payback is not None: self.calculate_d_payback() self.calculate_d_payback_energy() if save_models: Output.pickle(self, file_name=str(self.scenario_id) + cfg.demand_model_append_name, path=cfg.workingdir) def calculate_supply(self, save_models): if not self.demand_solved: raise ValueError('demand must be solved first before supply') logging.info('Configuring energy system supply') self.supply.add_nodes() self.supply.add_measures() self.supply.initial_calculate() self.supply.calculated_years = [] self.supply.calculate_loop(self.supply.years, self.supply.calculated_years) self.supply.final_calculate() self.supply_solved = True if save_models: Output.pickle(self, file_name=str(self.scenario_id) + cfg.full_model_append_name, path=cfg.workingdir) # we don't need the demand side object any more, so we can remove it to save drive space if os.path.isfile(os.path.join(cfg.workingdir, str(self.scenario_id) + cfg.demand_model_append_name)): os.remove(os.path.join(cfg.workingdir, str(self.scenario_id) + cfg.demand_model_append_name)) def pass_supply_results_back_to_demand(self): logging.info("Calculating link to supply") self.demand.link_to_supply(self.supply.emissions_demand_link, self.supply.demand_emissions_rates, self.supply.energy_demand_link, self.supply.cost_demand_link) if cfg.output_tco == 'true': if hasattr(self,'d_energy_tco'): self.demand.link_to_supply_tco(self.supply.emissions_demand_link, self.supply.demand_emissions_rates, self.supply.cost_demand_link) else: print "demand side has not been run with tco outputs set to 'true'" if cfg.output_payback == 'true': if hasattr(self,'demand.d_all_energy_demand_payback'): self.demand.link_to_supply_payback(self.supply.emissions_demand_link, self.supply.demand_emissions_rates, self.supply.cost_demand_link) else: print "demand side has not been run with tco outputs set to 'true'" def calculate_combined_results(self): logging.info("Calculating combined emissions results") self.calculate_combined_emissions_results() logging.info("Calculating combined cost results") self.calculate_combined_cost_results() logging.info("Calculating combined energy results") self.calculate_combined_energy_results() if cfg.output_tco == 'true': if self.demand.d_energy_tco is not None: self.calculate_tco() if cfg.output_payback == 'true': if self.demand.d_all_energy_demand_payback is not None: self.calculate_payback() def remove_old_results(self): folder_names = ['combined_outputs', 'demand_outputs', 'supply_outputs', 'dispatch_outputs'] for folder_name in folder_names: folder = os.path.join(cfg.workingdir, folder_name) if os.path.isdir(folder): shutil.rmtree(folder) def export_result_to_csv(self, result_name): if result_name=='combined_outputs': res_obj = self.outputs elif result_name=='demand_outputs': res_obj = self.demand.outputs elif result_name=='supply_outputs': res_obj = self.supply.outputs else: raise ValueError('result_name not recognized') for attribute in dir(res_obj): if not isinstance(getattr(res_obj, attribute), pd.DataFrame): continue result_df = getattr(res_obj, 'return_cleaned_output')(attribute) keys = [self.scenario.name.upper(), cfg.timestamp] names = ['SCENARIO','TIMESTAMP'] for key, name in zip(keys, names): result_df = pd.concat([result_df], keys=[key], names=[name]) if attribute in ('hourly_dispatch_results', 'electricity_reconciliation', 'hourly_marginal_cost', 'hourly_production_cost'): # Special case for hourly dispatch results where we want to write them outside of supply_outputs Output.write(result_df, attribute + '.csv', os.path.join(cfg.workingdir, 'dispatch_outputs')) else: Output.write(result_df, attribute+'.csv', os.path.join(cfg.workingdir, result_name)) def export_results_to_db(self): scenario_run_id = util.active_scenario_run_id(self.scenario_id) # Levelized costs costs = self.outputs.c_costs.groupby(level=['SUPPLY/DEMAND', 'YEAR']).sum() util.write_output_to_db(scenario_run_id, 1, costs) #Energy energy = self.outputs.c_energy.xs('FINAL', level='ENERGY ACCOUNTING')\ .groupby(level=['SECTOR', 'FINAL_ENERGY', 'YEAR']).sum() # Energy demand by sector util.write_output_to_db(scenario_run_id, 2, energy.groupby(level=['SECTOR', 'YEAR']).sum()) # Residential Energy by Fuel Type util.write_output_to_db(scenario_run_id, 6, energy.xs('RESIDENTIAL', level='SECTOR')) # Commercial Energy by Fuel Type util.write_output_to_db(scenario_run_id, 8, energy.xs('COMMERCIAL', level='SECTOR')) # Transportation Energy by Fuel Type util.write_output_to_db(scenario_run_id, 10, energy.xs('TRANSPORTATION', level='SECTOR')) # Productive Energy by Fuel Type util.write_output_to_db(scenario_run_id, 12, energy.xs('PRODUCTIVE', level='SECTOR')) #Emissions emissions = self.outputs.c_emissions.xs('DOMESTIC', level='EXPORT/DOMESTIC')\ .groupby(level=['SECTOR', 'FINAL_ENERGY', 'YEAR']).sum() emissions = util.DfOper.mult((emissions, 1-(emissions.abs()<1E-10).groupby(level='FINAL_ENERGY').all())) # get rid of noise # Annual emissions by sector util.write_output_to_db(scenario_run_id, 3, emissions.groupby(level=['SECTOR', 'YEAR']).sum()) # Residential Emissions by Fuel Type util.write_output_to_db(scenario_run_id, 7, emissions.xs('RESIDENTIAL', level='SECTOR')) # Commercial Emissions by Fuel Type util.write_output_to_db(scenario_run_id, 9, emissions.xs('COMMERCIAL', level='SECTOR')) # Transportation Emissions by Fuel Type util.write_output_to_db(scenario_run_id, 11, emissions.xs('TRANSPORTATION', level='SECTOR')) # Productive Emissions by Fuel Type util.write_output_to_db(scenario_run_id, 13, emissions.xs('PRODUCTIVE', level='SECTOR')) # Domestic emissions per capita annual_emissions = self.outputs.c_emissions.xs('DOMESTIC', level='EXPORT/DOMESTIC').groupby(level=['YEAR']).sum() population_driver = self.demand.drivers[2].values.groupby(level='year').sum().loc[annual_emissions.index] population_driver.index.name = 'YEAR' factor = 1E6 df = util.DfOper.divi((annual_emissions, population_driver)) * factor df.columns = ['TONNE PER CAPITA'] util.write_output_to_db(scenario_run_id, 4, df) # Electricity supply electricity_node_names = [self.supply.nodes[nodeid].name.upper() for nodeid in util.flatten_list(self.supply.injection_nodes.values())] df = self.outputs.c_energy.xs('ELECTRICITY', level='FINAL_ENERGY')\ .xs('EMBODIED', level='ENERGY ACCOUNTING')\ .groupby(level=['SUPPLY_NODE', 'YEAR']).sum() util.write_output_to_db(scenario_run_id, 5, df.loc[electricity_node_names]) def calculate_combined_cost_results(self): #calculate and format export costs cost_unit = cfg.cfgfile.get('case','currency_year_id') + " " + cfg.cfgfile.get('case','currency_name') if self.supply.export_costs is not None: setattr(self.outputs,'export_costs',self.supply.export_costs) self.export_costs_df = self.outputs.return_cleaned_output('export_costs') del self.outputs.export_costs util.replace_index_name(self.export_costs_df, 'FINAL_ENERGY','SUPPLY_NODE_EXPORT') keys = ["EXPORT","SUPPLY"] names = ['EXPORT/DOMESTIC', "SUPPLY/DEMAND"] for key,name in zip(keys,names): self.export_costs_df = pd.concat([self.export_costs_df],keys=[key],names=[name]) self.export_costs_df.columns = [cost_unit.upper()] else: self.export_costs_df = None #calculate and format emobodied supply costs self.embodied_energy_costs_df = self.demand.outputs.return_cleaned_output('demand_embodied_energy_costs') self.embodied_energy_costs_df.columns = [cost_unit.upper()] keys = ["DOMESTIC","SUPPLY"] names = ['EXPORT/DOMESTIC', "SUPPLY/DEMAND"] for key,name in zip(keys,names): self.embodied_energy_costs_df = pd.concat([self.embodied_energy_costs_df],keys=[key],names=[name]) #calculte and format direct demand costs self.demand_costs_df = self.demand.outputs.return_cleaned_output('d_levelized_costs') if self.demand_costs_df is not None: levels_to_keep = [x.upper() for x in cfg.output_combined_levels] levels_to_keep = [x for x in levels_to_keep if x in self.demand_costs_df.index.names] self.demand_costs_df = self.demand_costs_df.groupby(level=levels_to_keep).sum() keys = ["DOMESTIC","DEMAND"] names = ['EXPORT/DOMESTIC', "SUPPLY/DEMAND"] for key,name in zip(keys,names): self.demand_costs_df = pd.concat([self.demand_costs_df],keys=[key],names=[name]) keys = ['EXPORTED', 'SUPPLY-SIDE', 'DEMAND-SIDE'] names = ['COST TYPE'] self.outputs.c_costs = util.df_list_concatenate([self.export_costs_df, self.embodied_energy_costs_df, self.demand_costs_df],keys=keys,new_names=names) self.outputs.c_costs[self.outputs.c_costs<0]=0 self.outputs.c_costs= self.outputs.c_costs[self.outputs.c_costs[cost_unit.upper()]!=0] def calculate_tco(self): # self.embodied_emissions_df = self.demand.outputs.return_cleaned_output('demand_embodied_emissions_tco') # del self.demand.outputs.demand_embodied_emissions #calculte and format direct demand emissions # self.direct_emissions_df = self.demand.outputs.return_cleaned_output('demand_direct_emissions') ## del self.demand.outputs.demand_direct_emissions # emissions = util.DfOper.add([self.embodied_emissions_df,self.direct_emissions_df]) # #calculate and format export costs cost_unit = cfg.cfgfile.get('case','currency_year_id') + " " + cfg.cfgfile.get('case','currency_name') initial_vintage = min(cfg.supply_years) supply_side_df = self.demand.outputs.demand_embodied_energy_costs_tco supply_side_df = supply_side_df[supply_side_df.index.get_level_values('vintage')>=initial_vintage] demand_side_df = self.demand.d_levelized_costs_tco demand_side_df.columns = ['value'] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('vintage')>=initial_vintage] service_demand_df = self.demand.d_service_demand_tco service_demand_df = service_demand_df[service_demand_df.index.get_level_values('vintage')>=initial_vintage] keys = ['SUPPLY-SIDE', 'DEMAND-SIDE'] names = ['COST TYPE'] self.outputs.c_tco = pd.concat([util.DfOper.divi([supply_side_df,util.remove_df_levels(service_demand_df,'unit')]), util.DfOper.divi([demand_side_df,util.remove_df_levels(service_demand_df,'unit')])], keys=keys,names=names) self.outputs.c_tco = self.outputs.c_tco.replace([np.inf,np.nan],0) self.outputs.c_tco[self.outputs.c_tco<0]=0 for sector in self.demand.sectors.values(): for subsector in sector.subsectors.values(): if hasattr(subsector,'service_demand') and hasattr(subsector,'stock'): indexer = util.level_specific_indexer(self.outputs.c_tco,'subsector',subsector.id) self.outputs.c_tco.loc[indexer,'unit'] = subsector.service_demand.unit.upper() self.outputs.c_tco = self.outputs.c_tco.set_index('unit',append=True) self.outputs.c_tco.columns = [cost_unit.upper()] self.outputs.c_tco= self.outputs.c_tco[self.outputs.c_tco[cost_unit.upper()]!=0] self.outputs.c_tco = self.outputs.return_cleaned_output('c_tco') def calculate_payback(self): # self.embodied_emissions_df = self.demand.outputs.return_cleaned_output('demand_embodied_emissions_tco') # del self.demand.outputs.demand_embodied_emissions #calculte and format direct demand emissions # self.direct_emissions_df = self.demand.outputs.return_cleaned_output('demand_direct_emissions') ## del self.demand.outputs.demand_direct_emissions # emissions = util.DfOper.add([self.embodied_emissions_df,self.direct_emissions_df]) # #calculate and format export costs cost_unit = cfg.cfgfile.get('case','currency_year_id') + " " + cfg.cfgfile.get('case','currency_name') initial_vintage = min(cfg.supply_years) supply_side_df = self.demand.outputs.demand_embodied_energy_costs_payback supply_side_df = supply_side_df[supply_side_df.index.get_level_values('vintage')>=initial_vintage] supply_side_df = supply_side_df[supply_side_df.index.get_level_values('year')>=initial_vintage] supply_side_df = supply_side_df.sort_index() demand_side_df = self.demand.d_annual_costs_payback demand_side_df.columns = ['value'] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('vintage')>=initial_vintage] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('year')>=initial_vintage] demand_side_df = demand_side_df.reindex(supply_side_df.index).sort_index() sales_df = copy.deepcopy(self.demand.outputs.d_sales) util.replace_index_name(sales_df,'vintage','year') sales_df = sales_df[sales_df.index.get_level_values('vintage')>=initial_vintage] sales_df = util.add_and_set_index(sales_df,'year',cfg.supply_years) sales_df.index = sales_df.index.reorder_levels(supply_side_df.index.names) sales_df = sales_df.reindex(supply_side_df.index).sort_index() keys = ['SUPPLY-SIDE', 'DEMAND-SIDE'] names = ['COST TYPE'] self.outputs.c_payback = pd.concat([util.DfOper.divi([supply_side_df, sales_df]), util.DfOper.divi([demand_side_df, sales_df])],keys=keys,names=names) self.outputs.c_payback = self.outputs.c_payback[np.isfinite(self.outputs.c_payback.values)] self.outputs.c_payback = self.outputs.c_payback.replace([np.inf,np.nan],0) for sector in self.demand.sectors.values(): for subsector in sector.subsectors.values(): if hasattr(subsector,'stock') and subsector.sub_type!='link': indexer = util.level_specific_indexer(self.outputs.c_payback,'subsector',subsector.id) self.outputs.c_payback.loc[indexer,'unit'] = subsector.stock.unit.upper() self.outputs.c_payback = self.outputs.c_payback.set_index('unit', append=True) self.outputs.c_payback.columns = [cost_unit.upper()] self.outputs.c_payback['lifetime_year'] = self.outputs.c_payback.index.get_level_values('year')-self.outputs.c_payback.index.get_level_values('vintage')+1 self.outputs.c_payback = self.outputs.c_payback.set_index('lifetime_year',append=True) self.outputs.c_payback = util.remove_df_levels(self.outputs.c_payback,'year') self.outputs.c_payback = self.outputs.c_payback.groupby(level = [x for x in self.outputs.c_payback.index.names if x !='lifetime_year']).transform(lambda x: x.cumsum()) self.outputs.c_payback = self.outputs.c_payback[self.outputs.c_payback[cost_unit.upper()]!=0] self.outputs.c_payback = self.outputs.return_cleaned_output('c_payback') def calculate_d_payback(self): cost_unit = cfg.cfgfile.get('case','currency_year_id') + " " + cfg.cfgfile.get('case','currency_name') initial_vintage = min(cfg.supply_years) demand_side_df = self.demand.d_annual_costs_payback demand_side_df.columns = ['value'] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('vintage')>=initial_vintage] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('year')>=initial_vintage] sales_df = copy.deepcopy(self.demand.outputs.d_sales) util.replace_index_name(sales_df,'vintage','year') sales_df = sales_df[sales_df.index.get_level_values('vintage')>=initial_vintage] sales_df = util.add_and_set_index(sales_df,'year',cfg.supply_years) sales_df.index = sales_df.index.reorder_levels(demand_side_df.index.names) sales_df = sales_df.reindex(demand_side_df.index).sort_index() self.demand.outputs.d_payback = util.DfOper.divi([demand_side_df, sales_df]) self.demand.outputs.d_payback = self.demand.outputs.d_payback[np.isfinite(self.demand.outputs.d_payback.values)] self.demand.outputs.d_payback = self.demand.outputs.d_payback.replace([np.inf,np.nan],0) for sector in self.demand.sectors.values(): for subsector in sector.subsectors.values(): if hasattr(subsector,'stock') and subsector.sub_type!='link': indexer = util.level_specific_indexer(self.demand.outputs.d_payback,'subsector',subsector.id) self.demand.outputs.d_payback.loc[indexer,'unit'] = subsector.stock.unit.upper() self.demand.outputs.d_payback = self.demand.outputs.d_payback.set_index('unit', append=True) self.demand.outputs.d_payback.columns = [cost_unit.upper()] self.demand.outputs.d_payback['lifetime_year'] = self.demand.outputs.d_payback.index.get_level_values('year')-self.demand.outputs.d_payback.index.get_level_values('vintage')+1 self.demand.outputs.d_payback = self.demand.outputs.d_payback.set_index('lifetime_year',append=True) self.demand.outputs.d_payback = util.remove_df_levels(self.demand.outputs.d_payback,'year') self.demand.outputs.d_payback = self.demand.outputs.d_payback.groupby(level = [x for x in self.demand.outputs.d_payback.index.names if x !='lifetime_year']).transform(lambda x: x.cumsum()) self.demand.outputs.d_payback = self.demand.outputs.d_payback[self.demand.outputs.d_payback[cost_unit.upper()]!=0] self.demand.outputs.d_payback = self.demand.outputs.return_cleaned_output('d_payback') def calculate_d_payback_energy(self): initial_vintage = min(cfg.supply_years) demand_side_df = self.demand.d_all_energy_demand_payback demand_side_df.columns = ['value'] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('vintage')>=initial_vintage] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('year')>=initial_vintage] sales_df = copy.deepcopy(self.demand.outputs.d_sales) util.replace_index_name(sales_df,'vintage','year') sales_df = sales_df[sales_df.index.get_level_values('vintage')>=initial_vintage] sales_df = util.add_and_set_index(sales_df,'year',cfg.supply_years) # sales_df.index = sales_df.index.reorder_levels(demand_side_df.index.names) # sales_df = sales_df.reindex(demand_side_df.index).sort_index() self.demand.outputs.d_payback_energy = util.DfOper.divi([demand_side_df, sales_df]) self.demand.outputs.d_payback_energy = self.demand.outputs.d_payback_energy[np.isfinite(self.demand.outputs.d_payback_energy.values)] self.demand.outputs.d_payback_energy = self.demand.outputs.d_payback_energy.replace([np.inf,np.nan],0) for sector in self.demand.sectors.values(): for subsector in sector.subsectors.values(): if hasattr(subsector,'stock') and subsector.sub_type!='link': indexer = util.level_specific_indexer(self.demand.outputs.d_payback_energy,'subsector',subsector.id) self.demand.outputs.d_payback_energy.loc[indexer,'unit'] = subsector.stock.unit.upper() self.demand.outputs.d_payback_energy = self.demand.outputs.d_payback_energy.set_index('unit', append=True) self.demand.outputs.d_payback_energy.columns = [cfg.calculation_energy_unit.upper()] self.demand.outputs.d_payback_energy['lifetime_year'] = self.demand.outputs.d_payback_energy.index.get_level_values('year')-self.demand.outputs.d_payback_energy.index.get_level_values('vintage')+1 self.demand.outputs.d_payback_energy = self.demand.outputs.d_payback_energy.set_index('lifetime_year',append=True) self.demand.outputs.d_payback_energy = util.remove_df_levels(self.demand.outputs.d_payback_energy,'year') self.demand.outputs.d_payback_energy = self.demand.outputs.d_payback_energy.groupby(level = [x for x in self.demand.outputs.d_payback_energy.index.names if x !='lifetime_year']).transform(lambda x: x.cumsum()) self.demand.outputs.d_payback_energy = self.demand.outputs.d_payback_energy[self.demand.outputs.d_payback_energy[cfg.calculation_energy_unit.upper()]!=0] self.demand.outputs.d_payback_energy = self.demand.outputs.return_cleaned_output('d_payback_energy') def calculate_combined_emissions_results(self): #calculate and format export emissions if self.supply.export_emissions is not None: setattr(self.outputs,'export_emissions',self.supply.export_emissions) if 'supply_geography' not in cfg.output_combined_levels: util.remove_df_levels(self.outputs.export_emissions, cfg.primary_geography +'_supply') self.export_emissions_df = self.outputs.return_cleaned_output('export_emissions') del self.outputs.export_emissions util.replace_index_name(self.export_emissions_df, 'FINAL_ENERGY','SUPPLY_NODE_EXPORT') keys = ["EXPORT","SUPPLY"] names = ['EXPORT/DOMESTIC', "SUPPLY/DEMAND"] for key,name in zip(keys,names): self.export_emissions_df = pd.concat([self.export_emissions_df],keys=[key],names=[name]) else: self.export_emissions_df = None #calculate and format emobodied supply emissions self.embodied_emissions_df = self.demand.outputs.return_cleaned_output('demand_embodied_emissions') # del self.demand.outputs.demand_embodied_emissions keys = ["DOMESTIC","SUPPLY"] names = ['EXPORT/DOMESTIC', "SUPPLY/DEMAND"] for key,name in zip(keys,names): self.embodied_emissions_df = pd.concat([self.embodied_emissions_df],keys=[key],names=[name]) #calculte and format direct demand emissions self.direct_emissions_df = self.demand.outputs.return_cleaned_output('demand_direct_emissions') # del self.demand.outputs.demand_direct_emissions keys = ["DOMESTIC","DEMAND"] names = ['EXPORT/DOMESTIC', "SUPPLY/DEMAND"] for key, name in zip(keys, names): self.direct_emissions_df = pd.concat([self.direct_emissions_df], keys=[key], names=[name]) if cfg.primary_geography+'_supply' in cfg.output_combined_levels: keys = self.direct_emissions_df.index.get_level_values(cfg.primary_geography.upper()).values names = cfg.primary_geography.upper() +'_SUPPLY' self.direct_emissions_df[names] = keys self.direct_emissions_df.set_index(names,append=True,inplace=True) keys = ['EXPORTED', 'SUPPLY-SIDE', 'DEMAND-SIDE'] names = ['EMISSIONS TYPE'] self.outputs.c_emissions = util.df_list_concatenate([self.export_emissions_df, self.embodied_emissions_df, self.direct_emissions_df],keys=keys,new_names = names) util.replace_index_name(self.outputs.c_emissions, cfg.primary_geography.upper() +'-EMITTED', cfg.primary_geography.upper() +'_SUPPLY') util.replace_index_name(self.outputs.c_emissions, cfg.primary_geography.upper() +'-CONSUMED', cfg.primary_geography.upper()) self.outputs.c_emissions= self.outputs.c_emissions[self.outputs.c_emissions['VALUE']!=0] emissions_unit = cfg.cfgfile.get('case','mass_unit') self.outputs.c_emissions.columns = [emissions_unit.upper()] def calculate_combined_energy_results(self): energy_unit = cfg.calculation_energy_unit if self.supply.export_costs is not None: setattr(self.outputs,'export_energy',self.supply.export_energy) self.export_energy = self.outputs.return_cleaned_output('export_energy') del self.outputs.export_energy util.replace_index_name(self.export_energy, 'FINAL_ENERGY','SUPPLY_NODE_EXPORT') keys = ["EXPORT","EMBODIED"] names = ['EXPORT/DOMESTIC', 'ENERGY ACCOUNTING'] for key,name in zip(keys,names): self.export_energy = pd.concat([self.export_energy],keys=[key],names=[name]) else: self.export_energy = None self.embodied_energy = self.demand.outputs.return_cleaned_output('demand_embodied_energy') self.embodied_energy = self.embodied_energy[self.embodied_energy ['VALUE']!=0] keys = ['DOMESTIC','EMBODIED'] names = ['EXPORT/DOMESTIC', 'ENERGY ACCOUNTING'] for key,name in zip(keys,names): self.embodied_energy = pd.concat([self.embodied_energy],keys=[key],names=[name]) self.final_energy = self.demand.outputs.return_cleaned_output('d_energy') self.final_energy = self.final_energy[self.final_energy.index.get_level_values('YEAR')>=int(cfg.cfgfile.get('case','current_year'))] keys = ['DOMESTIC','FINAL'] names = ['EXPORT/DOMESTIC', 'ENERGY ACCOUNTING'] for key,name in zip(keys,names): self.final_energy = pd.concat([self.final_energy],keys=[key],names=[name]) # self.outputs.c_energy = pd.concat([self.embodied_energy, self.final_energy],keys=['DROP'],names=['DROP']) for name in [x for x in self.embodied_energy.index.names if x not in self.final_energy.index.names]: self.final_energy[name] = "N/A" self.final_energy.set_index(name,append=True,inplace=True) if self.export_energy is not None: for name in [x for x in self.embodied_energy.index.names if x not in self.export_energy.index.names]: self.export_energy[name] = "N/A" self.export_energy.set_index(name,append=True,inplace=True) self.export_energy = self.export_energy.groupby(level=self.embodied_energy.index.names).sum() self.export_energy = self.export_energy.reorder_levels(self.embodied_energy.index.names) self.final_energy = self.final_energy.groupby(level=self.embodied_energy.index.names).sum() self.final_energy = self.final_energy.reorder_levels(self.embodied_energy.index.names) self.outputs.c_energy = pd.concat([self.embodied_energy,self.final_energy,self.export_energy]) self.outputs.c_energy= self.outputs.c_energy[self.outputs.c_energy['VALUE']!=0] self.outputs.c_energy.columns = [energy_unit.upper()] def export_io(self): io_table_write_step = int(cfg.cfgfile.get('output_detail','io_table_write_step')) io_table_years = sorted([min(cfg.supply_years)] + range(max(cfg.supply_years), min(cfg.supply_years), -io_table_write_step)) df_list = [] for year in io_table_years: sector_df_list = [] keys = self.supply.demand_sectors name = ['sector'] for sector in self.supply.demand_sectors: sector_df_list.append(self.supply.io_dict[year][sector]) year_df = pd.concat(sector_df_list, keys=keys,names=name) year_df = pd.concat([year_df]*len(keys),keys=keys,names=name,axis=1) df_list.append(year_df) keys = io_table_years name = ['year'] df = pd.concat(df_list,keys=keys,names=name) for row_sector in self.supply.demand_sectors: for col_sector in self.supply.demand_sectors: if row_sector != col_sector: df.loc[util.level_specific_indexer(df,'sector',row_sector),util.level_specific_indexer(df,'sector',col_sector,axis=1)] = 0 self.supply.outputs.io = df result_df = self.supply.outputs.return_cleaned_output('io') keys = [self.scenario.name.upper(), cfg.timestamp] names = ['SCENARIO','TIMESTAMP'] for key, name in zip(keys,names): result_df = pd.concat([result_df], keys=[key],names=[name]) Output.write(result_df, 's_io.csv', os.path.join(cfg.workingdir, 'supply_outputs')) # self.export_stacked_io() def export_stacked_io(self): df = copy.deepcopy(self.supply.outputs.io) df.index.names = [x + '_input'if x!= 'year' else x for x in df.index.names ] df = df.stack(level=df.columns.names).to_frame() df.columns = ['value'] self.supply.outputs.stacked_io = df result_df = self.supply.outputs.return_cleaned_output('stacked_io') keys = [self.scenario.name.upper(), cfg.timestamp] names = ['SCENARIO','TIMESTAMP'] for key, name in zip(keys,names): result_df = pd.concat([result_df], keys=[key],names=[name]) Output.write(result_df, 's_stacked_io.csv', os.path.join(cfg.workingdir, 'supply_outputs'))
def test_init_with_negative_quantity_raises(): with pytest.raises(ValueError): Demand(quantity=-1)
def test_init_with_missing_quantity_raises(): with pytest.raises(ValueError): Demand(quantity=None)
def test_init_with_invalid_time_unit_raises(): with pytest.raises(ValueError): Demand(quantity=1, time_unit='X')
def test_init_with_valid_time_unit_captures(): d = Demand(quantity=1, time_unit='W') assert d.time_unit == 'W'
def test_init_with_positive_quantity_captures(): d = Demand(quantity=1) assert d.quantity == 1
class PathwaysModel(object): """ Highest level classification of the definition of an energy system. Includes the primary geography of the energy system (i.e. country name) as well as the author. """ def __init__(self, cfgfile_path, custom_pint_definitions_path=None, name=None, author=None): self.cfgfile_path = cfgfile_path self.custom_pint_definitions_path = custom_pint_definitions_path self.model_config(cfgfile_path, custom_pint_definitions_path) self.name = cfg.cfgfile.get('case', 'scenario') if name is None else name self.author = cfg.cfgfile.get('case', 'author') if author is None else author self.scenario_dict = dict(zip(util.sql_read_table('Scenarios','id', return_iterable=True, is_active=True), util.sql_read_table('Scenarios','name', return_iterable=True, is_active=True))) self.outputs = Output() self.geography = cfg.cfgfile.get('case', 'primary_geography') def model_config(self, cfgfile_path, custom_pint_definitions_path): cfg.init_cfgfile(cfgfile_path) cfg.init_db() cfg.path = custom_pint_definitions_path cfg.init_pint(custom_pint_definitions_path) cfg.init_geo() cfg.init_date_lookup() if shape.shapes.rerun: shape.shapes.create_empty_shapes() # shape.shapes.activate_shape(cfg.electricity_energy_type_shape_id) cfg.init_outputs_id_map() def configure_energy_system(self): print 'configuring energy system' self.demand = Demand(self.cfgfile_path, self.custom_pint_definitions_path) self.supply = Supply(os.path.join(os.getcwd(),'outputs'),self.cfgfile_path, self.custom_pint_definitions_path) self.configure_demand() self.configure_supply() def populate_energy_system(self): self.populate_demand_system() self.populate_supply_system() def populate_shapes(self): print 'processing shapes' if shape.shapes.rerun: shape.shapes.initiate_active_shapes() shape.shapes.process_active_shapes() def populate_measures(self, scenario_id): self.scenario_id = scenario_id self.scenario = self.scenario_dict[self.scenario_id] self.demand_case_id = util.sql_read_table('Scenarios','demand_case',id=self.scenario_id) self.populate_demand_measures() self.supply_case_id = util.sql_read_table('Scenarios','supply_case',id=self.scenario_id) self.populate_supply_measures() def calculate(self): self.calculate_demand_only() self.pass_results_to_supply() self.calculate_supply() def configure_demand(self): """Read in and initialize data""" # Drivers must come first self.demand.add_drivers() # Sectors requires drivers be read in self.demand.add_sectors() for sector in self.demand.sectors.values(): # print 'configuring the %s sector' %sector.name sector.add_subsectors() def configure_supply(self): self.supply.add_node_list() def populate_demand_system(self): print 'remapping drivers' self.demand.remap_drivers() print 'populating energy system data' for sector in self.demand.sectors.values(): print ' '+sector.name+' sector' # print 'reading energy system data for the %s sector' %sector.name for subsector in sector.subsectors.values(): print ' '+subsector.name subsector.add_energy_system_data() sector.precursor_dict() def populate_supply_system(self): self.supply.add_nodes() def populate_demand_measures(self): for sector in self.demand.sectors.values(): # print 'reading %s measures' %sector.name for subsector in sector.subsectors.values(): subsector.add_measures(self.demand_case_id) def populate_supply_measures(self): self.supply.add_measures(self.supply_case_id) def calculate_demand_only(self): self.demand.calculate_demand() print "aggregating demand results" self.demand.aggregate_results() def calculate_supply(self): self.supply.initial_calculate() self.supply.calculate_loop() self.supply.final_calculate() def pass_results_to_supply(self): for sector in self.demand.sectors.values(): sector.aggregate_subsector_energy_for_supply_side() self.demand.aggregate_sector_energy_for_supply_side() self.supply.demand_object = self.demand def pass_results_to_demand(self): print "calculating link to supply" self.demand.link_to_supply(self.supply.emissions_demand_link, self.supply.demand_emissions_rates, self.supply.energy_demand_link, self.supply.cost_demand_link) def calculate_combined_results(self): print "calculating combined emissions results" self.calculate_combined_emissions_results() print "calculating combined cost results" self.calculate_combined_cost_results() print "calculating combined energy results" self.calculate_combined_energy_results() def export_results(self): for attribute in dir(self.outputs): if isinstance(getattr(self.outputs,attribute), pd.DataFrame): result_df = getattr(self.outputs, attribute) keys = [self.scenario.upper(),str(datetime.now().replace(second=0,microsecond=0))] names = ['SCENARIO','TIMESTAMP'] for key, name in zip(keys,names): result_df = pd.concat([result_df],keys=[key],names=[name]) ExportMethods.writeobj(attribute,result_df, os.path.join(os.getcwd(),'combined_outputs'), append_results=True) for attribute in dir(self.demand.outputs): if isinstance(getattr(self.demand.outputs,attribute), pd.DataFrame): result_df = self.demand.outputs.return_cleaned_output(attribute) keys = [self.scenario.upper(),str(datetime.now().replace(second=0,microsecond=0))] names = ['SCENARIO','TIMESTAMP'] for key, name in zip(keys,names): result_df = pd.concat([result_df],keys=[key],names=[name]) ExportMethods.writeobj(attribute,result_df, os.path.join(os.getcwd(),'demand_outputs'), append_results=True) for attribute in dir(self.supply.outputs): if isinstance(getattr(self.supply.outputs,attribute), pd.DataFrame): result_df = self.supply.outputs.return_cleaned_output(attribute) keys = [self.scenario.upper(),str(datetime.now().replace(second=0,microsecond=0))] names = ['SCENARIO','TIMESTAMP'] for key, name in zip(keys,names): result_df = pd.concat([result_df],keys=[key],names=[name]) ExportMethods.writeobj(attribute,result_df, os.path.join(os.getcwd(),'supply_outputs'), append_results=True) def calculate_combined_cost_results(self): #calculate and format export costs cost_unit = cfg.cfgfile.get('case','currency_year_id') + " " + cfg.cfgfile.get('case','currency_name') if self.supply.export_costs is not None: setattr(self.outputs,'export_costs',self.supply.export_costs) self.export_costs_df = self.outputs.return_cleaned_output('export_costs') del self.outputs.export_costs util.replace_index_name(self.export_costs_df, 'FINAL_ENERGY','SUPPLY_NODE_EXPORT') keys = ["EXPORT","SUPPLY"] names = ['EXPORT/DOMESTIC', "SUPPLY/DEMAND"] for key,name in zip(keys,names): self.export_costs_df = pd.concat([self.export_costs_df],keys=[key],names=[name]) self.export_costs_df.columns = [cost_unit.upper()] else: self.export_costs_df = None #calculate and format emobodied supply costs self.embodied_energy_costs_df = self.demand.outputs.return_cleaned_output('demand_embodied_energy_costs') self.embodied_energy_costs_df.columns = [cost_unit.upper()] # del self.demand.outputs.demand_embodied_energy_costs keys = ["DOMESTIC","SUPPLY"] names = ['EXPORT/DOMESTIC', "SUPPLY/DEMAND"] for key,name in zip(keys,names): self.embodied_energy_costs_df = pd.concat([self.embodied_energy_costs_df],keys=[key],names=[name]) #calculte and format direct demand emissions self.demand_costs_df= self.demand.outputs.return_cleaned_output('levelized_costs') # del self.demand.outputs.levelized_costs keys = ["DOMESTIC","DEMAND"] names = ['EXPORT/DOMESTIC', "SUPPLY/DEMAND"] for key,name in zip(keys,names): self.demand_costs_df = pd.concat([self.demand_costs_df],keys=[key],names=[name]) # levels_to_keep = cfg.output_levels # levels_to_keep = [x.upper() for x in levels_to_keep] # levels_to_keep += names + [self.geography.upper() +'_SUPPLY', 'SUPPLY_NODE'] keys = ['EXPORTED', 'SUPPLY-SIDE', 'DEMAND-SIDE'] names = ['COST TYPE'] self.outputs.costs = util.df_list_concatenate([self.export_costs_df, self.embodied_energy_costs_df, self.demand_costs_df],keys=keys,new_names=names) # util.replace_index_name(self.outputs.costs, self.geography.upper() +'_EARNED', self.geography.upper() +'_SUPPLY') # util.replace_index_name(self.outputs.costs, self.geography.upper() +'_CONSUMED', self.geography.upper()) self.outputs.costs[self.outputs.costs<0]=0 self.outputs.costs= self.outputs.costs[self.outputs.costs[cost_unit.upper()]!=0] # self.outputs.costs.sort(inplace=True) def calculate_combined_emissions_results(self): #calculate and format export emissions if self.supply.export_emissions is not None: setattr(self.outputs,'export_emissions',self.supply.export_emissions) if 'supply_geography' not in cfg.output_combined_levels: util.remove_df_levels(self.outputs.export_emissions,self.geography +'_supply') self.export_emissions_df = self.outputs.return_cleaned_output('export_emissions') del self.outputs.export_emissions util.replace_index_name(self.export_emissions_df, 'FINAL_ENERGY','SUPPLY_NODE_EXPORT') keys = ["EXPORT","SUPPLY"] names = ['EXPORT/DOMESTIC', "SUPPLY/DEMAND"] for key,name in zip(keys,names): self.export_emissions_df = pd.concat([self.export_emissions_df],keys=[key],names=[name]) else: self.export_emissions_df = None #calculate and format emobodied supply emissions self.embodied_emissions_df = self.demand.outputs.return_cleaned_output('demand_embodied_emissions') # del self.demand.outputs.demand_embodied_emissions keys = ["DOMESTIC","SUPPLY"] names = ['EXPORT/DOMESTIC', "SUPPLY/DEMAND"] for key,name in zip(keys,names): self.embodied_emissions_df = pd.concat([self.embodied_emissions_df],keys=[key],names=[name]) #calculte and format direct demand emissions self.direct_emissions_df= self.demand.outputs.return_cleaned_output('demand_direct_emissions') # del self.demand.outputs.demand_direct_emissions keys = ["DOMESTIC","DEMAND"] names = ['EXPORT/DOMESTIC', "SUPPLY/DEMAND"] for key,name in zip(keys,names): self.direct_emissions_df = pd.concat([self.direct_emissions_df],keys=[key],names=[name]) if 'supply_geography' in cfg.output_combined_levels: keys = self.direct_emissions_df.index.get_level_values(self.geography.upper()).values names = self.geography.upper() +'_SUPPLY' self.direct_emissions_df[names] = keys self.direct_emissions_df.set_index(names,append=True,inplace=True) # levels_to_keep = cfg.output_levels # levels_to_keep = [x.upper() for x in levels_to_keep] # levels_to_keep += names + [self.geography.upper() +'_SUPPLY', 'SUPPLY_NODE'] keys = ['EXPORTED', 'SUPPLY-SIDE', 'DEMAND-SIDE'] names = ['EMISSIONS TYPE'] self.outputs.emissions = util.df_list_concatenate([self.export_emissions_df, self.embodied_emissions_df, self.direct_emissions_df],keys=keys,new_names = names) # util.replace_index_name(self.outputs.emissions, "ENERGY","FINAL_ENERGY") util.replace_index_name(self.outputs.emissions, self.geography.upper() +'_EMITTED', self.geography.upper() +'_SUPPLY') util.replace_index_name(self.outputs.emissions, self.geography.upper() +'_CONSUMED', self.geography.upper()) self.outputs.emissions= self.outputs.emissions[self.outputs.emissions['VALUE']!=0] emissions_unit = cfg.cfgfile.get('case','mass_unit') self.outputs.emissions.columns = [emissions_unit.upper()] # self.outputs.emissions.sort(inplace=True) def calculate_combined_energy_results(self): self.embodied_energy = self.demand.outputs.return_cleaned_output('demand_embodied_energy') self.embodied_energy = self.embodied_energy[self.embodied_energy ['VALUE']!=0] self.final_energy = self.demand.outputs.return_cleaned_output('energy') self.final_energy = self.final_energy[self.final_energy.index.get_level_values('YEAR')>=int(cfg.cfgfile.get('case','current_year'))] self.embodied_energy['ENERGY ACCOUNTING'] = 'EMBODIED' self.final_energy['ENERGY ACCOUNTING'] = 'FINAL' self.embodied_energy.set_index('ENERGY ACCOUNTING',append=True,inplace=True) self.final_energy.set_index('ENERGY ACCOUNTING',append=True,inplace=True) # self.outputs.energy = pd.concat([self.embodied_energy, self.final_energy],keys=['DROP'],names=['DROP']) for name in [x for x in self.embodied_energy.index.names if x not in self.final_energy.index.names]: self.final_energy[name] = "N/A" self.final_energy.set_index(name,append=True,inplace=True) self.final_energy = self.final_energy.groupby(level=self.embodied_energy.index.names).sum() self.final_energy = self.final_energy.reorder_levels(self.embodied_energy.index.names) self.outputs.energy = pd.concat([self.embodied_energy,self.final_energy]) self.outputs.energy= self.outputs.energy[self.outputs.energy['VALUE']!=0] energy_unit = cfg.cfgfile.get('case','energy_unit') self.outputs.energy.columns = [energy_unit.upper()]
def configure_energy_system(self): print 'configuring energy system' self.demand = Demand(self.cfgfile_path, self.custom_pint_definitions_path) self.supply = Supply(os.path.join(os.getcwd(),'outputs'),self.cfgfile_path, self.custom_pint_definitions_path) self.configure_demand() self.configure_supply()
class PathwaysModel(object): """ Highest level classification of the definition of an energy system. """ def __init__(self, scenario_id, api_run=False): self.scenario_id = scenario_id self.scenario = Scenario(self.scenario_id) self.api_run = api_run self.outputs = Output() self.demand = Demand(self.scenario) self.supply = None self.demand_solved, self.supply_solved = False, False def run(self, scenario_id, solve_demand, solve_supply, load_demand, load_supply, export_results, save_models, append_results, rio_scenario): #try: self.scenario_id = scenario_id self.scenario = Scenario(self.scenario_id) self.rio_scenario = rio_scenario if solve_demand and not (load_demand or load_supply): self.calculate_demand(save_models) if not append_results: self.remove_old_results() # it is nice if when loading a demand side object to rerun supply, it doesn't re-output these results every time if self.demand_solved and export_results and not self.api_run and not (load_demand and solve_supply): # self.demand.create_electricity_reconciliation() # self.demand.output_subsector_electricity_profiles() self.export_result_to_csv('demand_outputs') if solve_supply: if load_demand: # if we are loading the demand, we are changing the supply measures and want to reload our scenarios self.scenario = Scenario(self.scenario_id) self.supply = Supply(self.scenario, demand_object=self.demand,rio_scenario=rio_scenario) self.calculate_supply(save_models) if load_demand and solve_supply and export_results: # we do this now because we delayed before self.export_result_to_csv('demand_outputs') if self.supply_solved and export_results and (load_supply or solve_supply): self.supply.calculate_supply_outputs() self.pass_supply_results_back_to_demand() self.calculate_combined_results() self.outputs.electricity_reconciliation = self.demand.electricity_reconciliation # we want to write these to outputs self.export_result_to_csv('supply_outputs') self.export_result_to_csv('combined_outputs') self.export_io() #except: # pickle the model in the event that it crashes #if save_models: # if cfg.rio_supply_run: # Output.pickle(self, file_name=self.rio_scenario + cfg.model_error_append_name, path=cfg.workingdir) # else: # Output.pickle(self, file_name=str(self.scenario_id) + cfg.model_error_append_name, # path=cfg.workingdir) def calculate_demand(self, save_models): self.demand.setup_and_solve() self.demand_solved = True if cfg.output_payback == 'true': if self.demand.d_all_energy_demand_payback is not None: self.calculate_d_payback() self.calculate_d_payback_energy() if save_models: if cfg.rio_supply_run: Output.pickle(self, file_name=str(self.scenario_id) + cfg.demand_model_append_name, path=cfg.workingdir) else: Output.pickle(self, file_name=str(self.scenario_id) + cfg.demand_model_append_name, path=cfg.workingdir) def calculate_supply(self, save_models): if not self.demand_solved: raise ValueError('demand must be solved first before supply') logging.info('Configuring energy system supply') self.supply.add_nodes() self.supply.add_measures() self.supply.initial_calculate() self.supply.calculated_years = [] self.supply.calculate_loop(self.supply.years, self.supply.calculated_years) self.supply.final_calculate() self.supply_solved = True if save_models: if cfg.rio_supply_run: Output.pickle(self, file_name=self.rio_scenario + cfg.full_model_append_name, path=cfg.workingdir) else: Output.pickle(self, file_name=str(self.scenario_id) + cfg.full_model_append_name, path=cfg.workingdir) # we don't need the demand side object any more, so we can remove it to save drive space # if not cfg.rio_supply_run: # if os.path.isfile(os.path.join(cfg.workingdir, str(self.scenario_id) + cfg.demand_model_append_name)): # os.remove(os.path.join(cfg.workingdir, str(self.scenario_id) + cfg.demand_model_append_name)) def pass_supply_results_back_to_demand(self): # we need to geomap to the combined output geography emissions_demand_link = GeoMapper.geo_map(self.supply.emissions_demand_link, GeoMapper.supply_primary_geography, GeoMapper.combined_outputs_geography, 'intensity') demand_emissions_rates = GeoMapper.geo_map(self.supply.demand_emissions_rates, GeoMapper.supply_primary_geography, GeoMapper.combined_outputs_geography, 'intensity') energy_demand_link = GeoMapper.geo_map(self.supply.energy_demand_link, GeoMapper.supply_primary_geography, GeoMapper.combined_outputs_geography, 'intensity') cost_demand_link = GeoMapper.geo_map(self.supply.cost_demand_link, GeoMapper.supply_primary_geography, GeoMapper.combined_outputs_geography, 'intensity') logging.info("Calculating link to supply") self.demand.link_to_supply(emissions_demand_link, demand_emissions_rates, energy_demand_link, cost_demand_link) if cfg.output_tco == 'true': if hasattr(self,'d_energy_tco'): self.demand.link_to_supply_tco(emissions_demand_link, demand_emissions_rates, cost_demand_link) else: print "demand side has not been run with tco outputs set to 'true'" if cfg.output_payback == 'true': if hasattr(self,'demand.d_all_energy_demand_payback'): self.demand.link_to_supply_payback(emissions_demand_link, demand_emissions_rates, cost_demand_link) else: print "demand side has not been run with tco outputs set to 'true'" def calculate_combined_results(self): logging.info("Calculating combined emissions results") self.calculate_combined_emissions_results() logging.info("Calculating combined cost results") self.calculate_combined_cost_results() logging.info("Calculating combined energy results") self.calculate_combined_energy_results() if cfg.output_tco == 'true': if self.demand.d_energy_tco is not None: self.calculate_tco() if cfg.output_payback == 'true': if self.demand.d_all_energy_demand_payback is not None: self.calculate_payback() def remove_old_results(self): folder_names = ['combined_outputs', 'demand_outputs', 'supply_outputs', 'dispatch_outputs'] for folder_name in folder_names: folder = os.path.join(cfg.workingdir, folder_name) if os.path.isdir(folder): shutil.rmtree(folder) def export_result_to_csv(self, result_name): if result_name=='combined_outputs': res_obj = self.outputs elif result_name=='demand_outputs': res_obj = self.demand.outputs elif result_name=='supply_outputs': res_obj = self.supply.outputs else: raise ValueError('result_name not recognized') def clean_and_write(result_df, attribute): """ :param result_df: pandas dataframe :param attribute: string """ if cfg.rio_supply_run and self.supply is not None: keys = [self.supply.rio_scenario.upper(), cfg.timestamp] else: keys = [self.scenario.name.upper(), cfg.timestamp] names = ['SCENARIO', 'TIMESTAMP'] for key, name in zip(keys, names): result_df = pd.concat([result_df], keys=[key], names=[name]) result_df = result_df.fillna(0) if attribute in ( 'hourly_dispatch_results', 'electricity_reconciliation', 'hourly_marginal_cost', 'hourly_production_cost'): # Special case for hourly dispatch results where we want to write them outside of supply_outputs Output.write(result_df, attribute + '.csv', os.path.join(cfg.workingdir, 'dispatch_outputs')) else: Output.write(result_df, attribute + '.csv', os.path.join(cfg.workingdir, result_name)) for attribute in dir(res_obj): if isinstance(getattr(res_obj, attribute), list): for df in getattr(res_obj, attribute): result_df = getattr(res_obj, 'clean_df')(df) clean_and_write(result_df,attribute) elif isinstance(getattr(res_obj, attribute), pd.DataFrame): result_df = getattr(res_obj, 'clean_df')(getattr(res_obj, attribute)) clean_and_write(result_df, attribute) else: continue def calculate_tco(self): cost_unit = cfg.getParam('currency_year') + " " + cfg.getParam('currency_name') initial_vintage = min(cfg.supply_years) supply_side_df = self.demand.outputs.demand_embodied_energy_costs_tco supply_side_df = supply_side_df[supply_side_df.index.get_level_values('vintage')>=initial_vintage] demand_side_df = self.demand.d_levelized_costs_tco demand_side_df.columns = ['value'] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('vintage')>=initial_vintage] service_demand_df = self.demand.d_service_demand_tco service_demand_df = service_demand_df[service_demand_df.index.get_level_values('vintage')>=initial_vintage] keys = ['SUPPLY-SIDE', 'DEMAND-SIDE'] names = ['COST TYPE'] self.outputs.c_tco = pd.concat([util.DfOper.divi([supply_side_df,util.remove_df_levels(service_demand_df,'unit')]), util.DfOper.divi([demand_side_df,util.remove_df_levels(service_demand_df,'unit')])], keys=keys,names=names) self.outputs.c_tco = self.outputs.c_tco.replace([np.inf,np.nan],0) self.outputs.c_tco[self.outputs.c_tco<0]=0 for sector in self.demand.sectors.values(): for subsector in sector.subsectors.values(): if hasattr(subsector,'service_demand') and hasattr(subsector,'stock'): indexer = util.level_specific_indexer(self.outputs.c_tco,'subsector',subsector.id) self.outputs.c_tco.loc[indexer,'unit'] = subsector.service_demand.unit.upper() self.outputs.c_tco = self.outputs.c_tco.set_index('unit',append=True) self.outputs.c_tco.columns = [cost_unit.upper()] self.outputs.c_tco= self.outputs.c_tco[self.outputs.c_tco[cost_unit.upper()]!=0] self.outputs.c_tco = self.outputs.return_cleaned_output('c_tco') def calculate_payback(self): cost_unit = cfg.getParam('currency_year') + " " + cfg.getParam('currency_name') initial_vintage = min(cfg.supply_years) supply_side_df = self.demand.outputs.demand_embodied_energy_costs_payback supply_side_df = supply_side_df[supply_side_df.index.get_level_values('vintage')>=initial_vintage] supply_side_df = supply_side_df[supply_side_df.index.get_level_values('year')>=initial_vintage] supply_side_df = supply_side_df.sort_index() demand_side_df = self.demand.d_annual_costs_payback demand_side_df.columns = ['value'] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('vintage')>=initial_vintage] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('year')>=initial_vintage] demand_side_df = demand_side_df.reindex(supply_side_df.index).sort_index() sales_df = copy.deepcopy(self.demand.outputs.d_sales) util.replace_index_name(sales_df,'vintage','year') sales_df = sales_df[sales_df.index.get_level_values('vintage')>=initial_vintage] sales_df = util.add_and_set_index(sales_df,'year',cfg.supply_years) sales_df.index = sales_df.index.reorder_levels(supply_side_df.index.names) sales_df = sales_df.reindex(supply_side_df.index).sort_index() keys = ['SUPPLY-SIDE', 'DEMAND-SIDE'] names = ['COST TYPE'] self.outputs.c_payback = pd.concat([util.DfOper.divi([supply_side_df, sales_df]), util.DfOper.divi([demand_side_df, sales_df])],keys=keys,names=names) self.outputs.c_payback = self.outputs.c_payback[np.isfinite(self.outputs.c_payback.values)] self.outputs.c_payback = self.outputs.c_payback.replace([np.inf,np.nan],0) for sector in self.demand.sectors.values(): for subsector in sector.subsectors.values(): if hasattr(subsector,'stock') and subsector.sub_type!='link': indexer = util.level_specific_indexer(self.outputs.c_payback,'subsector',subsector.id) self.outputs.c_payback.loc[indexer,'unit'] = subsector.stock.unit.upper() self.outputs.c_payback = self.outputs.c_payback.set_index('unit', append=True) self.outputs.c_payback.columns = [cost_unit.upper()] self.outputs.c_payback['lifetime_year'] = self.outputs.c_payback.index.get_level_values('year')-self.outputs.c_payback.index.get_level_values('vintage')+1 self.outputs.c_payback = self.outputs.c_payback.set_index('lifetime_year',append=True) self.outputs.c_payback = util.remove_df_levels(self.outputs.c_payback,'year') self.outputs.c_payback = self.outputs.c_payback.groupby(level = [x for x in self.outputs.c_payback.index.names if x !='lifetime_year']).transform(lambda x: x.cumsum()) self.outputs.c_payback = self.outputs.c_payback[self.outputs.c_payback[cost_unit.upper()]!=0] self.outputs.c_payback = self.outputs.return_cleaned_output('c_payback') def calculate_d_payback(self): cost_unit = cfg.getParam('currency_year') + " " + cfg.getParam('currency_name') initial_vintage = min(cfg.supply_years) demand_side_df = self.demand.d_annual_costs_payback demand_side_df.columns = ['value'] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('vintage')>=initial_vintage] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('year')>=initial_vintage] sales_df = copy.deepcopy(self.demand.outputs.d_sales) util.replace_index_name(sales_df,'vintage','year') sales_df = sales_df[sales_df.index.get_level_values('vintage')>=initial_vintage] sales_df = util.add_and_set_index(sales_df,'year',cfg.supply_years) sales_df.index = sales_df.index.reorder_levels(demand_side_df.index.names) sales_df = sales_df.reindex(demand_side_df.index).sort_index() self.demand.outputs.d_payback = util.DfOper.divi([demand_side_df, sales_df]) self.demand.outputs.d_payback = self.demand.outputs.d_payback[np.isfinite(self.demand.outputs.d_payback.values)] self.demand.outputs.d_payback = self.demand.outputs.d_payback.replace([np.inf,np.nan],0) for sector in self.demand.sectors.values(): for subsector in sector.subsectors.values(): if hasattr(subsector,'stock') and subsector.sub_type!='link': indexer = util.level_specific_indexer(self.demand.outputs.d_payback,'subsector',subsector.id) self.demand.outputs.d_payback.loc[indexer,'unit'] = subsector.stock.unit.upper() self.demand.outputs.d_payback = self.demand.outputs.d_payback.set_index('unit', append=True) self.demand.outputs.d_payback.columns = [cost_unit.upper()] self.demand.outputs.d_payback['lifetime_year'] = self.demand.outputs.d_payback.index.get_level_values('year')-self.demand.outputs.d_payback.index.get_level_values('vintage')+1 self.demand.outputs.d_payback = self.demand.outputs.d_payback.set_index('lifetime_year',append=True) self.demand.outputs.d_payback = util.remove_df_levels(self.demand.outputs.d_payback,'year') self.demand.outputs.d_payback = self.demand.outputs.d_payback.groupby(level = [x for x in self.demand.outputs.d_payback.index.names if x !='lifetime_year']).transform(lambda x: x.cumsum()) self.demand.outputs.d_payback = self.demand.outputs.d_payback[self.demand.outputs.d_payback[cost_unit.upper()]!=0] self.demand.outputs.d_payback = self.demand.outputs.return_cleaned_output('d_payback') def calculate_d_payback_energy(self): initial_vintage = min(cfg.supply_years) demand_side_df = self.demand.d_all_energy_demand_payback demand_side_df.columns = ['value'] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('vintage')>=initial_vintage] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('year')>=initial_vintage] sales_df = copy.deepcopy(self.demand.outputs.d_sales) util.replace_index_name(sales_df,'vintage','year') sales_df = sales_df[sales_df.index.get_level_values('vintage')>=initial_vintage] sales_df = util.add_and_set_index(sales_df,'year',cfg.supply_years) # sales_df.index = sales_df.index.reorder_levels(demand_side_df.index.names) # sales_df = sales_df.reindex(demand_side_df.index).sort_index() self.demand.outputs.d_payback_energy = util.DfOper.divi([demand_side_df, sales_df]) self.demand.outputs.d_payback_energy = self.demand.outputs.d_payback_energy[np.isfinite(self.demand.outputs.d_payback_energy.values)] self.demand.outputs.d_payback_energy = self.demand.outputs.d_payback_energy.replace([np.inf,np.nan],0) for sector in self.demand.sectors.values(): for subsector in sector.subsectors.values(): if hasattr(subsector,'stock') and subsector.sub_type!='link': indexer = util.level_specific_indexer(self.demand.outputs.d_payback_energy,'subsector',subsector.id) self.demand.outputs.d_payback_energy.loc[indexer,'unit'] = subsector.stock.unit.upper() self.demand.outputs.d_payback_energy = self.demand.outputs.d_payback_energy.set_index('unit', append=True) self.demand.outputs.d_payback_energy.columns = [cfg.calculation_energy_unit.upper()] self.demand.outputs.d_payback_energy['lifetime_year'] = self.demand.outputs.d_payback_energy.index.get_level_values('year')-self.demand.outputs.d_payback_energy.index.get_level_values('vintage')+1 self.demand.outputs.d_payback_energy = self.demand.outputs.d_payback_energy.set_index('lifetime_year',append=True) self.demand.outputs.d_payback_energy = util.remove_df_levels(self.demand.outputs.d_payback_energy,'year') self.demand.outputs.d_payback_energy = self.demand.outputs.d_payback_energy.groupby(level = [x for x in self.demand.outputs.d_payback_energy.index.names if x !='lifetime_year']).transform(lambda x: x.cumsum()) self.demand.outputs.d_payback_energy = self.demand.outputs.d_payback_energy[self.demand.outputs.d_payback_energy[cfg.calculation_energy_unit.upper()]!=0] self.demand.outputs.d_payback_energy = self.demand.outputs.return_cleaned_output('d_payback_energy') def calc_and_format_export_costs(self): #calculate and format export costs if self.supply.export_costs is None: return None export_costs = GeoMapper.geo_map(self.supply.export_costs.copy(), GeoMapper.supply_primary_geography, GeoMapper.combined_outputs_geography, 'total') export_costs = Output.clean_df(export_costs) util.replace_index_name(export_costs, 'FINAL_ENERGY', 'SUPPLY_NODE_EXPORT') export_costs = util.add_to_df_index(export_costs, names=['EXPORT/DOMESTIC', "SUPPLY/DEMAND"], keys=["EXPORT", "SUPPLY"]) cost_unit = cfg.getParam('currency_year') + " " + cfg.getParam('currency_name') export_costs.columns = [cost_unit.upper()] return export_costs def calc_and_format_embodied_costs(self): #calculate and format embodied supply costs embodied_costs_list = [Output.clean_df(x) for x in self.demand.outputs.demand_embodied_energy_costs] cost_unit = cfg.getParam('currency_year') + " " + cfg.getParam('currency_name') for embodied_costs in embodied_costs_list: embodied_costs.columns = [cost_unit.upper()] embodied_costs_list = [util.add_to_df_index(x, names=['EXPORT/DOMESTIC', "SUPPLY/DEMAND"], keys=["DOMESTIC","SUPPLY"]) for x in embodied_costs_list] return embodied_costs_list def calc_and_format_direct_demand_costs(self): #calculte and format direct demand costs if self.demand.outputs.d_levelized_costs is None: return None direct_costs = GeoMapper.geo_map(self.demand.outputs.d_levelized_costs.copy(), GeoMapper.demand_primary_geography, GeoMapper.combined_outputs_geography, 'total') direct_costs = direct_costs[direct_costs.index.get_level_values('year').isin(cfg.combined_years_subset)] levels_to_keep = [x for x in cfg.output_combined_levels if x in direct_costs.index.names] direct_costs = direct_costs.groupby(level=levels_to_keep).sum() direct_costs = Output.clean_df(direct_costs) direct_costs = util.add_to_df_index(direct_costs, names=['EXPORT/DOMESTIC', "SUPPLY/DEMAND"], keys=["DOMESTIC","DEMAND"]) return direct_costs def calculate_combined_cost_results(self): cost_unit = cfg.getParam('currency_year') + " " + cfg.getParam('currency_name') export_costs = self.calc_and_format_export_costs() embodied_costs_list = self.calc_and_format_embodied_costs() direct_costs = self.calc_and_format_direct_demand_costs() export_costs = util.add_and_set_index(export_costs,['COST_TYPE'],['EXPORTED']) embodied_costs_list = [util.add_and_set_index(x,['COST_TYPE'],['SUPPLY-SIDE']) for x in embodied_costs_list] direct_costs = util.add_and_set_index(direct_costs,['COST_TYPE'],['DEMAND-SIDE']) if export_costs is not None: for name in [x for x in embodied_costs_list[0].index.names if x not in export_costs.index.names]: export_costs[name] = "N/A" export_costs.set_index(name,append=True,inplace=True) export_costs = export_costs.groupby(level=embodied_costs_list[0].index.names).sum() if direct_costs is not None: for name in [x for x in embodied_costs_list[0].index.names if x not in direct_costs.index.names]: direct_costs[name] = "N/A" direct_costs.set_index(name, append=True, inplace=True) direct_costs = direct_costs.groupby(level=embodied_costs_list[0].index.names).sum() self.outputs.c_costs = embodied_costs_list + [direct_costs] + [export_costs] self.outputs.c_costs= [x[x.values!=0] for x in self.outputs.c_costs] for x in self.outputs.c_costs: x.index = x.index.reorder_levels(embodied_costs_list[0].index.names) def calc_and_format_export_emissions(self): #calculate and format export emissions if self.supply.export_emissions is None: return None export_emissions = GeoMapper.geo_map(self.supply.export_emissions.copy(), GeoMapper.supply_primary_geography, GeoMapper.combined_outputs_geography, 'total') if 'supply_geography' not in cfg.output_combined_levels: util.remove_df_levels(export_emissions, GeoMapper.supply_primary_geography +'_supply') export_emissions = Output.clean_df(export_emissions) util.replace_index_name(export_emissions, 'FINAL_ENERGY','SUPPLY_NODE_EXPORT') index_names = export_emissions.index.names export_emissions = export_emissions.reset_index() export_emissions['FINAL_ENERGY'] = 'export ' + export_emissions['FINAL_ENERGY'] export_emissions = export_emissions.set_index(index_names).sort_index() export_emissions = util.add_to_df_index(export_emissions, names=['EXPORT/DOMESTIC', "SUPPLY/DEMAND"], keys=["EXPORT", "SUPPLY"]) return export_emissions def calc_and_format_embodied_supply_emissions(self): # calculate and format embodied supply emissions embodied_emissions_list = [Output.clean_df(x) for x in self.demand.outputs.demand_embodied_emissions] embodied_emissions_list = [util.add_to_df_index(x, names=['EXPORT/DOMESTIC', "SUPPLY/DEMAND"], keys=["DOMESTIC", "SUPPLY"]) for x in embodied_emissions_list] return embodied_emissions_list def calc_and_format_direct_demand_emissions(self): #calculte and format direct demand emissions direct_emissions_list = [Output.clean_df(x) for x in self.demand.outputs.demand_direct_emissions] direct_emissions_list = [util.add_to_df_index(x, names=['EXPORT/DOMESTIC', "SUPPLY/DEMAND"], keys=["DOMESTIC", "DEMAND"]) for x in direct_emissions_list] if GeoMapper.combined_outputs_geography + '_supply' in cfg.output_combined_levels: keys = direct_emissions_list[0].index.get_level_values(GeoMapper.combined_outputs_geography.upper()).values names = GeoMapper.combined_outputs_geography.upper() + '_SUPPLY' for x in direct_emissions_list: x[names] = keys direct_emissions_list = [x.set_index(names, append=True, inplace=True) for x in direct_emissions_list] return direct_emissions_list def calculate_combined_emissions_results(self): export_emissions = self.calc_and_format_export_emissions() embodied_emissions_list = self.calc_and_format_embodied_supply_emissions() direct_emissions_list = self.calc_and_format_direct_demand_emissions() export_emissions = util.add_and_set_index(export_emissions,['EMISSIONS_TYPE'],['EXPORTED']) embodied_emissions_list = [util.add_and_set_index(x, ['EMISSIONS_TYPE'], ['SUPPLY_SIDE']) for x in embodied_emissions_list] direct_emissions_list = [util.add_and_set_index(x,['EMISSIONS_TYPE'],['DEMAND_SIDE']) for x in direct_emissions_list] if export_emissions is not None: for name in [x for x in embodied_emissions_list[0].index.names if x not in export_emissions.index.names]: export_emissions[name] = "N/A" export_emissions.set_index(name,append=True,inplace=True) export_emissions = export_emissions.groupby(level=embodied_emissions_list[0].index.names).sum() if direct_emissions_list is not None: for df in direct_emissions_list: for name in [x for x in embodied_emissions_list[0].index.names if x not in df.index.names]: df[name] = "N/A" df.set_index(name,append=True,inplace=True) self.outputs.c_emissions = [export_emissions] + embodied_emissions_list + direct_emissions_list self.outputs.c_emissions = [util.replace_index_name(x, GeoMapper.combined_outputs_geography.upper() +'-EMITTED', GeoMapper.combined_outputs_geography.upper() +'_SUPPLY',inplace=True) for x in self.outputs.c_emissions] self.outputs.c_emissions = [util.replace_index_name(x, GeoMapper.combined_outputs_geography.upper() +'-CONSUMED', GeoMapper.combined_outputs_geography.upper(),inplace=True) for x in self.outputs.c_emissions] self.outputs.c_emissions = [x[x['VALUE']!=0] for x in self.outputs.c_emissions] emissions_unit = cfg.getParam('mass_unit') for x in self.outputs.c_emissions: x.columns = [emissions_unit.upper()] for x in self.outputs.c_emissions: x.index = x.index.reorder_levels([l for l in embodied_emissions_list[0].index.names if l in x.index.names]) def calc_and_format_export_energy(self): if self.supply.export_energy is None: return None export_energy = GeoMapper.geo_map(self.supply.export_energy.copy(), GeoMapper.supply_primary_geography, GeoMapper.combined_outputs_geography, 'total') export_energy = Output.clean_df(export_energy) util.replace_index_name(export_energy, 'FINAL_ENERGY','SUPPLY_NODE_EXPORT') export_energy = util.add_to_df_index(export_energy, names=['EXPORT/DOMESTIC', "ENERGY ACCOUNTING"], keys=["EXPORT", "EMBODIED"]) for x in cfg.output_combined_levels: if x not in export_energy.index.names: export_energy = util.add_and_set_index(export_energy,[x],["N/A"]) return export_energy def calc_and_format_embodied_supply_energy(self): embodied_energy_list = [Output.clean_df(x) for x in self.demand.outputs.demand_embodied_energy] embodied_energy_list = [x[x['VALUE']!=0] for x in embodied_energy_list] embodied_energy_list = [util.add_to_df_index(x, names=['EXPORT/DOMESTIC', "ENERGY ACCOUNTING"], keys=['DOMESTIC','EMBODIED']) for x in embodied_energy_list] return embodied_energy_list def calc_and_format_direct_demand_energy(self): demand_energy = GeoMapper.geo_map(self.demand.outputs.d_energy.copy(), GeoMapper.demand_primary_geography, GeoMapper.combined_outputs_geography, 'total') demand_energy = Output.clean_df(demand_energy) demand_energy = demand_energy[demand_energy.index.get_level_values('YEAR')>=cfg.getParamAsInt('current_year')] demand_energy = util.add_to_df_index(demand_energy, names=['EXPORT/DOMESTIC', "ENERGY ACCOUNTING"], keys=['DOMESTIC','FINAL']) return demand_energy def calculate_combined_energy_results(self): export_energy = self.calc_and_format_export_energy() embodied_energy_list = self.calc_and_format_embodied_supply_energy() demand_energy = self.calc_and_format_direct_demand_energy() # reorder levels so dfs match for name in [x for x in embodied_energy_list[0].index.names if x not in demand_energy.index.names]: demand_energy[name] = "N/A" demand_energy.set_index(name, append=True, inplace=True) demand_energy = demand_energy.groupby(level=embodied_energy_list[0].index.names).sum() if export_energy is not None: for name in [x for x in embodied_energy_list[0].index.names if x not in export_energy.index.names]: export_energy[name] = "N/A" export_energy.set_index(name,append=True,inplace=True) export_energy = export_energy.groupby(level=embodied_energy_list[0].index.names).sum() self.outputs.c_energy = embodied_energy_list + [demand_energy] + [export_energy] self.outputs.c_energy = [x[x['VALUE']!=0] for x in self.outputs.c_energy] energy_unit = cfg.calculation_energy_unit for x in self.outputs.c_energy: x.columns = [energy_unit.upper()] for x in self.outputs.c_energy: x.index = x.index.reorder_levels(embodied_energy_list[0].index.names) def export_io(self): io_table_write_step = cfg.getParamAsInt('io_table_write_step', 'output_detail') io_table_years = sorted([min(self.supply.years)] + range(max(self.supply.years), min(self.supply.years), -io_table_write_step)) df_list = [] for year in io_table_years: keys = self.supply.demand_sectors year_df = pd.concat([self.supply.io_dict[year][sector] for sector in keys], keys=keys,names=['sector']) year_df = pd.concat([year_df]*len(keys), keys=keys, names=['sector'], axis=1) df_list.append(year_df) keys = io_table_years name = ['year'] df = pd.concat(df_list,keys=keys,names=name) for row_sector in self.supply.demand_sectors: for col_sector in self.supply.demand_sectors: if row_sector != col_sector: df.loc[util.level_specific_indexer(df,'sector',row_sector),util.level_specific_indexer(df,'sector',col_sector,axis=1)] = 0 self.supply.outputs.io = df result_df = self.supply.outputs.return_cleaned_output('io') keys = [self.scenario.name.upper(), cfg.timestamp] names = ['SCENARIO','TIMESTAMP'] for key, name in zip(keys,names): result_df = pd.concat([result_df], keys=[key],names=[name]) Output.write(result_df, 's_io.csv', os.path.join(cfg.workingdir, 'supply_outputs')) # self.export_stacked_io() def export_stacked_io(self): df = copy.deepcopy(self.supply.outputs.io) df.index.names = [x + '_input'if x!= 'year' else x for x in df.index.names ] df = df.stack(level=df.columns.names).to_frame() df.columns = ['value'] self.supply.outputs.stacked_io = df result_df = self.supply.outputs.return_cleaned_output('stacked_io') keys = [self.scenario.name.upper(), cfg.timestamp] names = ['SCENARIO','TIMESTAMP'] for key, name in zip(keys,names): result_df = pd.concat([result_df], keys=[key],names=[name]) Output.write(result_df, 's_stacked_io.csv', os.path.join(cfg.workingdir, 'supply_outputs'))
np.random.seed(42) # Reproducibility MPR # Initializing vehicles Tampere.reset() # ============================================================================== # Defaults # ============================================================================== # Traffic Network trf_net = {"lengths_per_link": (20000, 10000), "lanes_per_link": (1, 2)} traffic_network = TrafficNetwork(**trf_net) # Demand demands = Demand((C / 2, ), (12, )) trf_dmd = {"lks": (1, ), "demands": (demands, demands)} traffic_demand = TrafficDemand(**trf_dmd) # ============================================================================== # Classes # ============================================================================== class Scenario: def __init__( self, traffic_network=traffic_network, traffic_demand=traffic_demand, mpr=MPR,
class PathwaysModel(object): """ Highest level classification of the definition of an energy system. """ def __init__(self, scenario_id, api_run=False): self.scenario_id = scenario_id self.scenario = Scenario(self.scenario_id) self.api_run = api_run self.outputs = Output() self.demand = Demand(self.scenario) self.supply = None self.demand_solved, self.supply_solved = False, False def run(self, scenario_id, solve_demand, solve_supply, load_demand, load_supply, export_results, save_models, append_results): try: if solve_demand and not (load_demand or load_supply): self.calculate_demand(save_models) if not append_results: self.remove_old_results() # it is nice if when loading a demand side object to rerun supply, it doesn't re-output these results every time if self.demand_solved and export_results and not self.api_run and not (load_demand and solve_supply): self.export_result_to_csv('demand_outputs') if solve_supply and not load_supply: if load_demand: # if we are loading the demand, we are changing the supply measures and want to reload our scenarios self.scenario = Scenario(self.scenario_id) self.supply = Supply(self.scenario, demand_object=self.demand) self.calculate_supply(save_models) if load_demand and solve_supply: # we do this now because we delayed before self.export_result_to_csv('demand_outputs') if self.supply_solved and export_results and load_supply or solve_supply: self.supply.calculate_supply_outputs() self.pass_supply_results_back_to_demand() self.calculate_combined_results() self.outputs.electricity_reconciliation = self.demand.electricity_reconciliation # we want to write these to outputs if self.api_run: self.export_results_to_db() else: self.export_result_to_csv('supply_outputs') self.export_result_to_csv('combined_outputs') self.export_io() except: # pickle the model in the event that it crashes if save_models: Output.pickle(self, file_name=str(scenario_id) + cfg.model_error_append_name, path=cfg.workingdir) raise def calculate_demand(self, save_models): self.demand.setup_and_solve() self.demand_solved = True if cfg.output_payback == 'true': if self.demand.d_all_energy_demand_payback is not None: self.calculate_d_payback() self.calculate_d_payback_energy() if save_models: Output.pickle(self, file_name=str(self.scenario_id) + cfg.demand_model_append_name, path=cfg.workingdir) def calculate_supply(self, save_models): if not self.demand_solved: raise ValueError('demand must be solved first before supply') logging.info('Configuring energy system supply') self.supply.add_nodes() self.supply.add_measures() self.supply.initial_calculate() self.supply.calculated_years = [] self.supply.calculate_loop(self.supply.years, self.supply.calculated_years) self.supply.final_calculate() self.supply_solved = True if save_models: Output.pickle(self, file_name=str(self.scenario_id) + cfg.full_model_append_name, path=cfg.workingdir) # we don't need the demand side object any more, so we can remove it to save drive space if os.path.isfile(os.path.join(cfg.workingdir, str(self.scenario_id) + cfg.demand_model_append_name)): os.remove(os.path.join(cfg.workingdir, str(self.scenario_id) + cfg.demand_model_append_name)) def pass_supply_results_back_to_demand(self): logging.info("Calculating link to supply") self.demand.link_to_supply(self.supply.emissions_demand_link, self.supply.demand_emissions_rates, self.supply.energy_demand_link, self.supply.cost_demand_link) if cfg.output_tco == 'true': if hasattr(self,'d_energy_tco'): self.demand.link_to_supply_tco(self.supply.emissions_demand_link, self.supply.demand_emissions_rates, self.supply.cost_demand_link) else: print "demand side has not been run with tco outputs set to 'true'" if cfg.output_payback == 'true': if hasattr(self,'demand.d_all_energy_demand_payback'): self.demand.link_to_supply_payback(self.supply.emissions_demand_link, self.supply.demand_emissions_rates, self.supply.cost_demand_link) else: print "demand side has not been run with tco outputs set to 'true'" def calculate_combined_results(self): logging.info("Calculating combined emissions results") self.calculate_combined_emissions_results() logging.info("Calculating combined cost results") self.calculate_combined_cost_results() logging.info("Calculating combined energy results") self.calculate_combined_energy_results() if cfg.output_tco == 'true': if self.demand.d_energy_tco is not None: self.calculate_tco() if cfg.output_payback == 'true': if self.demand.d_all_energy_demand_payback is not None: self.calculate_payback() def remove_old_results(self): folder_names = ['combined_outputs', 'demand_outputs', 'supply_outputs', 'dispatch_outputs'] for folder_name in folder_names: folder = os.path.join(cfg.workingdir, folder_name) if os.path.isdir(folder): shutil.rmtree(folder) def export_result_to_csv(self, result_name): if result_name=='combined_outputs': res_obj = self.outputs elif result_name=='demand_outputs': res_obj = self.demand.outputs elif result_name=='supply_outputs': res_obj = self.supply.outputs else: raise ValueError('result_name not recognized') for attribute in dir(res_obj): if not isinstance(getattr(res_obj, attribute), pd.DataFrame): continue result_df = getattr(res_obj, 'return_cleaned_output')(attribute) keys = [self.scenario.name.upper(), cfg.timestamp] names = ['SCENARIO','TIMESTAMP'] for key, name in zip(keys, names): result_df = pd.concat([result_df], keys=[key], names=[name]) if attribute in ('hourly_dispatch_results', 'electricity_reconciliation', 'hourly_marginal_cost', 'hourly_production_cost'): # Special case for hourly dispatch results where we want to write them outside of supply_outputs Output.write(result_df, attribute + '.csv', os.path.join(cfg.workingdir, 'dispatch_outputs')) else: Output.write(result_df, attribute+'.csv', os.path.join(cfg.workingdir, result_name)) def export_results_to_db(self): scenario_run_id = util.active_scenario_run_id(self.scenario_id) # Levelized costs costs = self.outputs.c_costs.groupby(level=['SUPPLY/DEMAND', 'YEAR']).sum() util.write_output_to_db(scenario_run_id, 1, costs) #Energy energy = self.outputs.c_energy.xs('FINAL', level='ENERGY ACCOUNTING')\ .groupby(level=['SECTOR', 'FINAL_ENERGY', 'YEAR']).sum() # Energy demand by sector util.write_output_to_db(scenario_run_id, 2, energy.groupby(level=['SECTOR', 'YEAR']).sum()) # Residential Energy by Fuel Type util.write_output_to_db(scenario_run_id, 6, energy.xs('RESIDENTIAL', level='SECTOR')) # Commercial Energy by Fuel Type util.write_output_to_db(scenario_run_id, 8, energy.xs('COMMERCIAL', level='SECTOR')) # Transportation Energy by Fuel Type util.write_output_to_db(scenario_run_id, 10, energy.xs('TRANSPORTATION', level='SECTOR')) # Productive Energy by Fuel Type util.write_output_to_db(scenario_run_id, 12, energy.xs('PRODUCTIVE', level='SECTOR')) #Emissions emissions = self.outputs.c_emissions.xs('DOMESTIC', level='EXPORT/DOMESTIC')\ .groupby(level=['SECTOR', 'FINAL_ENERGY', 'YEAR']).sum() emissions = util.DfOper.mult((emissions, 1-(emissions.abs()<1E-10).groupby(level='FINAL_ENERGY').all())) # get rid of noise # Annual emissions by sector util.write_output_to_db(scenario_run_id, 3, emissions.groupby(level=['SECTOR', 'YEAR']).sum()) # Residential Emissions by Fuel Type util.write_output_to_db(scenario_run_id, 7, emissions.xs('RESIDENTIAL', level='SECTOR')) # Commercial Emissions by Fuel Type util.write_output_to_db(scenario_run_id, 9, emissions.xs('COMMERCIAL', level='SECTOR')) # Transportation Emissions by Fuel Type util.write_output_to_db(scenario_run_id, 11, emissions.xs('TRANSPORTATION', level='SECTOR')) # Productive Emissions by Fuel Type util.write_output_to_db(scenario_run_id, 13, emissions.xs('PRODUCTIVE', level='SECTOR')) # Domestic emissions per capita annual_emissions = self.outputs.c_emissions.xs('DOMESTIC', level='EXPORT/DOMESTIC').groupby(level=['YEAR']).sum() population_driver = self.demand.drivers[2].values.groupby(level='year').sum().loc[annual_emissions.index] population_driver.index.name = 'YEAR' factor = 1E6 df = util.DfOper.divi((annual_emissions, population_driver)) * factor df.columns = ['TONNE PER CAPITA'] util.write_output_to_db(scenario_run_id, 4, df) # Electricity supply electricity_node_names = [self.supply.nodes[nodeid].name.upper() for nodeid in util.flatten_list(self.supply.injection_nodes.values())] df = self.outputs.c_energy.xs('ELECTRICITY', level='FINAL_ENERGY')\ .xs('EMBODIED', level='ENERGY ACCOUNTING')\ .groupby(level=['SUPPLY_NODE', 'YEAR']).sum() util.write_output_to_db(scenario_run_id, 5, df.loc[electricity_node_names]) def calculate_combined_cost_results(self): #calculate and format export costs cost_unit = cfg.cfgfile.get('case','currency_year_id') + " " + cfg.cfgfile.get('case','currency_name') if self.supply.export_costs is not None: setattr(self.outputs,'export_costs',self.supply.export_costs) self.export_costs_df = self.outputs.return_cleaned_output('export_costs') del self.outputs.export_costs util.replace_index_name(self.export_costs_df, 'FINAL_ENERGY','SUPPLY_NODE_EXPORT') keys = ["EXPORT","SUPPLY"] names = ['EXPORT/DOMESTIC', "SUPPLY/DEMAND"] for key,name in zip(keys,names): self.export_costs_df = pd.concat([self.export_costs_df],keys=[key],names=[name]) self.export_costs_df.columns = [cost_unit.upper()] else: self.export_costs_df = None #calculate and format emobodied supply costs self.embodied_energy_costs_df = self.demand.outputs.return_cleaned_output('demand_embodied_energy_costs') self.embodied_energy_costs_df.columns = [cost_unit.upper()] keys = ["DOMESTIC","SUPPLY"] names = ['EXPORT/DOMESTIC', "SUPPLY/DEMAND"] for key,name in zip(keys,names): self.embodied_energy_costs_df = pd.concat([self.embodied_energy_costs_df],keys=[key],names=[name]) #calculte and format direct demand costs self.demand_costs_df = self.demand.outputs.return_cleaned_output('d_levelized_costs') if self.demand_costs_df is not None: levels_to_keep = [x.upper() for x in cfg.output_combined_levels] levels_to_keep = [x for x in levels_to_keep if x in self.demand_costs_df.index.names] self.demand_costs_df = self.demand_costs_df.groupby(level=levels_to_keep).sum() keys = ["DOMESTIC","DEMAND"] names = ['EXPORT/DOMESTIC', "SUPPLY/DEMAND"] for key,name in zip(keys,names): self.demand_costs_df = pd.concat([self.demand_costs_df],keys=[key],names=[name]) keys = ['EXPORTED', 'SUPPLY-SIDE', 'DEMAND-SIDE'] names = ['COST TYPE'] self.outputs.c_costs = util.df_list_concatenate([self.export_costs_df, self.embodied_energy_costs_df, self.demand_costs_df],keys=keys,new_names=names) self.outputs.c_costs[self.outputs.c_costs<0]=0 self.outputs.c_costs= self.outputs.c_costs[self.outputs.c_costs[cost_unit.upper()]!=0] def calculate_tco(self): # self.embodied_emissions_df = self.demand.outputs.return_cleaned_output('demand_embodied_emissions_tco') # del self.demand.outputs.demand_embodied_emissions #calculte and format direct demand emissions # self.direct_emissions_df = self.demand.outputs.return_cleaned_output('demand_direct_emissions') ## del self.demand.outputs.demand_direct_emissions # emissions = util.DfOper.add([self.embodied_emissions_df,self.direct_emissions_df]) # #calculate and format export costs cost_unit = cfg.cfgfile.get('case','currency_year_id') + " " + cfg.cfgfile.get('case','currency_name') initial_vintage = min(cfg.supply_years) supply_side_df = self.demand.outputs.demand_embodied_energy_costs_tco supply_side_df = supply_side_df[supply_side_df.index.get_level_values('vintage')>=initial_vintage] demand_side_df = self.demand.d_levelized_costs_tco demand_side_df.columns = ['value'] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('vintage')>=initial_vintage] service_demand_df = self.demand.d_service_demand_tco service_demand_df = service_demand_df[service_demand_df.index.get_level_values('vintage')>=initial_vintage] keys = ['SUPPLY-SIDE', 'DEMAND-SIDE'] names = ['COST TYPE'] self.outputs.c_tco = pd.concat([util.DfOper.divi([supply_side_df,util.remove_df_levels(service_demand_df,'unit')]), util.DfOper.divi([demand_side_df,util.remove_df_levels(service_demand_df,'unit')])], keys=keys,names=names) self.outputs.c_tco = self.outputs.c_tco.replace([np.inf,np.nan],0) self.outputs.c_tco[self.outputs.c_tco<0]=0 for sector in self.demand.sectors.values(): for subsector in sector.subsectors.values(): if hasattr(subsector,'service_demand') and hasattr(subsector,'stock'): indexer = util.level_specific_indexer(self.outputs.c_tco,'subsector',subsector.id) self.outputs.c_tco.loc[indexer,'unit'] = subsector.service_demand.unit.upper() self.outputs.c_tco = self.outputs.c_tco.set_index('unit',append=True) self.outputs.c_tco.columns = [cost_unit.upper()] self.outputs.c_tco= self.outputs.c_tco[self.outputs.c_tco[cost_unit.upper()]!=0] self.outputs.c_tco = self.outputs.return_cleaned_output('c_tco') def calculate_payback(self): # self.embodied_emissions_df = self.demand.outputs.return_cleaned_output('demand_embodied_emissions_tco') # del self.demand.outputs.demand_embodied_emissions #calculte and format direct demand emissions # self.direct_emissions_df = self.demand.outputs.return_cleaned_output('demand_direct_emissions') ## del self.demand.outputs.demand_direct_emissions # emissions = util.DfOper.add([self.embodied_emissions_df,self.direct_emissions_df]) # #calculate and format export costs cost_unit = cfg.cfgfile.get('case','currency_year_id') + " " + cfg.cfgfile.get('case','currency_name') initial_vintage = min(cfg.supply_years) supply_side_df = self.demand.outputs.demand_embodied_energy_costs_payback supply_side_df = supply_side_df[supply_side_df.index.get_level_values('vintage')>=initial_vintage] supply_side_df = supply_side_df[supply_side_df.index.get_level_values('year')>=initial_vintage] supply_side_df = supply_side_df.sort_index() demand_side_df = self.demand.d_annual_costs_payback demand_side_df.columns = ['value'] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('vintage')>=initial_vintage] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('year')>=initial_vintage] demand_side_df = demand_side_df.reindex(supply_side_df.index).sort_index() sales_df = copy.deepcopy(self.demand.outputs.d_sales) util.replace_index_name(sales_df,'vintage','year') sales_df = sales_df[sales_df.index.get_level_values('vintage')>=initial_vintage] sales_df = util.add_and_set_index(sales_df,'year',cfg.supply_years) sales_df.index = sales_df.index.reorder_levels(supply_side_df.index.names) sales_df = sales_df.reindex(supply_side_df.index).sort_index() keys = ['SUPPLY-SIDE', 'DEMAND-SIDE'] names = ['COST TYPE'] self.outputs.c_payback = pd.concat([util.DfOper.divi([supply_side_df, sales_df]), util.DfOper.divi([demand_side_df, sales_df])],keys=keys,names=names) self.outputs.c_payback = self.outputs.c_payback[np.isfinite(self.outputs.c_payback.values)] self.outputs.c_payback = self.outputs.c_payback.replace([np.inf,np.nan],0) for sector in self.demand.sectors.values(): for subsector in sector.subsectors.values(): if hasattr(subsector,'stock') and subsector.sub_type!='link': indexer = util.level_specific_indexer(self.outputs.c_payback,'subsector',subsector.id) self.outputs.c_payback.loc[indexer,'unit'] = subsector.stock.unit.upper() self.outputs.c_payback = self.outputs.c_payback.set_index('unit', append=True) self.outputs.c_payback.columns = [cost_unit.upper()] self.outputs.c_payback['lifetime_year'] = self.outputs.c_payback.index.get_level_values('year')-self.outputs.c_payback.index.get_level_values('vintage')+1 self.outputs.c_payback = self.outputs.c_payback.set_index('lifetime_year',append=True) self.outputs.c_payback = util.remove_df_levels(self.outputs.c_payback,'year') self.outputs.c_payback = self.outputs.c_payback.groupby(level = [x for x in self.outputs.c_payback.index.names if x !='lifetime_year']).transform(lambda x: x.cumsum()) self.outputs.c_payback = self.outputs.c_payback[self.outputs.c_payback[cost_unit.upper()]!=0] self.outputs.c_payback = self.outputs.return_cleaned_output('c_payback') def calculate_d_payback(self): cost_unit = cfg.cfgfile.get('case','currency_year_id') + " " + cfg.cfgfile.get('case','currency_name') initial_vintage = min(cfg.supply_years) demand_side_df = self.demand.d_annual_costs_payback demand_side_df.columns = ['value'] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('vintage')>=initial_vintage] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('year')>=initial_vintage] sales_df = copy.deepcopy(self.demand.outputs.d_sales) util.replace_index_name(sales_df,'vintage','year') sales_df = sales_df[sales_df.index.get_level_values('vintage')>=initial_vintage] sales_df = util.add_and_set_index(sales_df,'year',cfg.supply_years) sales_df.index = sales_df.index.reorder_levels(demand_side_df.index.names) sales_df = sales_df.reindex(demand_side_df.index).sort_index() self.demand.outputs.d_payback = util.DfOper.divi([demand_side_df, sales_df]) self.demand.outputs.d_payback = self.demand.outputs.d_payback[np.isfinite(self.demand.outputs.d_payback.values)] self.demand.outputs.d_payback = self.demand.outputs.d_payback.replace([np.inf,np.nan],0) for sector in self.demand.sectors.values(): for subsector in sector.subsectors.values(): if hasattr(subsector,'stock') and subsector.sub_type!='link': indexer = util.level_specific_indexer(self.demand.outputs.d_payback,'subsector',subsector.id) self.demand.outputs.d_payback.loc[indexer,'unit'] = subsector.stock.unit.upper() self.demand.outputs.d_payback = self.demand.outputs.d_payback.set_index('unit', append=True) self.demand.outputs.d_payback.columns = [cost_unit.upper()] self.demand.outputs.d_payback['lifetime_year'] = self.demand.outputs.d_payback.index.get_level_values('year')-self.demand.outputs.d_payback.index.get_level_values('vintage')+1 self.demand.outputs.d_payback = self.demand.outputs.d_payback.set_index('lifetime_year',append=True) self.demand.outputs.d_payback = util.remove_df_levels(self.demand.outputs.d_payback,'year') self.demand.outputs.d_payback = self.demand.outputs.d_payback.groupby(level = [x for x in self.demand.outputs.d_payback.index.names if x !='lifetime_year']).transform(lambda x: x.cumsum()) self.demand.outputs.d_payback = self.demand.outputs.d_payback[self.demand.outputs.d_payback[cost_unit.upper()]!=0] self.demand.outputs.d_payback = self.demand.outputs.return_cleaned_output('d_payback') def calculate_d_payback_energy(self): initial_vintage = min(cfg.supply_years) demand_side_df = self.demand.d_all_energy_demand_payback demand_side_df.columns = ['value'] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('vintage')>=initial_vintage] demand_side_df = demand_side_df[demand_side_df.index.get_level_values('year')>=initial_vintage] sales_df = copy.deepcopy(self.demand.outputs.d_sales) util.replace_index_name(sales_df,'vintage','year') sales_df = sales_df[sales_df.index.get_level_values('vintage')>=initial_vintage] sales_df = util.add_and_set_index(sales_df,'year',cfg.supply_years) # sales_df.index = sales_df.index.reorder_levels(demand_side_df.index.names) # sales_df = sales_df.reindex(demand_side_df.index).sort_index() self.demand.outputs.d_payback_energy = util.DfOper.divi([demand_side_df, sales_df]) self.demand.outputs.d_payback_energy = self.demand.outputs.d_payback_energy[np.isfinite(self.demand.outputs.d_payback_energy.values)] self.demand.outputs.d_payback_energy = self.demand.outputs.d_payback_energy.replace([np.inf,np.nan],0) for sector in self.demand.sectors.values(): for subsector in sector.subsectors.values(): if hasattr(subsector,'stock') and subsector.sub_type!='link': indexer = util.level_specific_indexer(self.demand.outputs.d_payback_energy,'subsector',subsector.id) self.demand.outputs.d_payback_energy.loc[indexer,'unit'] = subsector.stock.unit.upper() self.demand.outputs.d_payback_energy = self.demand.outputs.d_payback_energy.set_index('unit', append=True) self.demand.outputs.d_payback_energy.columns = [cfg.calculation_energy_unit.upper()] self.demand.outputs.d_payback_energy['lifetime_year'] = self.demand.outputs.d_payback_energy.index.get_level_values('year')-self.demand.outputs.d_payback_energy.index.get_level_values('vintage')+1 self.demand.outputs.d_payback_energy = self.demand.outputs.d_payback_energy.set_index('lifetime_year',append=True) self.demand.outputs.d_payback_energy = util.remove_df_levels(self.demand.outputs.d_payback_energy,'year') self.demand.outputs.d_payback_energy = self.demand.outputs.d_payback_energy.groupby(level = [x for x in self.demand.outputs.d_payback_energy.index.names if x !='lifetime_year']).transform(lambda x: x.cumsum()) self.demand.outputs.d_payback_energy = self.demand.outputs.d_payback_energy[self.demand.outputs.d_payback_energy[cfg.calculation_energy_unit.upper()]!=0] self.demand.outputs.d_payback_energy = self.demand.outputs.return_cleaned_output('d_payback_energy') def calculate_combined_emissions_results(self): #calculate and format export emissions if self.supply.export_emissions is not None: setattr(self.outputs,'export_emissions',self.supply.export_emissions) if 'supply_geography' not in cfg.output_combined_levels: util.remove_df_levels(self.outputs.export_emissions, cfg.primary_geography +'_supply') self.export_emissions_df = self.outputs.return_cleaned_output('export_emissions') del self.outputs.export_emissions util.replace_index_name(self.export_emissions_df, 'FINAL_ENERGY','SUPPLY_NODE_EXPORT') keys = ["EXPORT","SUPPLY"] names = ['EXPORT/DOMESTIC', "SUPPLY/DEMAND"] for key,name in zip(keys,names): self.export_emissions_df = pd.concat([self.export_emissions_df],keys=[key],names=[name]) else: self.export_emissions_df = None #calculate and format emobodied supply emissions self.embodied_emissions_df = self.demand.outputs.return_cleaned_output('demand_embodied_emissions') # del self.demand.outputs.demand_embodied_emissions keys = ["DOMESTIC","SUPPLY"] names = ['EXPORT/DOMESTIC', "SUPPLY/DEMAND"] for key,name in zip(keys,names): self.embodied_emissions_df = pd.concat([self.embodied_emissions_df],keys=[key],names=[name]) #calculte and format direct demand emissions self.direct_emissions_df = self.demand.outputs.return_cleaned_output('demand_direct_emissions') # del self.demand.outputs.demand_direct_emissions keys = ["DOMESTIC","DEMAND"] names = ['EXPORT/DOMESTIC', "SUPPLY/DEMAND"] for key, name in zip(keys, names): self.direct_emissions_df = pd.concat([self.direct_emissions_df], keys=[key], names=[name]) if cfg.primary_geography+'_supply' in cfg.output_combined_levels: keys = self.direct_emissions_df.index.get_level_values(cfg.primary_geography.upper()).values names = cfg.primary_geography.upper() +'_SUPPLY' self.direct_emissions_df[names] = keys self.direct_emissions_df.set_index(names,append=True,inplace=True) keys = ['EXPORTED', 'SUPPLY-SIDE', 'DEMAND-SIDE'] names = ['EMISSIONS TYPE'] self.outputs.c_emissions = util.df_list_concatenate([self.export_emissions_df, self.embodied_emissions_df, self.direct_emissions_df],keys=keys,new_names = names) util.replace_index_name(self.outputs.c_emissions, cfg.primary_geography.upper() +'-EMITTED', cfg.primary_geography.upper() +'_SUPPLY') util.replace_index_name(self.outputs.c_emissions, cfg.primary_geography.upper() +'-CONSUMED', cfg.primary_geography.upper()) self.outputs.c_emissions= self.outputs.c_emissions[self.outputs.c_emissions['VALUE']!=0] emissions_unit = cfg.cfgfile.get('case','mass_unit') self.outputs.c_emissions.columns = [emissions_unit.upper()] def calculate_combined_energy_results(self): energy_unit = cfg.calculation_energy_unit if self.supply.export_costs is not None: setattr(self.outputs,'export_energy',self.supply.export_energy) self.export_energy = self.outputs.return_cleaned_output('export_energy') del self.outputs.export_energy util.replace_index_name(self.export_energy, 'FINAL_ENERGY','SUPPLY_NODE_EXPORT') keys = ["EXPORT","EMBODIED"] names = ['EXPORT/DOMESTIC', 'ENERGY ACCOUNTING'] for key,name in zip(keys,names): self.export_energy = pd.concat([self.export_energy],keys=[key],names=[name]) else: self.export_energy = None self.embodied_energy = self.demand.outputs.return_cleaned_output('demand_embodied_energy') self.embodied_energy = self.embodied_energy[self.embodied_energy ['VALUE']!=0] keys = ['DOMESTIC','EMBODIED'] names = ['EXPORT/DOMESTIC', 'ENERGY ACCOUNTING'] for key,name in zip(keys,names): self.embodied_energy = pd.concat([self.embodied_energy],keys=[key],names=[name]) self.final_energy = self.demand.outputs.return_cleaned_output('d_energy') self.final_energy = self.final_energy[self.final_energy.index.get_level_values('YEAR')>=int(cfg.cfgfile.get('case','current_year'))] keys = ['DOMESTIC','FINAL'] names = ['EXPORT/DOMESTIC', 'ENERGY ACCOUNTING'] for key,name in zip(keys,names): self.final_energy = pd.concat([self.final_energy],keys=[key],names=[name]) # self.outputs.c_energy = pd.concat([self.embodied_energy, self.final_energy],keys=['DROP'],names=['DROP']) for name in [x for x in self.embodied_energy.index.names if x not in self.final_energy.index.names]: self.final_energy[name] = "N/A" self.final_energy.set_index(name,append=True,inplace=True) if self.export_energy is not None: for name in [x for x in self.embodied_energy.index.names if x not in self.export_energy.index.names]: self.export_energy[name] = "N/A" self.export_energy.set_index(name,append=True,inplace=True) self.export_energy = self.export_energy.groupby(level=self.embodied_energy.index.names).sum() self.export_energy = self.export_energy.reorder_levels(self.embodied_energy.index.names) self.final_energy = self.final_energy.groupby(level=self.embodied_energy.index.names).sum() self.final_energy = self.final_energy.reorder_levels(self.embodied_energy.index.names) self.outputs.c_energy = pd.concat([self.embodied_energy,self.final_energy,self.export_energy]) self.outputs.c_energy= self.outputs.c_energy[self.outputs.c_energy['VALUE']!=0] self.outputs.c_energy.columns = [energy_unit.upper()] def export_io(self): io_table_write_step = int(cfg.cfgfile.get('output_detail','io_table_write_step')) io_table_years = sorted([min(cfg.supply_years)] + range(max(cfg.supply_years), min(cfg.supply_years), -io_table_write_step)) df_list = [] for year in io_table_years: sector_df_list = [] keys = self.supply.demand_sectors name = ['sector'] for sector in self.supply.demand_sectors: sector_df_list.append(self.supply.io_dict[year][sector]) year_df = pd.concat(sector_df_list, keys=keys,names=name) year_df = pd.concat([year_df]*len(keys),keys=keys,names=name,axis=1) df_list.append(year_df) keys = io_table_years name = ['year'] df = pd.concat(df_list,keys=keys,names=name) for row_sector in self.supply.demand_sectors: for col_sector in self.supply.demand_sectors: if row_sector != col_sector: df.loc[util.level_specific_indexer(df,'sector',row_sector),util.level_specific_indexer(df,'sector',col_sector,axis=1)] = 0 self.supply.outputs.io = df result_df = self.supply.outputs.return_cleaned_output('io') keys = [self.scenario.name.upper(), cfg.timestamp] names = ['SCENARIO','TIMESTAMP'] for key, name in zip(keys,names): result_df = pd.concat([result_df], keys=[key],names=[name]) Output.write(result_df, 's_io.csv', os.path.join(cfg.workingdir, 'supply_outputs')) # self.export_stacked_io() def export_stacked_io(self): df = copy.deepcopy(self.supply.outputs.io) df.index.names = [x + '_input'if x!= 'year' else x for x in df.index.names ] df = df.stack(level=df.columns.names).to_frame() df.columns = ['value'] self.supply.outputs.stacked_io = df result_df = self.supply.outputs.return_cleaned_output('stacked_io') keys = [self.scenario.name.upper(), cfg.timestamp] names = ['SCENARIO','TIMESTAMP'] for key, name in zip(keys,names): result_df = pd.concat([result_df], keys=[key],names=[name]) Output.write(result_df, 's_stacked_io.csv', os.path.join(cfg.workingdir, 'supply_outputs'))
from smbus_sensor_conf import SmbusSensorConf from demand_driven_io import DemandDrivenIo from sensor_exception import SensorException from demand import Demand class DemandSmbusSensor(SmbusSensorConf, DemandDrivenIo, SensorException): """This class is for the demand driven sensors""" def __init__(self, address=None, bus=1): super().__init__(self, address, bus) self.event_handlers = EventHandler() def demand_issue(self, demand, **catch_event) self.sensor_data = [] # 読み取ってとってくる値を格納する箱 if isinstance(demand, Demand()): self.demand = demand else: print('Please give a Demand object.') return False if catch_event != {}: # cath_eventは{'1011':method} これがもらえるとよそう # main処理 書 -> 読 -> コールバック(値に応じた) for event in catch_event: self.event_handlers.add(event, catch_event[event]) for write in demand.write_methods(): write() time.sleep(demand.interval)
class PathwaysModel(object): """ Highest level classification of the definition of an energy system. Includes the primary geography of the energy system (i.e. country name) as well as the author. """ def __init__(self, db_path, cfgfile_path, custom_pint_definitions_path=None, name=None, author=None): self.model_config(db_path, cfgfile_path, custom_pint_definitions_path) self.name = cfg.cfgfile.get("case", "scenario") if name is None else name self.author = cfg.cfgfile.get("case", "author") if author is None else author self.demand = Demand() self.supply = Supply() def model_config(self, db_path, cfgfile_path, custom_pint_definitions_path): cfg.init_cfgfile(cfgfile_path) cfg.init_db(db_path) cfg.init_pint(custom_pint_definitions_path) cfg.init_geo() cfg.init_shapes() cfg.init_outputs_id_map() def configure_energy_system(self): print "configuring energy system" self.configure_demand() self.configure_supply() cfg.init_outputs_id_map() def populate_energy_system(self): self.populate_demand_system() self.populate_supply_system() def populate_measures(self): self.populate_demand_measures() self.populate_supply_measures() def calculate(self): self.calculate_demand_only() self.pass_results_to_supply() self.calculate_supply() def configure_demand(self): """Read in and initialize data""" # Drivers must come first self.demand.add_drivers() # Sectors requires drivers be read in self.demand.add_sectors() for sector in self.demand.sectors.values(): # print 'configuring the %s sector' %sector.name sector.add_subsectors() def configure_supply(self): self.supply.add_nodes() def populate_demand_system(self): print "remapping drivers" self.demand.remap_drivers() print "populating energy system data" for sector in self.demand.sectors.values(): print " " + sector.name + " sector" for subsector in sector.subsectors.values(): print " " + subsector.name subsector.add_energy_system_data() self.demand.precursor_dict() def populate_supply_system(self): self.supply.add_energy_system_data() def populate_demand_measures(self): for sector in self.demand.sectors.values(): for subsector in sector.subsectors.values(): subsector.add_measures() def populate_supply_measures(self): self.supply.add_measures() def calculate_demand_only(self): self.demand.manage_calculations() def calculate_supply(self): self.supply.calculate() def pass_results_to_supply(self): for sector in self.demand.sectors.values(): sector.aggregate_subsector_energy_for_supply_side() self.demand.aggregate_sector_energy_for_supply_side() self.supply.demand_df = self.demand.energy_demand def pass_results_to_demand(self): self.demand.aggregate_results() self.demand.link_to_supply( self.supply.emissions_demand_link, self.supply.energy_demand_link, self.supply.cost_demand_link ) def export_results(self, specified_directory=None): if specified_directory is None: specified_directory = os.path.join(os.getcwd()) else: specified_directory = os.path.join(specified_directory) attributes = dir(self.demand.outputs) for att in attributes: if isinstance(getattr(self.demand.outputs, att), pd.core.frame.DataFrame): output = self.demand.outputs.return_cleaned_output(att) ExportMethods.writedataframe(att, output, specified_directory)
def __init__(self, db_path, cfgfile_path, custom_pint_definitions_path=None, name=None, author=None): self.model_config(db_path, cfgfile_path, custom_pint_definitions_path) self.name = cfg.cfgfile.get("case", "scenario") if name is None else name self.author = cfg.cfgfile.get("case", "author") if author is None else author self.demand = Demand() self.supply = Supply()