Results handling¶
Handling Results¶
The main purpose of the processing module is to collect and organise results. The views module will provide some typical representations of the results. Plots are not part of solph, because plots are highly individual. However, the provided pandas.DataFrames are a good start for plots. Some basic functions for plotting of optimisation results can be found in the separate repository oemof_visio.
The processing.results function gives back the results as a python
dictionary holding pandas Series for scalar values and pandas DataFrames for
all nodes and flows between them. This way we can make use of the full power
of the pandas package available to process the results.
See the pandas documentation to learn how to visualise, read or write or how to access parts of the DataFrame to process them.
The results chapter consists of three parts:
The first step is the processing of the results (Collecting results). This is followed by basic examples of the general analysis of the results (General approach) and finally the use of functionality already included in solph for providing a quick access to your results (Easy access). Especially for larger energy systems the general approach will help you to write your own results processing functions.
Easy access¶
The solph package provides some functions which will help you to access your results directly via labels, which is helpful especially for small energy systems. So, if you want to address objects by their label, you can convert the results dictionary such that the keys are changed to strings given by the labels:
views.convert_keys_to_strings(results)
print(results[('wind', 'bus_electricity')]['sequences']
In many situations it might be convenient to use the views module to collect information on a specific node. You can request all data related to a specific node by using either the node’s variable name or its label:
data_wind = solph.views.node(results, 'wind')
A function for collecting and printing meta results, i.e. information on the objective function, the problem and the solver, is provided as well:
meta_results = solph.processing.meta_results(om)
pp.pprint(meta_results)
Collecting results¶
Collecting results can be done with the help of the processing module. A solved model is needed:
[...]
model.solve(solver=solver)
results = solph.processing.results(model)
The scalars and sequences describe nodes (with keys like (node, None)) and flows between nodes (with keys like (node_1, node_2)). You can directly extract the data in the dictionary by using these keys, where “node” is the name of the object you want to address. Processing the results is the prerequisite for the examples in the following sections.
General approach¶
As stated above, after processing you will get a dictionary with all result data. If you want to access your results directly via labels, you can continue with Easy access. For a systematic analysis list comprehensions are the easiest way of filtering and analysing your results.
The keys of the results dictionary are tuples containing two nodes. Since flows have a starting node and an ending node, you get a list of all flows by filtering the results using the following expression:
flows = [x for x in results.keys() if x[1] is not None]
On the same way you can get a list of all nodes by applying:
nodes = [x for x in results.keys() if x[1] is None]
Probably you will just get storages as nodes, if you have some in your energy system. Note, that just nodes containing decision variables are listed, e.g. a Source or a Converter object does not have decision variables. These are in the flows from or to the nodes.
All items within the results dictionary are dictionaries and have two items with ‘scalars’ and ‘sequences’ as keys:
for flow in flows:
print(flow)
print(results[flow]['scalars'])
print(results[flow]['sequences'])
There many options of filtering the flows and nodes as you prefer. The following will give you all flows which are outputs of converter:
flows_from_converter = [x for x in flows if isinstance(
x[0], solph.components.Converter)]
You can filter your flows, if the label of in- or output contains a given string, e.g.:
flows_to_elec = [x for x in results.keys() if 'elec' in x[1].label]
Getting all labels of the starting node of your investment flows:
flows_invest = [x[0].label for x in flows if hasattr(
results[x]['scalars'], 'invest')]