Reference - Sub-Packages¶
You can get an overview of the purpose of the sub-packages from the previous section. The (detailed) description of all user-relevant functions in rivus are listed below. In addition to the documentation of the individual functions, a brief description is provided per sub-package or module to enlighten the used packages or design logic.
Note
- Prerequisites:
- In the code examples, we assume that you have a installed rivus (
git clone
) and the required packages for your work. (conda install
see in installation)
rivus.main¶
rivus¶
The formulation of the MILP model is implemented
with the help of Pyomo’s ConcreteModel. That means, the needed constrains are formulated with the help of python functions. These have descriptive names following the *_rule
or *_balance
naming convention. In general, you do not have to touch them.
As for now, the object returned by create_model()
(often named as prob
) serves as the base type of input for the other function. This may change in future versions. But as for now, it is important you get familiar with its format. Following attributes are directly accessible and esp. interesting in the first round.
peak : (Pandas.DataFrame) - Maximum demands per edge.
r_in, r_out : (Pandas.Series) - Process-Commodity ratios split by direction.
params : (dict)
commodity
- processed Excel sheetprocess
- processed Excel sheethub
- filtered version ofprocess
process_commodity
- processed Excel sheettime
- processed Excel sheetarea_demand
- processed Excel sheetvertex
- processed spatial inputedge
- processed spatial input
Warning
Following functions will be migrated to the io
sub-package:
read_excel
plot
-result_figures
save
-load
save_log
Following function will be migrated to rivus.main.getters
:
get_entity
-get_entities
-list_entities
get_onset_names
get_constants
get_timeseries
Modelling¶
-
create_model
(data, vertex, edge, peak_multiplier=None, hub_only_in_edge=True)[source]¶ Return a rivus model instance from input file and spatial input.
Parameters: - data (dict) – Processed Excel spreadsheet by
read_excel
- vertex (GeoDataFrame) – DataFrame with vertex IDs as column ‘Vertex’ and other columns named like source commodities (e.g. ‘Gas’, ‘Elec’, ‘Pellets’), containing source vertex capacities (in kW)
- edge (GeoDataFrame) – DataFrame with vertex IDs in columns ‘Vertex1’ and ‘Vertex2’ and other columns named like area types (in spreadsheet/Area-Demand), containing total areas (square metres) to be supplied
- peak_multiplier (callable, optional) – If not None and bool-casts to True, then m.peak will be calculated
by calling
m.peak = peak_multiplier(m)
- hub_only_in_edge (bool, optional) – Temporary switch between original and fixed process handling.
Returns: Pyomo ConcreteModel object
Note
This function will change its input objects! (Reindex, insertion of values.)
- data (dict) – Processed Excel spreadsheet by
IO¶
Following functions will be migrated to the io
sub-package
-
read_excel
(filepath)[source]¶ Read Excel input file and prepare rivus input data dict.
Reads an Excel spreadsheet that adheres to the structure shown in the example dataset data/mnl/mnl.xlsx. Must contain
Parameters: filepath (str) – absolute or relative filepath to an Excel spreadsheet. Returns: dict – 5 DataFrames, one for each sheet Example
data = read_excel('./data/mnl/data.xlsx')
-
plot
(prob, commodity, plot_demand=False, mapscale=False, tick_labels=True, annotations=True, buildings=None, shapefiles=None, decoration=True, boundary=False)[source]¶ Plot a map of supply, conversion, transport and consumption.
For given commodity, plot a map of all locations where the commodity is introduced (Rho), transported (Pin/Pot/Pmax), converted (Epsilon_*) and consumed (Sigma, peak).
Parameters: - prob – rivus ConcreteModel
- commodity – str like Elec, Heat etc.
- plot_demand – If True, plot demand, else plot capacities
- mapscale (Boolean) – If True, add mapscale to plot (default: False)
- tick_labels (Boolean) – If True, add lon/lat tick labels (default: True)
- annotations (Boolean) – If True, add numeric labels to graph (default: True)
- buildings (tuple) – tuple of (filename to shapefile, boolean) if true, color buildings according to attribute column “type” and colors in constant rivus.COLORS; else use default COLOR[‘building’] for all
- shapefiles (list) – list of dicts of shapefiles that shall be drawn by basemap function readshapefile. is passed as **kwargs
- decoration (Boolean) – Switch for map decoration (meridian, parallels)
- boundary (Boolean) – Draw map border or not.
Returns: fig – the map figure object
-
result_figures
(prob, file_basename, buildings=None, shapefiles=None)[source]¶ Call rivus.plot with hard-coded combinations of plot_type and commodity.
This is a convenience wrapper to shorten scripts. TODO: Generalise so that no hard-coding of commodity names is needed.
Parameters: - prob – a rivus model instance
- file_basename – filename prefix for figures
- buildings – optional filename to buildings shapefile
- shapefiles – list of dicts of shapefiles that shall be drawn by basemap function readshapefile. is passed as **kwargs
Returns: Nothing
-
report
(prob, filename)[source]¶ Write result summary to a spreadsheet file.
Create a concise result spreadsheet with values of all key variables, inclduing costs, pipe capacities, process and hub capacities, source flows, and process input/output/throughput per time step.
Parameters: - prob – a rivus model instance
- filename – Excel spreadsheet filename, will be overwritten if exists
Returns: Nothing
-
save_log
(result, filename)[source]¶ Save rivus result and solver information to a log file.
Parameters: - result – as returned by the solve method of a solver object
- filename – log file to be written
Returns: Nothing
-
save
(prob, filepath)[source]¶ Save rivus model instance to a gzip’ed pickle file
Pickle is the standard Python way of serializing and de-serializing Python objects. By using it, saving any object, in case of this function a Pyomo ConcreteModel, becomes a twoliner. GZip is a standard Python compression library that is used to transparently compress the pickle file further. It is used over the possibly more compact bzip2 compression due to the lower runtime.
Parameters: - prob – a rivus model instance
- filepath – pickle file to be written
Notes
Getters¶
Following function will be migrated to rivus.main.getters
-
get_entity
(instance, name)[source]¶ Return a DataFrame for an entity in model instance.
Parameters: - instance – a Pyomo ConcreteModel instance
- name – name of a Set, Param, Var, Constraint or Objective
Returns: a single-columned Pandas DataFrame with domain as index
-
get_entities
(instance, names)[source]¶ Return one DataFrame with entities in columns and a common index.
Works only on entities that share a common domain (set or set_tuple), which is used as index of the returned DataFrame.
Parameters: - instance – a Pyomo ConcreteModel instance
- names – list of entity names (as returned by list_entities)
Returns: a Pandas DataFrame with entities as columns and domains as index
-
list_entities
(instance, entity_type)[source]¶ Return list of sets, params, variables, constraints or objectives.
Parameters: - instance – a Pyomo ConcreteModel object
- entity_type – “set”, “par”, “var”, “con” or “obj”
Returns: DataFrame of entities
Example:
>>> data = read_excel('data-example.xlsx') >>> model = create_model(data, vertex, edge) >>> list_entities(model, 'obj') Name obj minimize(cost = sum of all cost types) [] [1 rows x 2 columns]
-
get_onset_names
(entity)[source]¶ Get onset names of model entity Example:
vertex, edge = create_square_grid() data = read_excel('data-example.xlsx') model = create_model(data, vertex, edge) get_onset_names(model.hub)
rivus.graph¶
Comparison of the common graph analysis tools:
NetworkX (preferred):
- + /- Pure python implementation.
- + Widely used and tested.
- + Docs are quite good.
- + Easy (platform independent) installation
- - Slower than igraph (and graph-tools)
python-igraph (fall-back):
- + C based with python wrappers.
- + Mature library package.
- + Included for speed and so for scalability.
- × Docs are OK.
- - Windows install can be somewhat tedious (with unofficial wheel files). But it works.
graph-tools: (eventually added in the future, if there is reeeaaly big need for efficiency..)
- + Self proclaimed: fastest in graph analyses
- - Not really windows user friendly (docker install should be tested)
These all facilitate pretty advanced graph theoretical analysis. Moreover, the file export functions of the used libraries were bridged through the to_graph
module. Preferred file format is .gml
which is supported by all common graph analysis tools. As such, specialized, stand-alone tools for graph visualisation and analysis can be used. E.g. Gephi with its exceptional geolayout plug-in can be of tremendous help for deeper graph visualization and analysis.
to_graph¶
Functions to convert tabular data to popular python graph structures
-
to_igraph
(vdf, edf, pmax, comms=None, peak=None, save_dir=None, ext='gml')[source]¶ Convert Data from (Geo)DataFrames to python-igraph’s Graph class Each commodity gets its own graph. Weights are derived from built capacity.
Parameters: - vdf ([Geo]DataFrame) – Holding Vertex Data id=Vertex and Commodity Sources as columns
- edf ([Geo]DataFrame) – Holding (V1,V2) Multi-indexed Edge data To be sure, that all edges are created.
- pmax (DataFrame) – Commodities as columns with max capacity per edge returned by rivus.get_constants()
- comms (iterable, optional) – Names of the commodities from which we build the graphs. (Each as separate graph.) If omitted, the columns of pmax will be used.
- peak (DataFrame, optional) – Commodities as columns with demands in t_peak time-step. Calculated in main.rivus
- save_dir (path string, optional) – Path to a dir to save graphs as ext Path preferably constructed using the os.path module. If dir does not exit yet, it will be created.
- ext (str, optional) – Description
- (string) file extension, supported by igraph.save() (ext) – If not one of the following, the default ‘gml’ will be applied. ‘adjacency’, ‘dimacs’, ‘dot’, ‘graphviz’, ‘edgelist’, ‘edges’, ‘edge’, ‘gml’, ‘graphml’, ‘graphmlz’, ‘gw’, ‘leda’, ‘lgl’, ‘lgr’, ‘ncol’, ‘net’, ‘pajek’, ‘pickle’, ‘picklez’, ‘svg’
Returns: list – List of igraph.Graph objects in order of
comms
. Graphs are undirected and weighted.Example
_, pmax, _, _ = get_constants(prob) graphs = to_igraph(vertex, edge, pmax, ['Gas', 'Heat'])
-
to_nx
(vdf, edf, pmax, comms=None, save_dir=None)[source]¶ Convert to networkx graph representation
Parameters: - vdf ([Geo]DataFrame) – Holding Vertex Data id=Vertex and Commodity Sources as columns
- edf ([Geo]DataFrame) – Holding (V1,V2) Multi-indexed Edge data To be sure, that all edges are created.
- pmax (DataFrame) – Commodities as columns with max capacity per edge returned by rivus.get_constants()
- comms (iterable, optional) – Names of the commodities from which we build the graphs. (Each as separate graph.) If omitted, the columns of pmax will be used.
- save_dir (path string, optional) – Path to a dir to save graphs as GML. Path preferably constructed using the os.path module If dir does not exit yet, it will be created.
Returns: list – nx_graph objects in accordance with input comms or all commodities found in pmax.columns
Example
_, pmax, _, _ = get_constants(prob) graphs = to_nx(vertex, edge, pmax, ['Gas', 'Heat'])
Note
nx.from_pandas_dataframe()
was also investigated for conversion, but it is a bit slower and does not improve code quality in my opinion.
analysis¶
Functions to hold dedicated analysis runs on the graph objects. networkx is the de-facto graph package, but igraph compatibility is also eligible.
-
minimal_graph_anal
(graphs, calc_spanning=True, graph_package='NX')[source]¶ Showcase interoperable connectivity analysis.
Parameters: - graphs (list) – networkx or igraph Graph objects. Awaited is the resulting ITERABLE of rivus.graph.to_graph functions.
- calc_spanning (bool, optional) – Default: True, sets whether to investigate: Is the graph of the built commodity also a minimal spanning tree of the street network?
- graph_package (str, optional) – Default: ‘NX’, Accepted: ‘NX’ or ‘IGRAPH’. To ease the decision of which package is used.
Returns: list of dicts per graph –
- commodity
- is_connected
- connected_components (number of them)
- is_minimal (if
calc_spanning
is True)
rivus.gridder¶
The birth of this module originates to the intention to regard the linear optimization model as a natural phenomenon. As usual approach in natural sciences, we abstract the specific question in focus, removing the “noise” of real-world data and homogenize the otherwise heterogeneous input data.
After gaining understanding of the highly symmetric model, the noise and asymmetries can be added back in an iterative process. Thus testing the validity of our findings.
As the first approach, a symmetric grid generator is implemented, which can be highly parametrized and can create input for create_model()
only in few lines of code.
Moreover, the possibility to have an input generator integrated into rivus
itself has proven itself useful in many ways. Testing the implemented paradigms can be more intuitive in a symmetric environment, and the ability to rapidly showcase little optimization projects can serve as a demonstration tool accompanying relevant lectures.
Note
A highly symmetric square grid may seem far-fetched from real-life street structures. However, remember the grid street plan which has been around since the Greeks and is to be found all over the world. So, it is maybe not such a bad starting point as considered it may seem at the first glance.
Short example set of cities Google Maps Set.
create_grid¶
-
create_square_grid
(origo_latlon=(48.26739, 11.66842), num_edge_x=1, num_edge_y=None, dx=100, dy=None, noise_prop=0.0, epsg=None, match=0)[source]¶ Create chessboard grid with edges and vertices on WGS84 suface with vincenty distance calculation lat ~ x, lon ~ y
Parameters: - origo_latlon (tuple, optional) – WGS84 latlon coordinates of the bottom left grid point defaults to some the TUM-ENS dep. ;]
- num_edge_x (int, optional) – how many edges horizontally
- num_edge_y (None, optional) – How many edgey vertically
- dx (int, optional) – length of the horizontal edges (in meters)
- dy (None, optional) – length of the vertical edges (in meters)
- noise_prop (float, optional) – 0.0 to MAX_NOISE (< 1.0) missplacement radius relative to dx and dy.
- epsg (int, optional) – If a valid epsg code which is supported py pyproy, the coordinates are calculated in the carthesian UTM CRS and then transformed into epsg4326 (latlon). If None or omitted, then the coordinates are calculated directly in epsg4326 with vincenty’s formula for distance and the grid lines up with the North and East directions
- match (enumerated values, optional) –
- 0 - vertices and edges are matched by the logic of generation
- (faster as less calculation is needed.)
- 1 - matching is done geographicaly
- with pandashp helper (slower, but flexible)
Returns: list of GeoDataFrames –
- vertices : with [geometry, Vertex] columns
- edges : with [geometry, Edge, Vertex1, Vertex2] columns
Note
Sequence of IDs: From buttom left to upper right. From row to row. From left to right.
bearing 0 (6)══04══(7)══05══(8) ║ ║ ║ 7 9 11 ║ ║ ║ (3)══02══(4)══03══(4) ^ ║ ║ ║ (y) 6 8 10 L ║ ║ ║ A (0)══00══(1)══01══(2) T LON (x) -> bearing 90
Raises: ValueError
– Not supported epsg number
-
get_source_candidates
(vdf, dim_x, dim_y, logic='sym')[source]¶ Calculate the set of indexes of the vertices, which are worth testing as source vertex in a single commodity case. A square grid is assumed. “Worth” means: The minimal set of vertices which cover the main symmetrical positions.
Parameters: - vdf (pandas DataFrame) – The vertex frame. (Created by create_square_grid())
- dim_x (int) – Number of vertices along the x axis.
- dim_y (int) – Number of vertices along the y axis.
- logic (str, optional default='sym') –
what kind or source candidates are looked for.
- sym - Minimal(ish) set of vertices based on symmetry.
- E.g. here the indices marked with * are selected.
18, 19, 20, 21, 22, 23 12, 13, 14, 15, 16, 17 *6, *7, *8, 9, 10, 11 *0, *1, *2, 3, 4, 5
- extrema - Pairs of vertices possibly further away from each other.
- Say: combination of the corners. 0: diagonal (0-23) 1: x-edge (0-5) 2: y-edge (0-18) if x-y have different lengths
- center - One corner and one center-ish ID
Returns: List of different dimensions –
- smy : 1D list [1,2,6,7,8]
- extrema, center : 2D list - list of lists [[0,23],[0,5],[0,18]]
Raises: ValueError
– Unsupported source vertex calculation logic
extend_grid¶
-
extend_edge_data
(edge_df, sorts=None, inits=None, strat='equal', strat_param=None)[source]¶ Add demand data to the edges in a (Geo)DataFrame
Parameters: - edge_df ((Geo)DataFrame) – edge dataframe to be extended
- sorts (list of str, optional) – The names of new columns (extensions) Defaults to [‘residential’]
- inits (list of int/float , optional) – The parameter values, matching to sorts argument. Defaults to [1000] for each sort.
- strat (str, optional) – TODO now only ‘equal’ has an effect How the data values will be created + ‘equal’ - all edge demand is the same + ‘linear’ - linearly decreasing + ‘exp’ - exponentially decreasing + ‘manual’ - provide mapper in strat_param
- strat_param (optional) – TODO not implemented yet Parameter for linear | exp | manual strategies. + ‘equal’ - None - no effect + ‘linear’ - minimum (lowest demand) + ‘exp’ - minimum (lowest demand) + ‘manual’ - function/dict to fetch value per edge
Example
sorts = ('residential', 'other') inits = (1000, 800) extend_edge_data(edge, sorts=sorts, inits=inits)
Raises: ValueError
– If inputs differ from awaited
-
vert_init_commodities
(vertex_df, commodities, sources=None, inplace=True)[source]¶ Add commodity columns to the vertex DataFrame with zeros to vertices without commodity source and source capacity at the vertices provided by sources.
Parameters: - vertex_df ((Geo)DataFrame) – vertex dataframe input
- commodities (list of str) – Like (‘Elec’, ‘Gas’, ‘Heat’)
- sources (list of tuples, optional) – Init the source nodes. Tuple form:(Commodity, Index, Value)
- inplace (Boolean, default: True) – If False, vertex_df is not changed and the result is returned.
Returns: None or DataFrame – DataFrame if inplace == False
Raises: ValueError
– If parameters differ from awaitedExample
comms = ('Elec', 'Gas') sources = [('Elec', 0, 1000), ('Gas', 1, 500)] vert_init_commodities(vert, comms, sources)
rivus.io¶
rivus.db¶
To advocate the possibilities provided by a good database connection, a throughout description of the set-up process is documented in rivus-db. There you can find help from the entry level (install, create database) to more advanced topics (queries, data archive).
In this module presents a convenient way to interact with your PostgreSQL database.
Store example
from sqlalchemy import create_engine
from rivus.io import db as rdb
engine = create_engine('postgresql://postgres:pass@localhost/rivus')
# ...
# Modelling, Solving, Analysing
# ...
this_run = dict(comment='testing graph table and features with networx',
profiler=profile_log)
rdb.store(engine, rivus_model, run_data=run_dict)
Import example
from sqlalchemy import create_engine
from rivus.io import db as rdb
from rivus.main.rivus import create_model
engine = create_engine('postgresql://postgres:pass@localhost/rivus')
run_id = 4242
data_dfs = ['process', 'commodity', 'process_commodity', 'time', 'area_demand']
data = {df_name: rdb.df_from_table(engine, df_name, run_id)
for df_name in data_dfs}
vertex = rdb.df_from_table(engine, 'vertex', run_id)
edge = rdb.df_from_table(engine, 'edge', run_id)
prob = create_model(data, vertex, edge, hub_only_in_edge=False)
Example queries with results and short descriptions are part of the separate documentation.
-
df_from_table
(engine, fname, run_id)[source]¶ Extract data form the database into a dataframe in a form, that is common during the rivus work-flow.
Implemented DataFrames:
rivus_model.params[] dataframes:
- process
- commodity
- process_commodity
- edge
- vertex
- time
- area_demand
get_timeseries dataframes:
- source
get_constants dataframes:
- cost
- pmax
- kappa_hub
- kappa_process
Parameters: - engine (sqlalchemy engine whit psycopg2 driver) – For managing connection to the DB.
- fname (str) – One of the implemented dataframes. (See summary.)
- run_id (int) – run_id of an initialized run row in the DB. You could query the run table for e.g. start date, or join it vertex table and execute a geographical query and get the run_id(s) you want to work with
Returns: DataFrame or Series – depending on the data’s dimensions. Only cost returns a Series to be consequent with get_constants.
-
init_run
(engine, runner='Havasi', start_ts=None, status='prepared', outcome='not_run', comment=None, plot_dict=None, profiler=None)[source]¶ Initialize the run table with basic info.
Parameters: - engine (sqlalchemy engine whit psycopg2 driver) – For managing connection to the DB.
- runner (str, optional) – Person’s name/identifier who created(executed) the data(process).
- start_ts (datetime.datetime, optional) – Timezone-less datetime object. If omitted, .now() will be used.
- status (str, optional) – One of the following strings: | ‘prepared’ (default) | ‘run’ | ‘error’
- outcome (str, optional) – One of the following strings: | ‘not_run’ (default) | ‘optimum’ | ‘optimum_not_found’ | ‘error’
- comment (str, optional) – Any text based comment. (No length limit.)
- plot_dict (dict, optional) – Dictionary returned by the rivus.io.plot.fig3d function.
- profiler (pandas.Series, optional) – Series containing profiled process name and execution time pairs. Execution time is measured in seconds
Returns: int – run_id of the initialized run row in the DB.
-
purge_run
(engine, run_id)[source]¶ Delete all rows related to run_id across all tables. This is not a throughout reliable function, and can do some harm. Use it with caution, and at your own risk!
Parameters: - engine (sqlalchemy engine whit psycopg2 driver) – For managing connection to the DB.
- run_id (int) – run_id of the initialized run row in the DB. Used to identify related data to be removed: directly (table has run_in as FK) and indirectly (table has FK of an Entity with run_id FK)
Returns: None
-
store
(engine, prob, run_id=None, graph_results=None, run_data=None, time_series=None, constants=None)[source]¶ Store I/O plus extras of a rivus model into a postgres DB.
Parameters: - engine (sqlalchemy engine whit psycopg2 driver) – For managing connection to the DB.
- prob (pyomo ConcreteModel) – Created by rivus.create_model()
- run_id (int, optional) – run_id of an initialized run row in the DB. If omitted: init_run() will be called with run_data.
- graph_results (iterable, optional) – Results of the graph analysis. Each graph should have its own dict. For implemented result keys see _handle_graph. E.g. [{‘is_connected’:True, ‘is_minimal’:True}, {‘is_connected’:True}]
- run_data (dict, optional) – Keyword arguments to be passed to init_run(). runner, start_ts, status, outcome, comment, plot_dict, profiler
- time_series (None, optional) – TODO If already present at function call, this could save time.
- constants (None, optional) – TODO If already present at function call, this could save time.
Returns: None
Raises: Exception caught during data export.
rivus.plot¶
Interactive 3D data visualization! See live example here (May take a while to load.)
Plotly has a great documentation and an extensive examples library.
It is available also available as a JavaScript library, which can help when a web-app GUI is added to rivus. (Client-side visualization.)
To ensure interoperability, it thinks in dictionaries (JSONs). This gives a greater flexibility then e.g. the API of matplotlib.
Adding extra hove-over information (line length, capacity, you-name-it) is also highly flexible.
The structure can be explained easily:
data = cap_layers + hub_layer + markers
fig = dict(data=data, layout=layout)
where cap_layers
, hub_layer
and markers
simply lists of dictionaries are, which dictionaries have the key-value pairs of the Scatter3d structure (class).
We use raw dicts instead of Plotly’s “classes” because they are mainly the same, but much faster.
Still, Loading the plot can take a while if there are a lot of elements to render. (For each edge we have a scatter3d dict in the data
list, which are grouped together by the same legendgroup
key value.)
The plot consists of layers, stacked upon each other. Each of these represent a commodity. All of the edges are shown in each layer, but if in one no carrier was built, it is displayed dashed. If the edge is stroked through, some amount of capacity was built out there. The width of the edges are in proportion with that amount.
Diamond shapes represent the sources in the vertices.
Vertical lines show processes (commodity conversions).
All of the elements can be toggled with the help of the menu in the upper right corner.
Note
As the legends (with which you can turn off/on the layers) are generated from the first elements per legend-groups in the data list, there are now dummies as first ones to ensure a nicer look.
-
fig3d
(prob, comms=None, linescale=1.0, use_hubs=False, hub_opac=0.55, dz=5, layout=None, verbose=False)[source]¶ Generate 3D representation of the rivus results using plotly
Parameters: - prob (rivus_archive) – A rivus model (later extract of it)
- comms (None, optional) – list/ndarray of commodity names to plot, Order: [‘C1’, ‘C2’, ‘C3’] -> Bottom: C1, Top: C3
- linescale (float, optional) – A multiplier to get proportionally thicker lines.
- use_hubs (bool, optional) – Switch to depict hub processes.
- hub_opac (float, optional) – 0-1 opacity param.
- dz (number, optional) – Distance between layers along ‘z’ axis .
- layout (None, optional) – A plotly layout dict to overwrite default.
- verbose (bool, optional) – To print out progress and the time it took.
Example
import plotly.offline as po fig = fig3d(prob, ['Gas', 'Heat', 'Elec'], hub_opac=0.55, linescale=7) # for static image # po.plot(fig, filename='plotly-game.html', image='png') po.plot(fig, filename='plotly-game.html')
Returns: plotly compatible figure *dict (in plotly everything is kinda a dict.)*
rivus.utils¶
prerun¶
Collection of small rivus related helper functions
In use to avoid multiple solutions of the same task, like:
- Setting up the solver.
- Todo: Create needed directories
-
setup_solver
(optim, logfile='solver.log', guro_time_lim=12000, guro_mip_focus=2, guro_mip_gap=0.001, guro_threads=None, log_to_console=True)[source]¶ Change solver options to custom values.
Parameters: - optim (SolverFactory) – pyomo Solver object from pyomo.opt.base
- logfile (str, optional) – default=’solver.log’ Name (Path) to the logfile
- guro_time_lim (int, optional) – unit is seconds | default=12000
- guro_mip_focus (int, optional) – default=2 1=feasible, 2=optimal, 3=bound
- guro_mip_gap (float, optional) – our default=.001 (gurobi’s default: 1e-4)
- guro_threads (None, optional) – parallel solver tasks | default=None If None, no Threads parameter is set (gurobi takes <=CPU_count threads automatically) If greater than CPU_count then it is threshold to CPU_count If less than CPU_count then Thread is set with the parameter
- log_to_console (bool, optional) – Description
- (Boolean, optional) If False, the output of the solver (log_to_console) – is not piped to the stdout.
Example
optim = SolverFactory('glpk') optim = setup_solver(optim, logfile=log_filename)
Returns: SolverFactory – With applied modifications
notify¶
-
email_me
(message, sender, send_pass, recipient, smtp_addr, smtp_port, subject='[rivus][notification]')[source]¶ Send notification message through email server.
Parameters: - message (str) – Body of the e-mail
- sender (str) – The e-mail account through which the email will be sent. E.g. tum.robot@gmail.com
- send_pass (str) – Password of sender. Hopefully read from a file, which is not added to Git…
- recipient (str) – The e-mail account of you, where you want to get the notification.
- smtp_addr (str) – SMTP Address. Like “smtp.gmail.com”
- smtp_port (int) – SMTP Port. Like 587
- subject (str, optional) – The subject of the mail…
Returns: integer – 0 - if run through without exception -1 - if encountered with a problem (mainly for unittest)
Example
email_setup = { 'sender': config['email']['s_user'], 'send_pass': config['email']['s_pass'], 'recipient': config['email']['r_user'], 'smtp_addr': config['email']['smtp_addr'], 'smtp_port': config['email']['smtp_port']} ... except Exception as solve_error: sub = run_summary + '[rivus][solve-error]' email_me(solve_error, subject=sub, **email_setup) # or with traceback: except Exception as plot_error: err_tb = tb.format_exception( None, plot_error, plot_error.__traceback__) sub = run_summary + '[rivus][plot-error]' email_me(err_tb, subject=sub, **email_setup)
runmany¶
Functions are collected here, which can be useful in case of a massive runs involving analysis of a broader parameter-space.
-
parameter_range
(data_df, index, column, lim_lo=None, lim_up=None, step=None, zero_root=None)[source]¶ Yield values of the parameter in a given range
Parameters: - data_df (DataFrame) – Original data frame, where the target parameter can be found.
- index (valid pandas DataFrame row label) – DataFrame .loc parameter to locate the parameter value. E.g.: [‘Gas power plant’, ‘CO2’, ‘Out’] or ‘Gas’
- column (str) – Label of the column, where the parameter is. E.g.: ‘ratio’ or ‘cap-max’
- lim_lo (None, optional) – Proportional parameter. If omitted, 90% of the original.
- lim_up (None, optional) – Proportional parameter. If omitted 110% of the original.
- step (None, optional) – Proportional parameter. The difference between two following yielded values.
- zero_root (None, optional) – If the selected parameter is 0, then the default method using proportions will fail. Use this value to set the root for the parameter range.
Yields: DataFrame – A modified version of xls[df_name]
Example
data = read_excel(data_spreadsheet) interesting_parameters = [ {'df_name': 'commodity', 'args': {'index': 'Heat', 'column': 'cost-inv-fix', 'lim_lo': 0.5, 'lim_up': 1.6, 'step': 0.5}}, {'df_name': 'commodity', 'args': {'index': 'Heat', 'column': 'cost-fix', 'lim_lo': 0.5, 'lim_up': 1.6, 'step': 0.5}}] for param in interesting_parameters : sheet = data[param['df_name']] param_path = param['args'] for variant in parameter_range(sheet, **param_path): ...
pandashp¶
pandashp: read/write shapefiles to/from special DataFrames
Offers two functions read_shp and write_shp that convert ESRI shapefiles to pandas DataFrames that can be manipulated at will and then written back to shapefiles. Opens up data manipulation capabilities beyond a simple GIS field calculator.
- Usage:
- import pandashp as pdshp # calculate population density from shapefile of cities (stupid, I know) cities = pdshp.read_shp(‘cities_germany_projected’) cities[‘popdens’] = cities[‘population’] / cities[‘area’] pdshp.write_shp(cities, ‘cities_germany_projected_popdens’)
-
find_closest_edge
(polygons, edges, to_attr='index', column='nearest')[source]¶ Find closest edge for centroid of polygons.
Parameters: - polygons – a pandas DataFrame with geometry column of Polygons
- edges – a pandas DataFrame with geometry column of LineStrings
- to_attr – a column name in DataFrame edges (default: index)
- column – a column name to be added/overwrite in DataFrame polygons with the value of column to_attr from the nearest edge in edges
Returns: a list of LineStrings connecting polygons’ centroids with the nearest point in in edges. Side effect: polygons recieves new column with the attribute value of nearest edge. Warning: if column exists, it is overwritten.
-
match_vertices_and_edges
(vertices, edges, vertex_cols=('Vertex1', 'Vertex2'))[source]¶ Adds unique IDs to vertices and corresponding edges.
Identifies, which nodes coincide with the endpoints of edges and creates matching IDs for matching points, thus creating a node-edge graph whose edges are encoded purely by node ID pairs. The optional argument vertex_cols specifies which DataFrame columns of edges are added, default is ‘Vertex1’ and ‘Vertex2’.
Parameters: - vertices – pandas DataFrame with geometry column of type Point
- edges – pandas DataFrame with geometry column of type LineString
- vertex_cols – tuple of 2 strings for the IDs numbers
Returns: Nothing, the mathing IDs are added to the columns vertex_cols in argument edges
-
read_shp
(filename)[source]¶ Read shapefile to dataframe w/ geometry.
Parameters: filename – ESRI shapefile name to be read (without .shp extension) Returns: pandas DataFrame with column geometry, containing individual shapely Geometry objects (i.e. Point, LineString, Polygon) depending on the shapefiles original shape type
-
write_shp
(filename, dataframe, write_index=True)[source]¶ Write dataframe w/ geometry to shapefile.
Parameters: - filename – ESRI shapefile name to be written (without .shp extension)
- dataframe – a pandas DataFrame with column geometry and homogenous shape types (Point, LineString, or Polygon)
- write_index – add index as column to attribute tabel (default: true)
Returns: Nothing.
rivus.test¶
Write tests to every function where there are clearly definable input(s) and output(s).
Enlighten the main logic of the test here if it is not trivial.
test_db¶
-
class
RivusDBTest
(methodName='runTest')[source]¶ -
test_df_insert_query
()[source]¶ Are the stored dataframes and the retrieved ones identical?
- Comparison form of frames is after create_model. (index is set)
- Comparison form expects that input dataframes only have meaningful columns. (See pull request #23)
- Only implemented dataframes are tested.
Note
Requires a
config.json
file in the root of rivus-repo with the database credentials. For Example:{ "db" : { "user" : "postgres", "pass" : "postgres", "host" : "localhost", "base" : "rivus" } }
-
test_utils¶
-
class
RivusUtilsTest
(methodName='runTest')[source]¶ -
test_email_notification
()[source]¶ It only can test, whether the notification function run trhrough successfully.
Can be useful for quick testing the email parameters in the config file
Note
Requires a
config.json
file in the root of rivus-repo with the database credentials. For Example:{ "email" : { "s_user" : "robot.mail@gmail.com", "s_pass" : "TheAnswerIs42!", "r_user" : "my.mail@gmail.com", "smpt_addr" : "smtp.gmail.com", "smpt_port" : "587" } }
-